Electroneum
Loading...
Searching...
No Matches
value_stream.h
Go to the documentation of this file.
1// Copyright (c) 2018, The Monero Project
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are
5// permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of
8// conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice, this list
11// of conditions and the following disclaimer in the documentation and/or other
12// materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors may be
15// used to endorse or promote products derived from this software without specific
16// prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
19// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#pragma once
28
29#include <boost/range/iterator_range.hpp>
30#include <cstdint>
31#include <cstring>
32#include <iterator>
33#include <lmdb.h>
34#include <utility>
35
36#include "span.h"
37
38namespace lmdb
39{
40 namespace stream
41 {
42 /*
43 \throw std::system_error if unexpected LMDB error.
44 \return 0 if `cur == nullptr`, otherwise count of values at current key.
45 */
47
63 std::pair<epee::span<const std::uint8_t>, epee::span<const std::uint8_t>>
64 get(MDB_cursor& cur, MDB_cursor_op op, std::size_t key, std::size_t value);
65 }
66
81 template<typename T, typename F = T, std::size_t offset = 0>
83 {
84 MDB_cursor* cur;
86
87 void increment()
88 {
89 values.remove_prefix(sizeof(T));
90 if (values.empty() && cur)
91 values = lmdb::stream::get(*cur, MDB_NEXT_DUP, 0, sizeof(T)).second;
92 }
93
94 public:
95 using value_type = F;
97 using pointer = void;
98 using difference_type = std::size_t;
99 using iterator_category = std::input_iterator_tag;
100
102 value_iterator() noexcept
103 : cur(nullptr), values()
104 {}
105
112 : cur(cur), values()
113 {
114 if (cur)
115 values = lmdb::stream::get(*cur, MDB_GET_CURRENT, 0, sizeof(T)).second;
116 }
117
119 ~value_iterator() = default;
121
123 bool is_end() const noexcept { return values.empty(); }
124
126 bool equal(value_iterator const& rhs) const noexcept
127 {
128 return
129 (values.empty() && rhs.values.empty()) ||
130 values.data() == rhs.values.data();
131 }
132
135 {
136 increment();
137 return *this;
138 }
139
142 {
143 value_iterator out{*this};
144 increment();
145 return out;
146 }
147
160 template<typename U, typename G = U, std::size_t uoffset = 0>
161 G get_value() const noexcept
162 {
163 static_assert(std::is_same<U, T>(), "bad ELECTRONEUM_FIELD usage?");
164 static_assert(std::is_pod<U>(), "value type must be pod");
165 static_assert(std::is_pod<G>(), "field type must be pod");
166 static_assert(sizeof(G) + uoffset <= sizeof(U), "bad field and/or offset");
167 assert(sizeof(G) + uoffset <= values.size());
168 assert(!is_end());
169
170 G value;
171 std::memcpy(std::addressof(value), values.data() + uoffset, sizeof(value));
172 return value;
173 }
174
176 value_type operator*() const noexcept { return get_value<T, F, offset>(); }
177 };
178
185 template<typename T, typename D>
187 {
188 std::unique_ptr<MDB_cursor, D> cur;
189 public:
190
192 explicit value_stream(std::unique_ptr<MDB_cursor, D> cur)
193 : cur(std::move(cur))
194 {}
195
197 value_stream(value_stream const&) = delete;
198 ~value_stream() = default;
201
208 std::unique_ptr<MDB_cursor, D> give_cursor() noexcept
209 {
210 return {std::move(cur)};
211 }
212
220 void reset()
221 {
222 if (cur)
223 lmdb::stream::get(*cur, MDB_FIRST_DUP, 0, 0);
224 }
225
230 std::size_t count() const
231 {
232 return lmdb::stream::count(cur.get());
233 }
234
248 template<typename U = T, typename F = U, std::size_t offset = 0>
250 {
251 static_assert(std::is_same<U, T>(), "was ELECTRONEUM_FIELD used with wrong type?");
252 return {cur.get()};
253 }
254
266 template<typename U = T, typename F = U, std::size_t offset = 0>
267 boost::iterator_range<value_iterator<U, F, offset>> make_range() const
268 {
270 }
271 };
272
273 template<typename T, typename F, std::size_t offset>
274 inline
276 {
277 return lhs.equal(rhs);
278 }
279
280 template<typename T, typename F, std::size_t offset>
281 inline
283 {
284 return !lhs.equal(rhs);
285 }
286} // lmdb
287
Non-owning sequence of data. Does not deep copy.
Definition span.h:57
std::size_t remove_prefix(std::size_t amount) noexcept
Definition span.h:95
G get_value() const noexcept
value_iterator & operator++()
Invalidates all prior copies of the iterator.
value_iterator & operator=(value_iterator const &)=default
value_iterator(value_iterator const &)=default
value_iterator() noexcept
Construct an "end" iterator.
value_iterator(MDB_cursor *cur)
value_iterator operator++(int)
~value_iterator()=default
value_type operator*() const noexcept
bool equal(value_iterator const &rhs) const noexcept
std::size_t difference_type
bool is_end() const noexcept
std::input_iterator_tag iterator_category
value_stream(value_stream const &)=delete
value_stream(value_stream &&)=default
std::size_t count() const
value_stream(std::unique_ptr< MDB_cursor, D > cur)
Take ownership of cur without changing position. nullptr valid.
value_stream & operator=(value_stream &&)=default
std::unique_ptr< MDB_cursor, D > give_cursor() noexcept
value_iterator< U, F, offset > make_iterator() const
~value_stream()=default
value_stream & operator=(value_stream const &)=delete
boost::iterator_range< value_iterator< U, F, offset > > make_range() const
#define F(s)
MDB_cursor_op
Cursor Get operations.
Definition lmdb.h:398
@ MDB_NEXT_DUP
Definition lmdb.h:412
@ MDB_GET_CURRENT
Definition lmdb.h:404
@ MDB_FIRST_DUP
Definition lmdb.h:400
struct MDB_cursor MDB_cursor
Opaque structure for navigating through a database.
Definition lmdb.h:273
const char * key
Lightning memory-mapped database library.
size_t mdb_size_t
Definition lmdb.h:196
mdb_size_t count(MDB_cursor *cur)
std::pair< epee::span< const std::uint8_t >, epee::span< const std::uint8_t > > get(MDB_cursor &cur, MDB_cursor_op op, std::size_t key, std::size_t value)
bool operator==(key_iterator< K, V > const &lhs, key_iterator< K, V > const &rhs) noexcept
Definition key_stream.h:252
bool operator!=(key_iterator< K, V > const &lhs, key_iterator< K, V > const &rhs) noexcept
Definition key_stream.h:259
STL namespace.
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1225
#define T(x)