rrudb 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/LICENSE.txt +22 -0
- data/README.md +26 -0
- data/examples/example.rb +39 -0
- data/ext/rudb/NuDB/include/nudb/CMakeLists.txt +104 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/basic_seconds_clock.hpp +200 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/chrono_util.hpp +58 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/fail_file.hpp +343 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/temp_dir.hpp +73 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/test_store.hpp +451 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/xor_shift_engine.hpp +105 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/util.hpp +288 -0
- data/ext/rudb/NuDB/include/nudb/basic_store.hpp +461 -0
- data/ext/rudb/NuDB/include/nudb/concepts.hpp +205 -0
- data/ext/rudb/NuDB/include/nudb/context.hpp +144 -0
- data/ext/rudb/NuDB/include/nudb/create.hpp +117 -0
- data/ext/rudb/NuDB/include/nudb/detail/arena.hpp +296 -0
- data/ext/rudb/NuDB/include/nudb/detail/bucket.hpp +473 -0
- data/ext/rudb/NuDB/include/nudb/detail/buffer.hpp +86 -0
- data/ext/rudb/NuDB/include/nudb/detail/bulkio.hpp +196 -0
- data/ext/rudb/NuDB/include/nudb/detail/cache.hpp +236 -0
- data/ext/rudb/NuDB/include/nudb/detail/endian.hpp +93 -0
- data/ext/rudb/NuDB/include/nudb/detail/field.hpp +265 -0
- data/ext/rudb/NuDB/include/nudb/detail/format.hpp +630 -0
- data/ext/rudb/NuDB/include/nudb/detail/gentex.hpp +259 -0
- data/ext/rudb/NuDB/include/nudb/detail/mutex.hpp +26 -0
- data/ext/rudb/NuDB/include/nudb/detail/pool.hpp +243 -0
- data/ext/rudb/NuDB/include/nudb/detail/store_base.hpp +45 -0
- data/ext/rudb/NuDB/include/nudb/detail/stream.hpp +149 -0
- data/ext/rudb/NuDB/include/nudb/detail/xxhash.hpp +328 -0
- data/ext/rudb/NuDB/include/nudb/error.hpp +257 -0
- data/ext/rudb/NuDB/include/nudb/file.hpp +55 -0
- data/ext/rudb/NuDB/include/nudb/impl/basic_store.ipp +785 -0
- data/ext/rudb/NuDB/include/nudb/impl/context.ipp +241 -0
- data/ext/rudb/NuDB/include/nudb/impl/create.ipp +163 -0
- data/ext/rudb/NuDB/include/nudb/impl/error.ipp +175 -0
- data/ext/rudb/NuDB/include/nudb/impl/posix_file.ipp +248 -0
- data/ext/rudb/NuDB/include/nudb/impl/recover.ipp +209 -0
- data/ext/rudb/NuDB/include/nudb/impl/rekey.ipp +248 -0
- data/ext/rudb/NuDB/include/nudb/impl/verify.ipp +634 -0
- data/ext/rudb/NuDB/include/nudb/impl/visit.ipp +96 -0
- data/ext/rudb/NuDB/include/nudb/impl/win32_file.ipp +264 -0
- data/ext/rudb/NuDB/include/nudb/native_file.hpp +76 -0
- data/ext/rudb/NuDB/include/nudb/nudb.hpp +27 -0
- data/ext/rudb/NuDB/include/nudb/posix_file.hpp +228 -0
- data/ext/rudb/NuDB/include/nudb/progress.hpp +32 -0
- data/ext/rudb/NuDB/include/nudb/recover.hpp +73 -0
- data/ext/rudb/NuDB/include/nudb/rekey.hpp +110 -0
- data/ext/rudb/NuDB/include/nudb/store.hpp +27 -0
- data/ext/rudb/NuDB/include/nudb/type_traits.hpp +63 -0
- data/ext/rudb/NuDB/include/nudb/verify.hpp +200 -0
- data/ext/rudb/NuDB/include/nudb/version.hpp +21 -0
- data/ext/rudb/NuDB/include/nudb/visit.hpp +63 -0
- data/ext/rudb/NuDB/include/nudb/win32_file.hpp +246 -0
- data/ext/rudb/NuDB/include/nudb/xxhasher.hpp +45 -0
- data/ext/rudb/extconf.rb +12 -0
- data/ext/rudb/rudb.cpp +234 -0
- data/lib/rudb/version.rb +3 -0
- data/lib/rudb.rb +1 -0
- metadata +104 -0
@@ -0,0 +1,473 @@
|
|
1
|
+
//
|
2
|
+
// Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
3
|
+
//
|
4
|
+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
5
|
+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
6
|
+
//
|
7
|
+
|
8
|
+
#ifndef NUDB_DETAIL_BUCKET_HPP
|
9
|
+
#define NUDB_DETAIL_BUCKET_HPP
|
10
|
+
|
11
|
+
#include <nudb/error.hpp>
|
12
|
+
#include <nudb/type_traits.hpp>
|
13
|
+
#include <nudb/detail/bulkio.hpp>
|
14
|
+
#include <nudb/detail/field.hpp>
|
15
|
+
#include <nudb/detail/format.hpp>
|
16
|
+
#include <boost/assert.hpp>
|
17
|
+
#include <cstddef>
|
18
|
+
#include <cstdint>
|
19
|
+
#include <cstring>
|
20
|
+
|
21
|
+
namespace nudb {
|
22
|
+
namespace detail {
|
23
|
+
|
24
|
+
// Returns bucket index given hash, buckets, and modulus
|
25
|
+
//
|
26
|
+
inline
|
27
|
+
nbuck_t
|
28
|
+
bucket_index(nhash_t h, nbuck_t buckets, std::uint64_t modulus)
|
29
|
+
{
|
30
|
+
BOOST_ASSERT(modulus <= 0x100000000ULL);
|
31
|
+
auto n = h % modulus;
|
32
|
+
if(n >= buckets)
|
33
|
+
n -= modulus / 2;
|
34
|
+
return static_cast<nbuck_t>(n);
|
35
|
+
}
|
36
|
+
|
37
|
+
//------------------------------------------------------------------------------
|
38
|
+
|
39
|
+
// Tag for constructing empty buckets
|
40
|
+
struct empty_t
|
41
|
+
{
|
42
|
+
constexpr empty_t() = default;
|
43
|
+
};
|
44
|
+
|
45
|
+
static empty_t constexpr empty{};
|
46
|
+
|
47
|
+
// Allows inspection and manipulation of bucket blobs in memory
|
48
|
+
template<class = void>
|
49
|
+
class bucket_t
|
50
|
+
{
|
51
|
+
nsize_t block_size_; // Size of a key file block
|
52
|
+
nkey_t size_; // Current key count
|
53
|
+
noff_t spill_; // Offset of next spill record or 0
|
54
|
+
std::uint8_t* p_; // Pointer to the bucket blob
|
55
|
+
|
56
|
+
public:
|
57
|
+
struct value_type
|
58
|
+
{
|
59
|
+
noff_t offset;
|
60
|
+
nhash_t hash;
|
61
|
+
nsize_t size;
|
62
|
+
};
|
63
|
+
|
64
|
+
bucket_t() = default;
|
65
|
+
bucket_t(bucket_t const&) = default;
|
66
|
+
bucket_t& operator=(bucket_t const&) = default;
|
67
|
+
|
68
|
+
bucket_t(nsize_t block_size, void* p);
|
69
|
+
|
70
|
+
bucket_t(nsize_t block_size, void* p, empty_t);
|
71
|
+
|
72
|
+
nsize_t
|
73
|
+
block_size() const
|
74
|
+
{
|
75
|
+
return block_size_;
|
76
|
+
}
|
77
|
+
|
78
|
+
// Serialized bucket size.
|
79
|
+
// Excludes empty
|
80
|
+
nsize_t
|
81
|
+
actual_size() const
|
82
|
+
{
|
83
|
+
return bucket_size(size_);
|
84
|
+
}
|
85
|
+
|
86
|
+
bool
|
87
|
+
empty() const
|
88
|
+
{
|
89
|
+
return size_ == 0;
|
90
|
+
}
|
91
|
+
|
92
|
+
bool
|
93
|
+
full() const
|
94
|
+
{
|
95
|
+
return size_ >=
|
96
|
+
detail::bucket_capacity(block_size_);
|
97
|
+
}
|
98
|
+
|
99
|
+
nkey_t
|
100
|
+
size() const
|
101
|
+
{
|
102
|
+
return size_;
|
103
|
+
}
|
104
|
+
|
105
|
+
// Returns offset of next spill record or 0
|
106
|
+
//
|
107
|
+
noff_t
|
108
|
+
spill() const
|
109
|
+
{
|
110
|
+
return spill_;
|
111
|
+
}
|
112
|
+
|
113
|
+
// Set offset of next spill record
|
114
|
+
//
|
115
|
+
void
|
116
|
+
spill(noff_t offset);
|
117
|
+
|
118
|
+
// Clear contents of the bucket
|
119
|
+
//
|
120
|
+
void
|
121
|
+
clear();
|
122
|
+
|
123
|
+
// Returns the record for a key
|
124
|
+
// entry without bounds checking.
|
125
|
+
//
|
126
|
+
value_type const
|
127
|
+
at(nkey_t i) const;
|
128
|
+
|
129
|
+
value_type const
|
130
|
+
operator[](nkey_t i) const
|
131
|
+
{
|
132
|
+
return at(i);
|
133
|
+
}
|
134
|
+
|
135
|
+
// Returns index of entry with prefix
|
136
|
+
// equal to or greater than the given prefix.
|
137
|
+
//
|
138
|
+
nkey_t
|
139
|
+
lower_bound(nhash_t h) const;
|
140
|
+
|
141
|
+
void
|
142
|
+
insert(noff_t offset, nsize_t size, nhash_t h);
|
143
|
+
|
144
|
+
// Erase an element by index
|
145
|
+
//
|
146
|
+
void
|
147
|
+
erase(nkey_t i);
|
148
|
+
|
149
|
+
// Read a full bucket from the
|
150
|
+
// file at the specified offset.
|
151
|
+
//
|
152
|
+
template<class File>
|
153
|
+
void
|
154
|
+
read(File& f, noff_t, error_code& ec);
|
155
|
+
|
156
|
+
// Read a compact bucket
|
157
|
+
//
|
158
|
+
template<class File>
|
159
|
+
void
|
160
|
+
read(bulk_reader<File>& r, error_code& ec);
|
161
|
+
|
162
|
+
// Write a compact bucket to the stream.
|
163
|
+
// This only writes entries that are not empty.
|
164
|
+
//
|
165
|
+
void
|
166
|
+
write(ostream& os) const;
|
167
|
+
|
168
|
+
// Write a bucket to the file at the specified offset.
|
169
|
+
// The full block_size() bytes are written.
|
170
|
+
//
|
171
|
+
template<class File>
|
172
|
+
void
|
173
|
+
write(File& f,noff_t offset, error_code& ec) const;
|
174
|
+
|
175
|
+
private:
|
176
|
+
// Update size and spill in the blob
|
177
|
+
void
|
178
|
+
update();
|
179
|
+
};
|
180
|
+
|
181
|
+
//------------------------------------------------------------------------------
|
182
|
+
|
183
|
+
template<class _>
|
184
|
+
bucket_t<_>::
|
185
|
+
bucket_t(nsize_t block_size, void* p)
|
186
|
+
: block_size_(block_size)
|
187
|
+
, p_(reinterpret_cast<std::uint8_t*>(p))
|
188
|
+
{
|
189
|
+
// Bucket Record
|
190
|
+
istream is(p_, block_size);
|
191
|
+
detail::read<uint16_t>(is, size_); // Count
|
192
|
+
detail::read<uint48_t>(is, spill_); // Spill
|
193
|
+
}
|
194
|
+
|
195
|
+
template<class _>
|
196
|
+
bucket_t<_>::
|
197
|
+
bucket_t(nsize_t block_size, void* p, empty_t)
|
198
|
+
: block_size_(block_size)
|
199
|
+
, size_(0)
|
200
|
+
, spill_(0)
|
201
|
+
, p_(reinterpret_cast<std::uint8_t*>(p))
|
202
|
+
{
|
203
|
+
clear();
|
204
|
+
}
|
205
|
+
|
206
|
+
template<class _>
|
207
|
+
void
|
208
|
+
bucket_t<_>::
|
209
|
+
spill(noff_t offset)
|
210
|
+
{
|
211
|
+
spill_ = offset;
|
212
|
+
update();
|
213
|
+
}
|
214
|
+
|
215
|
+
template<class _>
|
216
|
+
void
|
217
|
+
bucket_t<_>::clear()
|
218
|
+
{
|
219
|
+
size_ = 0;
|
220
|
+
spill_ = 0;
|
221
|
+
std::memset(p_, 0, block_size_);
|
222
|
+
}
|
223
|
+
|
224
|
+
template<class _>
|
225
|
+
auto
|
226
|
+
bucket_t<_>::
|
227
|
+
at(nkey_t i) const ->
|
228
|
+
value_type const
|
229
|
+
{
|
230
|
+
value_type result;
|
231
|
+
// Bucket Entry
|
232
|
+
auto const w =
|
233
|
+
field<uint48_t>::size + // Offset
|
234
|
+
field<uint48_t>::size + // Size
|
235
|
+
field<f_hash>::size; // Prefix
|
236
|
+
// Bucket Record
|
237
|
+
detail::istream is{p_ +
|
238
|
+
field<std::uint16_t>::size + // Count
|
239
|
+
field<uint48_t>::size + // Spill
|
240
|
+
i * w, w};
|
241
|
+
// Bucket Entry
|
242
|
+
detail::read<uint48_t>(
|
243
|
+
is, result.offset); // Offset
|
244
|
+
detail::read_size48(
|
245
|
+
is, result.size); // Size
|
246
|
+
detail::read<f_hash>(
|
247
|
+
is, result.hash); // Hash
|
248
|
+
return result;
|
249
|
+
}
|
250
|
+
|
251
|
+
template<class _>
|
252
|
+
nkey_t
|
253
|
+
bucket_t<_>::
|
254
|
+
lower_bound(nhash_t h) const
|
255
|
+
{
|
256
|
+
// Bucket Entry
|
257
|
+
auto const w =
|
258
|
+
field<uint48_t>::size + // Offset
|
259
|
+
field<uint48_t>::size + // Size
|
260
|
+
field<f_hash>::size; // Hash
|
261
|
+
// Bucket Record
|
262
|
+
auto const p = p_ +
|
263
|
+
field<std::uint16_t>::size + // Count
|
264
|
+
field<uint48_t>::size + // Spill
|
265
|
+
// Bucket Entry
|
266
|
+
field<uint48_t>::size + // Offset
|
267
|
+
field<uint48_t>::size; // Size
|
268
|
+
nkey_t step;
|
269
|
+
nkey_t first = 0;
|
270
|
+
nkey_t count = size_;
|
271
|
+
while(count > 0)
|
272
|
+
{
|
273
|
+
step = count / 2;
|
274
|
+
nkey_t i = first + step;
|
275
|
+
nhash_t h1;
|
276
|
+
readp<f_hash>(p + i * w, h1);
|
277
|
+
if(h1 < h)
|
278
|
+
{
|
279
|
+
first = i + 1;
|
280
|
+
count -= step + 1;
|
281
|
+
}
|
282
|
+
else
|
283
|
+
{
|
284
|
+
count = step;
|
285
|
+
}
|
286
|
+
}
|
287
|
+
return first;
|
288
|
+
}
|
289
|
+
|
290
|
+
template<class _>
|
291
|
+
void
|
292
|
+
bucket_t<_>::
|
293
|
+
insert(
|
294
|
+
noff_t offset, nsize_t size, nhash_t h)
|
295
|
+
{
|
296
|
+
auto const i = lower_bound(h);
|
297
|
+
// Bucket Record
|
298
|
+
auto const p = p_ +
|
299
|
+
field<
|
300
|
+
std::uint16_t>::size + // Count
|
301
|
+
field<uint48_t>::size; // Spill
|
302
|
+
// Bucket Entry
|
303
|
+
auto const w =
|
304
|
+
field<uint48_t>::size + // Offset
|
305
|
+
field<uint48_t>::size + // Size
|
306
|
+
field<f_hash>::size; // Hash
|
307
|
+
std::memmove(
|
308
|
+
p +(i + 1) * w,
|
309
|
+
p + i * w,
|
310
|
+
(size_ - i) * w);
|
311
|
+
++size_;
|
312
|
+
update();
|
313
|
+
// Bucket Entry
|
314
|
+
ostream os{p + i * w, w};
|
315
|
+
detail::write<uint48_t>(
|
316
|
+
os, offset); // Offset
|
317
|
+
detail::write<uint48_t>(
|
318
|
+
os, size); // Size
|
319
|
+
detail::write<f_hash>(
|
320
|
+
os, h); // Prefix
|
321
|
+
}
|
322
|
+
|
323
|
+
template<class _>
|
324
|
+
void
|
325
|
+
bucket_t<_>::
|
326
|
+
erase(nkey_t i)
|
327
|
+
{
|
328
|
+
// Bucket Record
|
329
|
+
auto const p = p_ +
|
330
|
+
field<std::uint16_t>::size + // Count
|
331
|
+
field<uint48_t>::size; // Spill
|
332
|
+
auto const w =
|
333
|
+
field<uint48_t>::size + // Offset
|
334
|
+
field<uint48_t>::size + // Size
|
335
|
+
field<f_hash>::size; // Hash
|
336
|
+
--size_;
|
337
|
+
if(i < size_)
|
338
|
+
std::memmove(
|
339
|
+
p + i * w,
|
340
|
+
p +(i + 1) * w,
|
341
|
+
(size_ - i) * w);
|
342
|
+
std::memset(p + size_ * w, 0, w);
|
343
|
+
update();
|
344
|
+
}
|
345
|
+
|
346
|
+
template<class _>
|
347
|
+
template<class File>
|
348
|
+
void
|
349
|
+
bucket_t<_>::
|
350
|
+
read(File& f, noff_t offset, error_code& ec)
|
351
|
+
{
|
352
|
+
auto const cap = bucket_capacity(block_size_);
|
353
|
+
// Excludes padding to block size
|
354
|
+
f.read(offset, p_, bucket_size(cap), ec);
|
355
|
+
if(ec)
|
356
|
+
return;
|
357
|
+
istream is{p_, block_size_};
|
358
|
+
detail::read<std::uint16_t>(is, size_); // Count
|
359
|
+
detail::read<uint48_t>(is, spill_); // Spill
|
360
|
+
if(size_ > cap)
|
361
|
+
{
|
362
|
+
ec = error::invalid_bucket_size;
|
363
|
+
return;
|
364
|
+
}
|
365
|
+
}
|
366
|
+
|
367
|
+
template<class _>
|
368
|
+
template<class File>
|
369
|
+
void
|
370
|
+
bucket_t<_>::
|
371
|
+
read(bulk_reader<File>& r, error_code& ec)
|
372
|
+
{
|
373
|
+
// Bucket Record(compact)
|
374
|
+
auto is = r.prepare(
|
375
|
+
detail::field<std::uint16_t>::size +
|
376
|
+
detail::field<uint48_t>::size, ec);
|
377
|
+
if(ec)
|
378
|
+
return;
|
379
|
+
detail::read<std::uint16_t>(is, size_); // Count
|
380
|
+
detail::read<uint48_t>(is, spill_); // Spill
|
381
|
+
update();
|
382
|
+
// Excludes empty bucket entries
|
383
|
+
auto const w = size_ * (
|
384
|
+
field<uint48_t>::size + // Offset
|
385
|
+
field<uint48_t>::size + // Size
|
386
|
+
field<f_hash>::size); // Hash
|
387
|
+
is = r.prepare(w, ec);
|
388
|
+
if(ec)
|
389
|
+
return;
|
390
|
+
std::memcpy(p_ +
|
391
|
+
field<std::uint16_t>::size + // Count
|
392
|
+
field<uint48_t>::size, // Spill
|
393
|
+
is.data(w), w); // Entries
|
394
|
+
}
|
395
|
+
|
396
|
+
template<class _>
|
397
|
+
void
|
398
|
+
bucket_t<_>::
|
399
|
+
write(ostream& os) const
|
400
|
+
{
|
401
|
+
// Does not pad up to the block size. This
|
402
|
+
// is called to write to the data file.
|
403
|
+
auto const size = actual_size();
|
404
|
+
// Bucket Record
|
405
|
+
std::memcpy(os.data(size), p_, size);
|
406
|
+
}
|
407
|
+
|
408
|
+
template<class _>
|
409
|
+
template<class File>
|
410
|
+
void
|
411
|
+
bucket_t<_>::
|
412
|
+
write(File& f, noff_t offset, error_code& ec) const
|
413
|
+
{
|
414
|
+
// Includes zero pad up to the block
|
415
|
+
// size, to make the key file size always
|
416
|
+
// a multiple of the block size.
|
417
|
+
auto const size = actual_size();
|
418
|
+
std::memset(p_ + size, 0, block_size_ - size);
|
419
|
+
// Bucket Record
|
420
|
+
f.write(offset, p_, block_size_, ec);
|
421
|
+
if(ec)
|
422
|
+
return;
|
423
|
+
}
|
424
|
+
|
425
|
+
template<class _>
|
426
|
+
void
|
427
|
+
bucket_t<_>::
|
428
|
+
update()
|
429
|
+
{
|
430
|
+
// Bucket Record
|
431
|
+
ostream os{p_, block_size_};
|
432
|
+
detail::write<std::uint16_t>(os, size_); // Count
|
433
|
+
detail::write<uint48_t>(os, spill_); // Spill
|
434
|
+
}
|
435
|
+
|
436
|
+
using bucket = bucket_t<>;
|
437
|
+
|
438
|
+
//------------------------------------------------------------------------------
|
439
|
+
|
440
|
+
// Spill bucket if full.
|
441
|
+
// The bucket is cleared after it spills.
|
442
|
+
//
|
443
|
+
template<class File>
|
444
|
+
void
|
445
|
+
maybe_spill(
|
446
|
+
bucket& b, bulk_writer<File>& w, error_code& ec)
|
447
|
+
{
|
448
|
+
if(b.full())
|
449
|
+
{
|
450
|
+
// Spill Record
|
451
|
+
auto const offset = w.offset();
|
452
|
+
auto os = w.prepare(
|
453
|
+
field<uint48_t>::size + // Zero
|
454
|
+
field<uint16_t>::size + // Size
|
455
|
+
b.actual_size(), ec);
|
456
|
+
if(ec)
|
457
|
+
return;
|
458
|
+
write<uint48_t>(os, 0ULL); // Zero
|
459
|
+
write<std::uint16_t>(
|
460
|
+
os, b.actual_size()); // Size
|
461
|
+
auto const spill =
|
462
|
+
offset + os.size();
|
463
|
+
b.write(os); // Bucket
|
464
|
+
// Update bucket
|
465
|
+
b.clear();
|
466
|
+
b.spill(spill);
|
467
|
+
}
|
468
|
+
}
|
469
|
+
|
470
|
+
} // detail
|
471
|
+
} // nudb
|
472
|
+
|
473
|
+
#endif
|
@@ -0,0 +1,86 @@
|
|
1
|
+
//
|
2
|
+
// Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
3
|
+
//
|
4
|
+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
5
|
+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
6
|
+
//
|
7
|
+
|
8
|
+
#ifndef NUDB_DETAIL_BUFFER_HPP
|
9
|
+
#define NUDB_DETAIL_BUFFER_HPP
|
10
|
+
|
11
|
+
#include <atomic>
|
12
|
+
#include <cstdint>
|
13
|
+
#include <memory>
|
14
|
+
|
15
|
+
namespace nudb {
|
16
|
+
namespace detail {
|
17
|
+
|
18
|
+
// Simple growable memory buffer
|
19
|
+
class buffer
|
20
|
+
{
|
21
|
+
private:
|
22
|
+
std::size_t size_ = 0;
|
23
|
+
std::unique_ptr<std::uint8_t[]> buf_;
|
24
|
+
|
25
|
+
public:
|
26
|
+
~buffer() = default;
|
27
|
+
buffer() = default;
|
28
|
+
buffer(buffer const&) = delete;
|
29
|
+
buffer& operator=(buffer const&) = delete;
|
30
|
+
|
31
|
+
explicit
|
32
|
+
buffer(std::size_t n)
|
33
|
+
: size_(n)
|
34
|
+
, buf_(new std::uint8_t[n])
|
35
|
+
{
|
36
|
+
}
|
37
|
+
|
38
|
+
buffer(buffer&& other)
|
39
|
+
: size_(other.size_)
|
40
|
+
, buf_(std::move(other.buf_))
|
41
|
+
{
|
42
|
+
other.size_ = 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
buffer&
|
46
|
+
operator=(buffer&& other)
|
47
|
+
{
|
48
|
+
size_ = other.size_;
|
49
|
+
buf_ = std::move(other.buf_);
|
50
|
+
other.size_ = 0;
|
51
|
+
return *this;
|
52
|
+
}
|
53
|
+
|
54
|
+
std::size_t
|
55
|
+
size() const
|
56
|
+
{
|
57
|
+
return size_;
|
58
|
+
}
|
59
|
+
|
60
|
+
std::uint8_t*
|
61
|
+
get() const
|
62
|
+
{
|
63
|
+
return buf_.get();
|
64
|
+
}
|
65
|
+
|
66
|
+
void
|
67
|
+
reserve(std::size_t n)
|
68
|
+
{
|
69
|
+
if(size_ < n)
|
70
|
+
buf_.reset(new std::uint8_t[n]);
|
71
|
+
size_ = n;
|
72
|
+
}
|
73
|
+
|
74
|
+
// BufferFactory
|
75
|
+
void*
|
76
|
+
operator()(std::size_t n)
|
77
|
+
{
|
78
|
+
reserve(n);
|
79
|
+
return buf_.get();
|
80
|
+
}
|
81
|
+
};
|
82
|
+
|
83
|
+
} // detail
|
84
|
+
} // nudb
|
85
|
+
|
86
|
+
#endif
|