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 <cstring>
20 #include <iterator>
21 #include <utility>
22 
23 #include <protozero/config.hpp>
24 #include <protozero/varint.hpp>
25 
26 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
27 # include <protozero/byteswap.hpp>
28 #endif
29 
30 namespace protozero {
31 
32 namespace detail {
33 
34  // Copy N bytes from src to dest on little endian machines, on big
35  // endian swap the bytes in the process.
36  template <int N>
37  inline void copy_or_byteswap(const char* src, void* dest) noexcept {
38 #if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN
39  std::memcpy(dest, src, N);
40 #else
41  byteswap<N>(src, reinterpret_cast<char*>(dest));
42 #endif
43  }
44 
45 } // end namespace detail
46 
52 template <typename T, typename P = std::pair<T, T>>
54 #ifdef PROTOZERO_STRICT_API
55  protected
56 #else
57  public
58 #endif
59  P {
60 
61 public:
62 
64  using iterator = T;
65 
67  using value_type = typename std::iterator_traits<T>::value_type;
68 
72  constexpr iterator_range() :
73  P(iterator{}, iterator{}) {
74  }
75 
82  constexpr iterator_range(iterator&& first_iterator, iterator&& last_iterator) :
83  P(std::forward<iterator>(first_iterator),
84  std::forward<iterator>(last_iterator)) {
85  }
86 
88  constexpr iterator begin() const noexcept {
89  return this->first;
90  }
91 
93  constexpr iterator end() const noexcept {
94  return this->second;
95  }
96 
98  constexpr iterator cbegin() const noexcept {
99  return this->first;
100  }
101 
103  constexpr iterator cend() const noexcept {
104  return this->second;
105  }
106 
108  constexpr std::size_t empty() const noexcept {
109  return begin() == end();
110  }
111 
117  value_type front() const {
118  protozero_assert(!empty());
119  return *(this->first);
120  }
121 
127  void drop_front() {
128  protozero_assert(!empty());
129  ++this->first;
130  }
131 
137  void swap(iterator_range& other) noexcept {
138  using std::swap;
139  swap(this->first, other.first);
140  swap(this->second, other.second);
141  }
142 
143 }; // struct iterator_range
144 
151 template <typename T>
152 inline void swap(iterator_range<T>& lhs, iterator_range<T>& rhs) noexcept {
153  lhs.swap(rhs);
154 }
155 
156 #ifdef PROTOZERO_USE_BARE_POINTER_FOR_PACKED_FIXED
157 
158 template <typename T>
159 using const_fixed_iterator = const T*;
160 
167 template <typename T>
168 inline iterator_range<const_fixed_iterator<T>> create_fixed_iterator_range(const char* first, const char* last) {
169  return iterator_range<const_fixed_iterator<T>>{reinterpret_cast<const T*>(first),
170  reinterpret_cast<const T*>(last)};
171 }
172 
173 #else
174 
179 template <typename T>
181 
183  const char* m_data;
184 
186  const char* m_end;
187 
188 public:
189 
190  using iterator_category = std::forward_iterator_tag;
191  using value_type = T;
192  using difference_type = std::ptrdiff_t;
193  using pointer = value_type*;
194  using reference = value_type&;
195 
196  const_fixed_iterator() noexcept :
197  m_data(nullptr),
198  m_end(nullptr) {
199  }
200 
201  const_fixed_iterator(const char* data, const char* end) noexcept :
202  m_data(data),
203  m_end(end) {
204  }
205 
206  const_fixed_iterator(const const_fixed_iterator&) noexcept = default;
207  const_fixed_iterator(const_fixed_iterator&&) noexcept = default;
208 
209  const_fixed_iterator& operator=(const const_fixed_iterator&) noexcept = default;
210  const_fixed_iterator& operator=(const_fixed_iterator&&) noexcept = default;
211 
212  ~const_fixed_iterator() noexcept = default;
213 
214  value_type operator*() const {
215  value_type result;
216  detail::copy_or_byteswap<sizeof(value_type)>(m_data , &result);
217  return result;
218  }
219 
220  const_fixed_iterator& operator++() {
221  m_data += sizeof(value_type);
222  return *this;
223  }
224 
225  const_fixed_iterator operator++(int) {
226  const const_fixed_iterator tmp(*this);
227  ++(*this);
228  return tmp;
229  }
230 
231  bool operator==(const const_fixed_iterator& rhs) const noexcept {
232  return m_data == rhs.m_data && m_end == rhs.m_end;
233  }
234 
235  bool operator!=(const const_fixed_iterator& rhs) const noexcept {
236  return !(*this == rhs);
237  }
238 
239 }; // class const_fixed_iterator
240 
247 template <typename T>
248 inline iterator_range<const_fixed_iterator<T>> create_fixed_iterator_range(const char* first, const char* last) {
250  const_fixed_iterator<T>(last, last)};
251 }
252 
253 #endif
254 
259 template <typename T>
261 
262 protected:
263 
265  const char* m_data;
266 
268  const char* m_end;
269 
270 public:
271 
272  using iterator_category = std::forward_iterator_tag;
273  using value_type = T;
274  using difference_type = std::ptrdiff_t;
275  using pointer = value_type*;
276  using reference = value_type&;
277 
278  const_varint_iterator() noexcept :
279  m_data(nullptr),
280  m_end(nullptr) {
281  }
282 
283  const_varint_iterator(const char* data, const char* end) noexcept :
284  m_data(data),
285  m_end(end) {
286  }
287 
288  const_varint_iterator(const const_varint_iterator&) noexcept = default;
289  const_varint_iterator(const_varint_iterator&&) noexcept = default;
290 
291  const_varint_iterator& operator=(const const_varint_iterator&) noexcept = default;
292  const_varint_iterator& operator=(const_varint_iterator&&) noexcept = default;
293 
294  ~const_varint_iterator() noexcept = default;
295 
296  value_type operator*() const {
297  const char* d = m_data; // will be thrown away
298  return static_cast<value_type>(decode_varint(&d, m_end));
299  }
300 
301  const_varint_iterator& operator++() {
302  skip_varint(&m_data, m_end);
303  return *this;
304  }
305 
306  const_varint_iterator operator++(int) {
307  const const_varint_iterator tmp(*this);
308  ++(*this);
309  return tmp;
310  }
311 
312  bool operator==(const const_varint_iterator& rhs) const noexcept {
313  return m_data == rhs.m_data && m_end == rhs.m_end;
314  }
315 
316  bool operator!=(const const_varint_iterator& rhs) const noexcept {
317  return !(*this == rhs);
318  }
319 
320 }; // class const_varint_iterator
321 
326 template <typename T>
328 
329 public:
330 
331  using iterator_category = std::forward_iterator_tag;
332  using value_type = T;
333  using difference_type = std::ptrdiff_t;
334  using pointer = value_type*;
335  using reference = value_type&;
336 
337  const_svarint_iterator() noexcept :
339  }
340 
341  const_svarint_iterator(const char* data, const char* end) noexcept :
342  const_varint_iterator<T>(data, end) {
343  }
344 
347 
348  const_svarint_iterator& operator=(const const_svarint_iterator&) = default;
349  const_svarint_iterator& operator=(const_svarint_iterator&&) = default;
350 
351  ~const_svarint_iterator() = default;
352 
353  value_type operator*() const {
354  const char* d = this->m_data; // will be thrown away
355  return static_cast<value_type>(decode_zigzag64(decode_varint(&d, this->m_end)));
356  }
357 
358  const_svarint_iterator& operator++() {
359  skip_varint(&this->m_data, this->m_end);
360  return *this;
361  }
362 
363  const_svarint_iterator operator++(int) {
364  const const_svarint_iterator tmp(*this);
365  ++(*this);
366  return tmp;
367  }
368 
369 }; // class const_svarint_iterator
370 
371 } // end namespace protozero
372 
373 #endif // PROTOZERO_ITERATORS_HPP
constexpr iterator cbegin() const noexcept
Return iterator to beginning of range.
Definition: iterators.hpp:98
typename std::iterator_traits< T >::value_type value_type
The value type of the underlying iterator.
Definition: iterators.hpp:67
Definition: iterators.hpp:180
void swap(iterator_range &other) noexcept
Definition: iterators.hpp:137
constexpr iterator begin() const noexcept
Return iterator to beginning of range.
Definition: iterators.hpp:88
T iterator
The type of the iterators in this range.
Definition: iterators.hpp:64
constexpr iterator end() const noexcept
Return iterator to end of range.
Definition: iterators.hpp:93
iterator_range< const_fixed_iterator< T > > create_fixed_iterator_range(const char *first, const char *last)
Definition: iterators.hpp:248
Contains macro checks for different configurations.
bool operator!=(data_view &lhs, data_view &rhs) noexcept
Definition: types.hpp:180
constexpr std::size_t empty() const noexcept
Return true if this range is empty.
Definition: iterators.hpp:108
constexpr iterator_range(iterator &&first_iterator, iterator &&last_iterator)
Definition: iterators.hpp:82
void swap(iterator_range< T > &lhs, iterator_range< T > &rhs) noexcept
Definition: iterators.hpp:152
void skip_varint(const char **data, const char *end)
Definition: varint.hpp:112
void drop_front()
Definition: iterators.hpp:127
const char * m_end
Pointer to end iterator position.
Definition: iterators.hpp:268
const char * m_data
Pointer to current iterator position.
Definition: iterators.hpp:265
Contains functions to swap bytes in values (for different endianness).
constexpr iterator_range()
Definition: iterators.hpp:72
Definition: iterators.hpp:327
Definition: iterators.hpp:260
Definition: iterators.hpp:53
Contains low-level varint and zigzag encoding and decoding functions.
bool operator==(data_view &lhs, data_view &rhs) noexcept
Definition: types.hpp:169
value_type front() const
Definition: iterators.hpp:117
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:103
int64_t decode_zigzag64(uint64_t value) noexcept
Definition: varint.hpp:181
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24