protozero
Minimalistic protocol buffer decoder and encoder in C++.
iterators.hpp
Go to the documentation of this file.
1 #ifndef PROTOZERO_ITERATORS_HPP
2 #define PROTOZERO_ITERATORS_HPP
3 
4 /*****************************************************************************
5 
6 protozero - Minimalistic protocol buffer decoder and encoder in C++.
7 
8 This file is from https://github.com/mapbox/protozero where you can find more
9 documentation.
10 
11 *****************************************************************************/
12 
19 #include <algorithm>
20 #include <cstring>
21 #include <iterator>
22 #include <utility>
23 
24 #include <protozero/config.hpp>
25 #include <protozero/varint.hpp>
26 
27 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
28 # include <protozero/byteswap.hpp>
29 #endif
30 
31 namespace protozero {
32 
38 template <typename T, typename P = std::pair<T, T>>
40 #ifdef PROTOZERO_STRICT_API
41  protected
42 #else
43  public
44 #endif
45  P {
46 
47 public:
48 
50  using iterator = T;
51 
53  using value_type = typename std::iterator_traits<T>::value_type;
54 
58  constexpr iterator_range() :
59  P(iterator{}, iterator{}) {
60  }
61 
68  constexpr iterator_range(iterator&& first_iterator, iterator&& last_iterator) :
69  P(std::forward<iterator>(first_iterator),
70  std::forward<iterator>(last_iterator)) {
71  }
72 
74  constexpr iterator begin() const noexcept {
75  return this->first;
76  }
77 
79  constexpr iterator end() const noexcept {
80  return this->second;
81  }
82 
84  constexpr iterator cbegin() const noexcept {
85  return this->first;
86  }
87 
89  constexpr iterator cend() const noexcept {
90  return this->second;
91  }
92 
98  constexpr bool empty() const noexcept {
99  return begin() == end();
100  }
101 
107  std::size_t size() const noexcept {
108  return begin().size();
109  }
110 
116  value_type front() const {
117  protozero_assert(!empty());
118  return *(this->first);
119  }
120 
126  void drop_front() {
127  protozero_assert(!empty());
128  ++this->first;
129  }
130 
136  void swap(iterator_range& other) noexcept {
137  using std::swap;
138  swap(this->first, other.first);
139  swap(this->second, other.second);
140  }
141 
142 }; // struct iterator_range
143 
150 template <typename T>
151 inline void swap(iterator_range<T>& lhs, iterator_range<T>& rhs) noexcept {
152  lhs.swap(rhs);
153 }
154 
159 template <typename T>
161 
163  const char* m_data = nullptr;
164 
166  const char* m_end = nullptr;
167 
168 public:
169 
170  using iterator_category = std::forward_iterator_tag;
171  using value_type = T;
172  using difference_type = std::ptrdiff_t;
173  using pointer = value_type*;
174  using reference = value_type&;
175 
176  const_fixed_iterator() noexcept = default;
177 
178  const_fixed_iterator(const char* data, const char* end) noexcept :
179  m_data(data),
180  m_end(end) {
181  }
182 
183  const_fixed_iterator(const const_fixed_iterator&) noexcept = default;
184  const_fixed_iterator(const_fixed_iterator&&) noexcept = default;
185 
186  const_fixed_iterator& operator=(const const_fixed_iterator&) noexcept = default;
187  const_fixed_iterator& operator=(const_fixed_iterator&&) noexcept = default;
188 
189  ~const_fixed_iterator() noexcept = default;
190 
191  value_type operator*() const {
192  value_type result;
193  std::memcpy(&result, m_data, sizeof(value_type));
194 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
195  detail::byteswap_inplace(&result);
196 #endif
197  return result;
198  }
199 
200  const_fixed_iterator& operator++() {
201  m_data += sizeof(value_type);
202  return *this;
203  }
204 
205  const_fixed_iterator operator++(int) {
206  const const_fixed_iterator tmp(*this);
207  ++(*this);
208  return tmp;
209  }
210 
211  std::size_t size() const noexcept {
212  return static_cast<std::size_t>(m_end - m_data) / sizeof(T);
213  }
214 
215  bool operator==(const const_fixed_iterator& rhs) const noexcept {
216  return m_data == rhs.m_data && m_end == rhs.m_end;
217  }
218 
219  bool operator!=(const const_fixed_iterator& rhs) const noexcept {
220  return !(*this == rhs);
221  }
222 
223 }; // class const_fixed_iterator
224 
229 template <typename T>
231 
232 protected:
233 
235  const char* m_data = nullptr;
236 
238  const char* m_end = nullptr;
239 
240 public:
241 
242  using iterator_category = std::forward_iterator_tag;
243  using value_type = T;
244  using difference_type = std::ptrdiff_t;
245  using pointer = value_type*;
246  using reference = value_type&;
247 
248  const_varint_iterator() noexcept = default;
249 
250  const_varint_iterator(const char* data, const char* end) noexcept :
251  m_data(data),
252  m_end(end) {
253  }
254 
255  const_varint_iterator(const const_varint_iterator&) noexcept = default;
256  const_varint_iterator(const_varint_iterator&&) noexcept = default;
257 
258  const_varint_iterator& operator=(const const_varint_iterator&) noexcept = default;
259  const_varint_iterator& operator=(const_varint_iterator&&) noexcept = default;
260 
261  ~const_varint_iterator() noexcept = default;
262 
263  value_type operator*() const {
264  const char* d = m_data; // will be thrown away
265  return static_cast<value_type>(decode_varint(&d, m_end));
266  }
267 
268  const_varint_iterator& operator++() {
269  skip_varint(&m_data, m_end);
270  return *this;
271  }
272 
273  const_varint_iterator operator++(int) {
274  const const_varint_iterator tmp(*this);
275  ++(*this);
276  return tmp;
277  }
278 
279  std::size_t size() const noexcept {
280  // We know that each varint contains exactly one byte with the most
281  // significant bit not set. We can use this to quickly figure out
282  // how many varints there are without actually decoding the varints.
283  return static_cast<std::size_t>(std::count_if(m_data, m_end, [](char c) {
284  return (static_cast<unsigned char>(c) & 0x80) == 0;
285  }));
286  }
287 
288  bool operator==(const const_varint_iterator& rhs) const noexcept {
289  return m_data == rhs.m_data && m_end == rhs.m_end;
290  }
291 
292  bool operator!=(const const_varint_iterator& rhs) const noexcept {
293  return !(*this == rhs);
294  }
295 
296 }; // class const_varint_iterator
297 
302 template <typename T>
304 
305 public:
306 
307  using iterator_category = std::forward_iterator_tag;
308  using value_type = T;
309  using difference_type = std::ptrdiff_t;
310  using pointer = value_type*;
311  using reference = value_type&;
312 
313  const_svarint_iterator() noexcept :
315  }
316 
317  const_svarint_iterator(const char* data, const char* end) noexcept :
319  }
320 
322  const_svarint_iterator(const_svarint_iterator&&) noexcept = default;
323 
324  const_svarint_iterator& operator=(const const_svarint_iterator&) = default;
325  const_svarint_iterator& operator=(const_svarint_iterator&&) noexcept = default;
326 
327  ~const_svarint_iterator() = default;
328 
329  value_type operator*() const {
330  const char* d = this->m_data; // will be thrown away
331  return static_cast<value_type>(decode_zigzag64(decode_varint(&d, this->m_end)));
332  }
333 
334  const_svarint_iterator& operator++() {
335  skip_varint(&this->m_data, this->m_end);
336  return *this;
337  }
338 
339  const_svarint_iterator operator++(int) {
340  const const_svarint_iterator tmp(*this);
341  ++(*this);
342  return tmp;
343  }
344 
345 }; // class const_svarint_iterator
346 
347 } // end namespace protozero
348 
349 #endif // PROTOZERO_ITERATORS_HPP
constexpr iterator cbegin() const noexcept
Return iterator to beginning of range.
Definition: iterators.hpp:84
typename std::iterator_traits< T >::value_type value_type
The value type of the underlying iterator.
Definition: iterators.hpp:53
constexpr int64_t decode_zigzag64(uint64_t value) noexcept
Definition: varint.hpp:181
Definition: iterators.hpp:160
void swap(iterator_range &other) noexcept
Definition: iterators.hpp:136
constexpr iterator begin() const noexcept
Return iterator to beginning of range.
Definition: iterators.hpp:74
T iterator
The type of the iterators in this range.
Definition: iterators.hpp:50
constexpr iterator end() const noexcept
Return iterator to end of range.
Definition: iterators.hpp:79
Contains macro checks for different configurations.
constexpr iterator_range(iterator &&first_iterator, iterator &&last_iterator)
Definition: iterators.hpp:68
constexpr bool empty() const noexcept
Definition: iterators.hpp:98
void swap(iterator_range< T > &lhs, iterator_range< T > &rhs) noexcept
Definition: iterators.hpp:151
void skip_varint(const char **data, const char *end)
Definition: varint.hpp:112
void drop_front()
Definition: iterators.hpp:126
const char * m_end
Pointer to end iterator position.
Definition: iterators.hpp:238
std::size_t size() const noexcept
Definition: iterators.hpp:107
const char * m_data
Pointer to current iterator position.
Definition: iterators.hpp:235
Contains functions to swap bytes in values (for different endianness).
constexpr iterator_range()
Definition: iterators.hpp:58
Definition: iterators.hpp:303
bool operator==(const data_view &lhs, const data_view &rhs) noexcept
Definition: types.hpp:187
Definition: iterators.hpp:230
bool operator!=(const data_view &lhs, const data_view &rhs) noexcept
Definition: types.hpp:198
Definition: iterators.hpp:39
Contains low-level varint and zigzag encoding and decoding functions.
value_type front() const
Definition: iterators.hpp:116
uint64_t decode_varint(const char **data, const char *end)
Definition: varint.hpp:89
constexpr iterator cend() const noexcept
Return iterator to end of range.
Definition: iterators.hpp:89
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24