rrudb 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +26 -0
  5. data/examples/example.rb +39 -0
  6. data/ext/rudb/NuDB/include/nudb/CMakeLists.txt +104 -0
  7. data/ext/rudb/NuDB/include/nudb/_experimental/basic_seconds_clock.hpp +200 -0
  8. data/ext/rudb/NuDB/include/nudb/_experimental/chrono_util.hpp +58 -0
  9. data/ext/rudb/NuDB/include/nudb/_experimental/test/fail_file.hpp +343 -0
  10. data/ext/rudb/NuDB/include/nudb/_experimental/test/temp_dir.hpp +73 -0
  11. data/ext/rudb/NuDB/include/nudb/_experimental/test/test_store.hpp +451 -0
  12. data/ext/rudb/NuDB/include/nudb/_experimental/test/xor_shift_engine.hpp +105 -0
  13. data/ext/rudb/NuDB/include/nudb/_experimental/util.hpp +288 -0
  14. data/ext/rudb/NuDB/include/nudb/basic_store.hpp +461 -0
  15. data/ext/rudb/NuDB/include/nudb/concepts.hpp +205 -0
  16. data/ext/rudb/NuDB/include/nudb/context.hpp +144 -0
  17. data/ext/rudb/NuDB/include/nudb/create.hpp +117 -0
  18. data/ext/rudb/NuDB/include/nudb/detail/arena.hpp +296 -0
  19. data/ext/rudb/NuDB/include/nudb/detail/bucket.hpp +473 -0
  20. data/ext/rudb/NuDB/include/nudb/detail/buffer.hpp +86 -0
  21. data/ext/rudb/NuDB/include/nudb/detail/bulkio.hpp +196 -0
  22. data/ext/rudb/NuDB/include/nudb/detail/cache.hpp +236 -0
  23. data/ext/rudb/NuDB/include/nudb/detail/endian.hpp +93 -0
  24. data/ext/rudb/NuDB/include/nudb/detail/field.hpp +265 -0
  25. data/ext/rudb/NuDB/include/nudb/detail/format.hpp +630 -0
  26. data/ext/rudb/NuDB/include/nudb/detail/gentex.hpp +259 -0
  27. data/ext/rudb/NuDB/include/nudb/detail/mutex.hpp +26 -0
  28. data/ext/rudb/NuDB/include/nudb/detail/pool.hpp +243 -0
  29. data/ext/rudb/NuDB/include/nudb/detail/store_base.hpp +45 -0
  30. data/ext/rudb/NuDB/include/nudb/detail/stream.hpp +149 -0
  31. data/ext/rudb/NuDB/include/nudb/detail/xxhash.hpp +328 -0
  32. data/ext/rudb/NuDB/include/nudb/error.hpp +257 -0
  33. data/ext/rudb/NuDB/include/nudb/file.hpp +55 -0
  34. data/ext/rudb/NuDB/include/nudb/impl/basic_store.ipp +785 -0
  35. data/ext/rudb/NuDB/include/nudb/impl/context.ipp +241 -0
  36. data/ext/rudb/NuDB/include/nudb/impl/create.ipp +163 -0
  37. data/ext/rudb/NuDB/include/nudb/impl/error.ipp +175 -0
  38. data/ext/rudb/NuDB/include/nudb/impl/posix_file.ipp +248 -0
  39. data/ext/rudb/NuDB/include/nudb/impl/recover.ipp +209 -0
  40. data/ext/rudb/NuDB/include/nudb/impl/rekey.ipp +248 -0
  41. data/ext/rudb/NuDB/include/nudb/impl/verify.ipp +634 -0
  42. data/ext/rudb/NuDB/include/nudb/impl/visit.ipp +96 -0
  43. data/ext/rudb/NuDB/include/nudb/impl/win32_file.ipp +264 -0
  44. data/ext/rudb/NuDB/include/nudb/native_file.hpp +76 -0
  45. data/ext/rudb/NuDB/include/nudb/nudb.hpp +27 -0
  46. data/ext/rudb/NuDB/include/nudb/posix_file.hpp +228 -0
  47. data/ext/rudb/NuDB/include/nudb/progress.hpp +32 -0
  48. data/ext/rudb/NuDB/include/nudb/recover.hpp +73 -0
  49. data/ext/rudb/NuDB/include/nudb/rekey.hpp +110 -0
  50. data/ext/rudb/NuDB/include/nudb/store.hpp +27 -0
  51. data/ext/rudb/NuDB/include/nudb/type_traits.hpp +63 -0
  52. data/ext/rudb/NuDB/include/nudb/verify.hpp +200 -0
  53. data/ext/rudb/NuDB/include/nudb/version.hpp +21 -0
  54. data/ext/rudb/NuDB/include/nudb/visit.hpp +63 -0
  55. data/ext/rudb/NuDB/include/nudb/win32_file.hpp +246 -0
  56. data/ext/rudb/NuDB/include/nudb/xxhasher.hpp +45 -0
  57. data/ext/rudb/extconf.rb +12 -0
  58. data/ext/rudb/rudb.cpp +234 -0
  59. data/lib/rudb/version.rb +3 -0
  60. data/lib/rudb.rb +1 -0
  61. metadata +104 -0
@@ -0,0 +1,259 @@
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_GENTEX_HPP
9
+ #define NUDB_DETAIL_GENTEX_HPP
10
+
11
+ #include <boost/assert.hpp>
12
+ #include <condition_variable>
13
+ #include <cstddef>
14
+ #include <mutex>
15
+ #include <system_error>
16
+
17
+ namespace nudb {
18
+ namespace detail {
19
+
20
+ // Generation counting mutex
21
+ //
22
+ template<class = void>
23
+ class gentex_t
24
+ {
25
+ private:
26
+ std::mutex m_;
27
+ std::size_t gen_ = 0;
28
+ std::size_t cur_ = 0;
29
+ std::size_t prev_ = 0;
30
+ std::condition_variable cond_;
31
+
32
+ public:
33
+ gentex_t() = default;
34
+ gentex_t(gentex_t const&) = delete;
35
+ gentex_t& operator=(gentex_t const&) = delete;
36
+
37
+ void
38
+ start();
39
+
40
+ void
41
+ finish();
42
+
43
+ std::size_t
44
+ lock_gen();
45
+
46
+ void
47
+ unlock_gen(std::size_t gen);
48
+ };
49
+
50
+ template<class _>
51
+ void
52
+ gentex_t<_>::
53
+ start()
54
+ {
55
+ std::unique_lock<std::mutex> l{m_};
56
+ prev_ += cur_;
57
+ cur_ = 0;
58
+ ++gen_;
59
+ }
60
+
61
+ template<class _>
62
+ void
63
+ gentex_t<_>::
64
+ finish()
65
+ {
66
+ std::unique_lock<std::mutex> l{m_};
67
+ while(prev_ > 0)
68
+ cond_.wait(l);
69
+ }
70
+
71
+ template<class _>
72
+ std::size_t
73
+ gentex_t<_>::
74
+ lock_gen()
75
+ {
76
+ std::lock_guard<
77
+ std::mutex> l{m_};
78
+ ++cur_;
79
+ return gen_;
80
+ }
81
+
82
+ template<class _>
83
+ void
84
+ gentex_t<_>::
85
+ unlock_gen(std::size_t gen)
86
+ {
87
+ std::unique_lock<std::mutex> l{m_};
88
+ if(gen == gen_)
89
+ {
90
+ --cur_;
91
+ }
92
+ else
93
+ {
94
+ --prev_;
95
+ if(prev_ == 0)
96
+ cond_.notify_all();
97
+ }
98
+ }
99
+
100
+ using gentex = gentex_t<>;
101
+
102
+ //------------------------------------------------------------------------------
103
+
104
+ template<class GenerationLockable>
105
+ class genlock
106
+ {
107
+ private:
108
+ bool owned_ = false;
109
+ GenerationLockable* g_ = nullptr;
110
+ std::size_t gen_;
111
+
112
+ public:
113
+ using mutex_type = GenerationLockable;
114
+
115
+ genlock() = default;
116
+ genlock(genlock const&) = delete;
117
+ genlock& operator=(genlock const&) = delete;
118
+
119
+ genlock(genlock&& other);
120
+
121
+ genlock& operator=(genlock&& other);
122
+
123
+ explicit
124
+ genlock(mutex_type& g);
125
+
126
+ genlock(mutex_type& g, std::defer_lock_t);
127
+
128
+ ~genlock();
129
+
130
+ mutex_type*
131
+ mutex() noexcept
132
+ {
133
+ return g_;
134
+ }
135
+
136
+ bool
137
+ owns_lock() const noexcept
138
+ {
139
+ return g_ && owned_;
140
+ }
141
+
142
+ explicit
143
+ operator bool() const noexcept
144
+ {
145
+ return owns_lock();
146
+ }
147
+
148
+ void
149
+ lock();
150
+
151
+ void
152
+ unlock();
153
+
154
+ mutex_type*
155
+ release() noexcept;
156
+
157
+ template<class U>
158
+ friend
159
+ void
160
+ swap(genlock<U>& lhs, genlock<U>& rhs) noexcept;
161
+ };
162
+
163
+ template<class G>
164
+ genlock<G>::
165
+ genlock(genlock&& other)
166
+ : owned_(other.owned_)
167
+ , g_(other.g_)
168
+ {
169
+ other.owned_ = false;
170
+ other.g_ = nullptr;
171
+ }
172
+
173
+ template<class G>
174
+ genlock<G>&
175
+ genlock<G>::
176
+ operator=(genlock&& other)
177
+ {
178
+ if(owns_lock())
179
+ unlock();
180
+ owned_ = other.owned_;
181
+ g_ = other.g_;
182
+ other.owned_ = false;
183
+ other.g_ = nullptr;
184
+ return *this;
185
+ }
186
+
187
+ template<class G>
188
+ genlock<G>::
189
+ genlock(mutex_type& g)
190
+ : g_(&g)
191
+ {
192
+ lock();
193
+ }
194
+
195
+ template<class G>
196
+ genlock<G>::
197
+ genlock(mutex_type& g, std::defer_lock_t)
198
+ : g_(&g)
199
+ {
200
+ }
201
+
202
+ template<class G>
203
+ genlock<G>::
204
+ ~genlock()
205
+ {
206
+ if(owns_lock())
207
+ unlock();
208
+ }
209
+
210
+ template<class G>
211
+ void
212
+ genlock<G>::
213
+ lock()
214
+ {
215
+ // no associated gentex
216
+ BOOST_ASSERT(g_ != nullptr);
217
+ // gentex is already owned
218
+ BOOST_ASSERT(! owned_);
219
+ gen_ = g_->lock_gen();
220
+ owned_ = true;
221
+ }
222
+
223
+ template<class G>
224
+ void
225
+ genlock<G>::
226
+ unlock()
227
+ {
228
+ // no associated gentex
229
+ BOOST_ASSERT(g_ != nullptr);
230
+ // gentex is not owned
231
+ BOOST_ASSERT(owned_);
232
+ g_->unlock_gen(gen_);
233
+ owned_ = false;
234
+ }
235
+
236
+ template<class G>
237
+ auto
238
+ genlock<G>::
239
+ release() noexcept ->
240
+ mutex_type*
241
+ {
242
+ mutex_type* const g = g_;
243
+ g_ = nullptr;
244
+ return g;
245
+ }
246
+
247
+ template<class G>
248
+ void
249
+ swap(genlock<G>& lhs, genlock<G>& rhs) noexcept
250
+ {
251
+ using namespace std;
252
+ swap(lhs.owned_, rhs.owned_);
253
+ swap(lhs.g_, rhs.g_);
254
+ }
255
+
256
+ } // detail
257
+ } // nudb
258
+
259
+ #endif
@@ -0,0 +1,26 @@
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_MUTEX_HPP
9
+ #define NUDB_DETAIL_MUTEX_HPP
10
+
11
+ #include <boost/thread/lock_types.hpp>
12
+ #include <boost/thread/shared_mutex.hpp>
13
+
14
+ namespace nudb {
15
+ namespace detail {
16
+
17
+ using shared_lock_type =
18
+ boost::shared_lock<boost::shared_mutex>;
19
+
20
+ using unique_lock_type =
21
+ boost::unique_lock<boost::shared_mutex>;
22
+
23
+ } // detail
24
+ } // nudb
25
+
26
+ #endif
@@ -0,0 +1,243 @@
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_POOL_HPP
9
+ #define NUDB_DETAIL_POOL_HPP
10
+
11
+ #include <nudb/detail/arena.hpp>
12
+ #include <nudb/detail/bucket.hpp>
13
+ #include <nudb/detail/format.hpp>
14
+ #include <boost/assert.hpp>
15
+ #include <boost/thread/lock_types.hpp>
16
+ #include <cstdint>
17
+ #include <cstring>
18
+ #include <memory>
19
+ #include <map>
20
+ #include <utility>
21
+
22
+ namespace nudb {
23
+ namespace detail {
24
+
25
+ // Buffers key/value pairs in a map, associating
26
+ // them with a modifiable data file offset.
27
+ template<class = void>
28
+ class pool_t
29
+ {
30
+ public:
31
+ struct value_type;
32
+ class compare;
33
+
34
+ private:
35
+ using map_type = std::map<
36
+ value_type, noff_t, compare>;
37
+
38
+ arena arena_;
39
+ nsize_t key_size_;
40
+ nsize_t data_size_ = 0;
41
+ map_type map_;
42
+
43
+ public:
44
+ using iterator =
45
+ typename map_type::iterator;
46
+
47
+ pool_t(pool_t const&) = delete;
48
+ pool_t& operator=(pool_t const&) = delete;
49
+
50
+ pool_t(pool_t&& other);
51
+
52
+ pool_t(nsize_t key_size, char const* label);
53
+
54
+ iterator
55
+ begin()
56
+ {
57
+ return map_.begin();
58
+ }
59
+
60
+ iterator
61
+ end()
62
+ {
63
+ return map_.end();
64
+ }
65
+
66
+ bool
67
+ empty() const
68
+ {
69
+ return map_.size() == 0;
70
+ }
71
+
72
+ // Returns the number of elements in the pool
73
+ std::size_t
74
+ size() const
75
+ {
76
+ return map_.size();
77
+ }
78
+
79
+ // Returns the sum of data sizes in the pool
80
+ std::size_t
81
+ data_size() const
82
+ {
83
+ return data_size_;
84
+ }
85
+
86
+ void
87
+ clear();
88
+
89
+ void
90
+ periodic_activity();
91
+
92
+ iterator
93
+ find(void const* key);
94
+
95
+ // Insert a value
96
+ // @param h The hash of the key
97
+ void
98
+ insert(nhash_t h, void const* key,
99
+ void const* buffer, nsize_t size);
100
+
101
+ template<class U>
102
+ friend
103
+ void
104
+ swap(pool_t<U>& lhs, pool_t<U>& rhs);
105
+ };
106
+
107
+ template<class _>
108
+ struct pool_t<_>::value_type
109
+ {
110
+ nhash_t hash;
111
+ nsize_t size;
112
+ void const* key;
113
+ void const* data;
114
+
115
+ value_type(value_type const&) = default;
116
+ value_type& operator=(value_type const&) = default;
117
+
118
+ value_type(nhash_t hash_, nsize_t size_,
119
+ void const* key_, void const* data_)
120
+ : hash(hash_)
121
+ , size(size_)
122
+ , key(key_)
123
+ , data(data_)
124
+ {
125
+ }
126
+ };
127
+
128
+ template<class _>
129
+ class pool_t<_>::compare
130
+ {
131
+ std::size_t key_size_;
132
+
133
+ public:
134
+ using result_type = bool;
135
+ using first_argument_type = value_type;
136
+ using second_argument_type = value_type;
137
+
138
+ compare(compare const&) = default;
139
+ compare& operator=(compare const&) = default;
140
+
141
+ explicit
142
+ compare(nsize_t key_size)
143
+ : key_size_(key_size)
144
+ {
145
+ }
146
+
147
+ bool
148
+ operator()(value_type const& lhs,
149
+ value_type const& rhs) const
150
+ {
151
+ return std::memcmp(
152
+ lhs.key, rhs.key, key_size_) < 0;
153
+ }
154
+ };
155
+
156
+ //------------------------------------------------------------------------------
157
+
158
+ template<class _>
159
+ pool_t<_>::
160
+ pool_t(pool_t&& other)
161
+ : arena_(std::move(other.arena_))
162
+ , key_size_(other.key_size_)
163
+ , data_size_(other.data_size_)
164
+ , map_(std::move(other.map_))
165
+ {
166
+ }
167
+
168
+ template<class _>
169
+ pool_t<_>::
170
+ pool_t(nsize_t key_size, char const* label)
171
+ : arena_(label)
172
+ , key_size_(key_size)
173
+ , map_(compare{key_size})
174
+ {
175
+ }
176
+
177
+ template<class _>
178
+ void
179
+ pool_t<_>::
180
+ clear()
181
+ {
182
+ arena_.clear();
183
+ data_size_ = 0;
184
+ map_.clear();
185
+ }
186
+
187
+ template<class _>
188
+ void
189
+ pool_t<_>::
190
+ periodic_activity()
191
+ {
192
+ arena_.periodic_activity();
193
+ }
194
+
195
+ template<class _>
196
+ auto
197
+ pool_t<_>::
198
+ find(void const* key) ->
199
+ iterator
200
+ {
201
+ // VFALCO need is_transparent here
202
+ value_type tmp{0, 0, key, nullptr};
203
+ auto const iter = map_.find(tmp);
204
+ return iter;
205
+ }
206
+
207
+ template<class _>
208
+ void
209
+ pool_t<_>::
210
+ insert(nhash_t h,
211
+ void const* key, void const* data, nsize_t size)
212
+ {
213
+ auto const k = arena_.alloc(key_size_);
214
+ auto const d = arena_.alloc(size);
215
+ std::memcpy(k, key, key_size_);
216
+ std::memcpy(d, data, size);
217
+ auto const result = map_.emplace(
218
+ std::piecewise_construct,
219
+ std::make_tuple(h, size, k, d),
220
+ std::make_tuple(0));
221
+ (void)result.second;
222
+ // Must not already exist!
223
+ BOOST_ASSERT(result.second);
224
+ data_size_ += size;
225
+ }
226
+
227
+ template<class _>
228
+ void
229
+ swap(pool_t<_>& lhs, pool_t<_>& rhs)
230
+ {
231
+ using std::swap;
232
+ swap(lhs.arena_, rhs.arena_);
233
+ swap(lhs.key_size_, rhs.key_size_);
234
+ swap(lhs.data_size_, rhs.data_size_);
235
+ swap(lhs.map_, rhs.map_);
236
+ }
237
+
238
+ using pool = pool_t<>;
239
+
240
+ } // detail
241
+ } // nudb
242
+
243
+ #endif
@@ -0,0 +1,45 @@
1
+ //
2
+ // Copyright (c) 2019 Miguel Portilla (miguelportilla64 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_STORE_BASE_HPP
9
+ #define NUDB_DETAIL_STORE_BASE_HPP
10
+
11
+ namespace nudb {
12
+
13
+ class context;
14
+
15
+ namespace detail {
16
+
17
+ class store_base
18
+ {
19
+ protected:
20
+ friend class nudb::context;
21
+
22
+ virtual void flush() = 0;
23
+
24
+ private:
25
+ #if ! NUDB_DOXYGEN
26
+ friend class test::context_test;
27
+ #endif
28
+
29
+ enum class state
30
+ {
31
+ waiting,
32
+ flushing,
33
+ intermediate,
34
+ none
35
+ };
36
+
37
+ store_base* next_ = nullptr;
38
+ store_base* prev_ = nullptr;
39
+ state state_ = state::none;
40
+ };
41
+
42
+ } // detail
43
+ } // nudb
44
+
45
+ #endif
@@ -0,0 +1,149 @@
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_STREAM_HPP
9
+ #define NUDB_DETAIL_STREAM_HPP
10
+
11
+ #include <boost/assert.hpp>
12
+ #include <array>
13
+ #include <cstddef>
14
+ #include <cstdint>
15
+ #include <cstring>
16
+ #include <memory>
17
+
18
+ namespace nudb {
19
+ namespace detail {
20
+
21
+ // Input stream from bytes
22
+ template<class = void>
23
+ class istream_t
24
+ {
25
+ std::uint8_t const* buf_ = nullptr;
26
+ std::size_t size_ = 0;
27
+
28
+ public:
29
+ istream_t() = default;
30
+ istream_t(istream_t const&) = default;
31
+ istream_t& operator=(istream_t const&) = default;
32
+
33
+ istream_t(void const* data, std::size_t size)
34
+ : buf_(reinterpret_cast<std::uint8_t const*>(data))
35
+ , size_(size)
36
+ {
37
+ }
38
+
39
+ template<std::size_t N>
40
+ istream_t(std::array<std::uint8_t, N> const& a)
41
+ : buf_(a.data())
42
+ , size_(a.size())
43
+ {
44
+ }
45
+
46
+ std::uint8_t const*
47
+ data(std::size_t bytes);
48
+
49
+ std::uint8_t const*
50
+ operator()(std::size_t bytes)
51
+ {
52
+ return data(bytes);
53
+ }
54
+ };
55
+
56
+ // Precondition: bytes <= size_
57
+ //
58
+ template<class _>
59
+ std::uint8_t const*
60
+ istream_t<_>::data(std::size_t bytes)
61
+ {
62
+ BOOST_ASSERT(bytes <= size_);
63
+ if(size_ < bytes)
64
+ throw std::logic_error("short read from istream");
65
+ auto const data = buf_;
66
+ buf_ = buf_ + bytes;
67
+ size_ -= bytes;
68
+ return data;
69
+ }
70
+
71
+ using istream = istream_t<>;
72
+
73
+ //------------------------------------------------------------------------------
74
+
75
+ // Output stream to bytes
76
+ // VFALCO Should this assert on overwriting the buffer?
77
+ template<class = void>
78
+ class ostream_t
79
+ {
80
+ std::uint8_t* buf_ = nullptr;
81
+ std::size_t size_ = 0;
82
+
83
+ public:
84
+ ostream_t() = default;
85
+ ostream_t(ostream_t const&) = default;
86
+ ostream_t& operator=(ostream_t const&) = default;
87
+
88
+ ostream_t(void* data, std::size_t)
89
+ : buf_(reinterpret_cast<std::uint8_t*>(data))
90
+ {
91
+ }
92
+
93
+ template<std::size_t N>
94
+ ostream_t(std::array<std::uint8_t, N>& a)
95
+ : buf_(a.data())
96
+ {
97
+ }
98
+
99
+ // Returns the number of bytes written
100
+ std::size_t
101
+ size() const
102
+ {
103
+ return size_;
104
+ }
105
+
106
+ std::uint8_t*
107
+ data(std::size_t bytes);
108
+
109
+ std::uint8_t*
110
+ operator()(std::size_t bytes)
111
+ {
112
+ return data(bytes);
113
+ }
114
+ };
115
+
116
+ template<class _>
117
+ std::uint8_t*
118
+ ostream_t<_>::data(std::size_t bytes)
119
+ {
120
+ auto const data = buf_;
121
+ buf_ = buf_ + bytes;
122
+ size_ += bytes;
123
+ return data;
124
+ }
125
+
126
+ using ostream = ostream_t<>;
127
+
128
+ //------------------------------------------------------------------------------
129
+
130
+ // read blob
131
+ inline
132
+ void
133
+ read(istream& is, void* buffer, std::size_t bytes)
134
+ {
135
+ std::memcpy(buffer, is.data(bytes), bytes);
136
+ }
137
+
138
+ // write blob
139
+ inline
140
+ void
141
+ write(ostream& os, void const* buffer, std::size_t bytes)
142
+ {
143
+ std::memcpy(os.data(bytes), buffer, bytes);
144
+ }
145
+
146
+ } // detail
147
+ } // nudb
148
+
149
+ #endif