Electroneum
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 
38 namespace 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 
118  value_iterator(value_iterator const&) = default;
119  ~value_iterator() = default;
120  value_iterator& operator=(value_iterator const&) = 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 
196  value_stream(value_stream&&) = default;
197  value_stream(value_stream const&) = delete;
198  ~value_stream() = default;
199  value_stream& operator=(value_stream&&) = default;
200  value_stream& operator=(value_stream const&) = delete;
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  {
269  return {make_iterator<U, F, offset>(), value_iterator<U, F, offset>{}};
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 
boost::iterator_range< value_iterator< U, F, offset > > make_range() const
Definition: value_stream.h:267
const uint32_t T[512]
bool operator!=(key_iterator< K, V > const &lhs, key_iterator< K, V > const &rhs) noexcept
Definition: key_stream.h:259
~value_stream()=default
G get_value() const noexcept
Definition: value_stream.h:161
Lightning memory-mapped database library.
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)
std::input_iterator_tag iterator_category
Definition: value_stream.h:99
const char * key
Definition: hmac_keccak.cpp:39
STL namespace.
std::unique_ptr< MDB_cursor, D > give_cursor() noexcept
Definition: value_stream.h:208
value_type operator*() const noexcept
Definition: value_stream.h:176
~value_iterator()=default
value_stream & operator=(value_stream &&)=default
constexpr std::size_t size() const noexcept
Definition: span.h:111
mdb_size_t count(MDB_cursor *cur)
std::size_t difference_type
Definition: value_stream.h:98
value_iterator(MDB_cursor *cur)
Definition: value_stream.h:111
std::size_t count() const
Definition: value_stream.h:230
MDB_cursor_op
Cursor Get operations.
Definition: lmdb.h:398
std::size_t remove_prefix(std::size_t amount) noexcept
Definition: span.h:95
value_iterator & operator=(value_iterator const &)=default
struct MDB_cursor MDB_cursor
Opaque structure for navigating through a database.
Definition: lmdb.h:273
const T & move(const T &t)
Definition: gtest-port.h:1317
bool is_end() const noexcept
Definition: value_stream.h:123
value_iterator< U, F, offset > make_iterator() const
Definition: value_stream.h:249
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void * memcpy(void *a, const void *b, size_t c)
value_iterator() noexcept
Construct an "end" iterator.
Definition: value_stream.h:102
value_iterator & operator++()
Invalidates all prior copies of the iterator.
Definition: value_stream.h:134
#define F(s)
bool operator==(key_iterator< K, V > const &lhs, key_iterator< K, V > const &rhs) noexcept
Definition: key_stream.h:252
value_stream(std::unique_ptr< MDB_cursor, D > cur)
Take ownership of cur without changing position. nullptr valid.
Definition: value_stream.h:192
constexpr bool empty() const noexcept
Definition: span.h:109
size_t mdb_size_t
Definition: lmdb.h:196
bool equal(value_iterator const &rhs) const noexcept
Definition: value_stream.h:126
constexpr pointer data() const noexcept
Definition: span.h:110
value_iterator operator++(int)
Definition: value_stream.h:141