Loading...
Searching...
No Matches
iterators.hpp
Go to the documentation of this file.
#ifndef PROTOZERO_ITERATORS_HPP
#define PROTOZERO_ITERATORS_HPP
/*****************************************************************************
protozero - Minimalistic protocol buffer decoder and encoder in C++.
This file is from https://github.com/mapbox/protozero where you can find more
documentation.
*****************************************************************************/
#include "config.hpp"
#include "varint.hpp"
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
# include <protozero/byteswap.hpp>
#endif
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
namespace protozero {
template <typename T, typename P = std::pair<T, T>>
class iterator_range :
#ifdef PROTOZERO_STRICT_API
protected
#else
public
#endif
P {
public:
using iterator = T;
using value_type = typename std::iterator_traits<T>::value_type;
constexpr iterator_range() :
P{iterator{}, iterator{}} {
}
constexpr iterator_range(iterator&& first_iterator, iterator&& last_iterator) :
P{std::forward<iterator>(first_iterator),
std::forward<iterator>(last_iterator)} {
}
constexpr iterator begin() const noexcept {
return this->first;
}
constexpr iterator end() const noexcept {
return this->second;
}
constexpr iterator cbegin() const noexcept {
return this->first;
}
constexpr iterator cend() const noexcept {
return this->second;
}
constexpr bool empty() const noexcept {
return begin() == end();
}
std::size_t size() const noexcept {
return static_cast<size_t>(std::distance(begin(), end()));
}
value_type front() const {
protozero_assert(!empty());
return *(this->first);
}
void drop_front() {
protozero_assert(!empty());
++this->first;
}
void swap(iterator_range& other) noexcept {
using std::swap;
swap(this->first, other.first);
swap(this->second, other.second);
}
}; // struct iterator_range
template <typename T>
inline void swap(iterator_range<T>& lhs, iterator_range<T>& rhs) noexcept {
lhs.swap(rhs);
}
template <typename T>
class const_fixed_iterator {
const char* m_data = nullptr;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
const_fixed_iterator() noexcept = default;
explicit const_fixed_iterator(const char* data) noexcept :
m_data{data} {
}
const_fixed_iterator(const const_fixed_iterator&) noexcept = default;
const_fixed_iterator(const_fixed_iterator&&) noexcept = default;
const_fixed_iterator& operator=(const const_fixed_iterator&) noexcept = default;
const_fixed_iterator& operator=(const_fixed_iterator&&) noexcept = default;
~const_fixed_iterator() noexcept = default;
value_type operator*() const noexcept {
value_type result;
std::memcpy(&result, m_data, sizeof(value_type));
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
byteswap_inplace(&result);
#endif
return result;
}
const_fixed_iterator& operator++() noexcept {
m_data += sizeof(value_type);
return *this;
}
const_fixed_iterator operator++(int) noexcept {
const const_fixed_iterator tmp{*this};
++(*this);
return tmp;
}
const_fixed_iterator& operator--() noexcept {
m_data -= sizeof(value_type);
return *this;
}
const_fixed_iterator operator--(int) noexcept {
const const_fixed_iterator tmp{*this};
--(*this);
return tmp;
}
friend bool operator==(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return lhs.m_data == rhs.m_data;
}
friend bool operator!=(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return !(lhs == rhs);
}
friend bool operator<(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return lhs.m_data < rhs.m_data;
}
friend bool operator>(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return rhs < lhs;
}
friend bool operator<=(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return !(lhs > rhs);
}
friend bool operator>=(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return !(lhs < rhs);
}
const_fixed_iterator& operator+=(difference_type val) noexcept {
m_data += (sizeof(value_type) * val);
return *this;
}
friend const_fixed_iterator operator+(const_fixed_iterator lhs, difference_type rhs) noexcept {
const_fixed_iterator tmp{lhs};
tmp.m_data += (sizeof(value_type) * rhs);
return tmp;
}
friend const_fixed_iterator operator+(difference_type lhs, const_fixed_iterator rhs) noexcept {
const_fixed_iterator tmp{rhs};
tmp.m_data += (sizeof(value_type) * lhs);
return tmp;
}
const_fixed_iterator& operator-=(difference_type val) noexcept {
m_data -= (sizeof(value_type) * val);
return *this;
}
friend const_fixed_iterator operator-(const_fixed_iterator lhs, difference_type rhs) noexcept {
const_fixed_iterator tmp{lhs};
tmp.m_data -= (sizeof(value_type) * rhs);
return tmp;
}
friend difference_type operator-(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
return static_cast<difference_type>(lhs.m_data - rhs.m_data) / static_cast<difference_type>(sizeof(T));
}
value_type operator[](difference_type n) const noexcept {
return *(*this + n);
}
}; // class const_fixed_iterator
template <typename T>
class const_varint_iterator {
protected:
const char* m_data = nullptr; // NOLINT(misc-non-private-member-variables-in-classes, cppcoreguidelines-non-private-member-variables-in-classes,-warnings-as-errors)
const char* m_end = nullptr; // NOLINT(misc-non-private-member-variables-in-classes, cppcoreguidelines-non-private-member-variables-in-classes,-warnings-as-errors)
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
static difference_type distance(const_varint_iterator begin, const_varint_iterator end) noexcept {
// The "distance" between default initialized const_varint_iterator's
// is always 0.
if (!begin.m_data) {
return 0;
}
// We know that each varint contains exactly one byte with the most
// significant bit not set. We can use this to quickly figure out
// how many varints there are without actually decoding the varints.
return std::count_if(begin.m_data, end.m_data, [](char c) noexcept {
return (static_cast<unsigned char>(c) & 0x80U) == 0;
});
}
const_varint_iterator() noexcept = default;
const_varint_iterator(const char* data, const char* end) noexcept :
m_data{data},
m_end{end} {
}
const_varint_iterator(const const_varint_iterator&) noexcept = default;
const_varint_iterator(const_varint_iterator&&) noexcept = default;
const_varint_iterator& operator=(const const_varint_iterator&) noexcept = default;
const_varint_iterator& operator=(const_varint_iterator&&) noexcept = default;
~const_varint_iterator() noexcept = default;
value_type operator*() const {
protozero_assert(m_data);
const char* d = m_data; // will be thrown away
return static_cast<value_type>(decode_varint(&d, m_end));
}
const_varint_iterator& operator++() {
protozero_assert(m_data);
skip_varint(&m_data, m_end);
return *this;
}
const_varint_iterator operator++(int) {
protozero_assert(m_data);
const const_varint_iterator tmp{*this};
++(*this);
return tmp;
}
bool operator==(const const_varint_iterator& rhs) const noexcept {
return m_data == rhs.m_data && m_end == rhs.m_end;
}
bool operator!=(const const_varint_iterator& rhs) const noexcept {
return !(*this == rhs);
}
}; // class const_varint_iterator
template <typename T>
class const_svarint_iterator : public const_varint_iterator<T> {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
const_svarint_iterator() noexcept :
const_varint_iterator<T>{} {
}
const_svarint_iterator(const char* data, const char* end) noexcept :
const_varint_iterator<T>{data, end} {
}
const_svarint_iterator(const const_svarint_iterator&) = default;
const_svarint_iterator(const_svarint_iterator&&) noexcept = default;
const_svarint_iterator& operator=(const const_svarint_iterator&) = default;
const_svarint_iterator& operator=(const_svarint_iterator&&) noexcept = default;
~const_svarint_iterator() = default;
value_type operator*() const {
protozero_assert(this->m_data);
const char* d = this->m_data; // will be thrown away
return static_cast<value_type>(decode_zigzag64(decode_varint(&d, this->m_end)));
}
const_svarint_iterator& operator++() {
protozero_assert(this->m_data);
skip_varint(&this->m_data, this->m_end);
return *this;
}
const_svarint_iterator operator++(int) {
protozero_assert(this->m_data);
const const_svarint_iterator tmp{*this};
++(*this);
return tmp;
}
}; // class const_svarint_iterator
} // end namespace protozero
namespace std {
// Specialize std::distance for all the protozero iterators. Because
// functions can't be partially specialized, we have to do this for
// every value_type we are using.
template <>
inline typename protozero::const_varint_iterator<int32_t>::difference_type
distance<protozero::const_varint_iterator<int32_t>>(protozero::const_varint_iterator<int32_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
protozero::const_varint_iterator<int32_t> last) {
return protozero::const_varint_iterator<int32_t>::distance(first, last);
}
template <>
inline typename protozero::const_varint_iterator<int64_t>::difference_type
distance<protozero::const_varint_iterator<int64_t>>(protozero::const_varint_iterator<int64_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
protozero::const_varint_iterator<int64_t> last) {
return protozero::const_varint_iterator<int64_t>::distance(first, last);
}
template <>
inline typename protozero::const_varint_iterator<uint32_t>::difference_type
distance<protozero::const_varint_iterator<uint32_t>>(protozero::const_varint_iterator<uint32_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
protozero::const_varint_iterator<uint32_t> last) {
return protozero::const_varint_iterator<uint32_t>::distance(first, last);
}
template <>
inline typename protozero::const_varint_iterator<uint64_t>::difference_type
distance<protozero::const_varint_iterator<uint64_t>>(protozero::const_varint_iterator<uint64_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
protozero::const_varint_iterator<uint64_t> last) {
return protozero::const_varint_iterator<uint64_t>::distance(first, last);
}
template <>
inline typename protozero::const_svarint_iterator<int32_t>::difference_type
distance<protozero::const_svarint_iterator<int32_t>>(protozero::const_svarint_iterator<int32_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
protozero::const_svarint_iterator<int32_t> last) {
return protozero::const_svarint_iterator<int32_t>::distance(first, last);
}
template <>
inline typename protozero::const_svarint_iterator<int64_t>::difference_type
distance<protozero::const_svarint_iterator<int64_t>>(protozero::const_svarint_iterator<int64_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
protozero::const_svarint_iterator<int64_t> last) {
return protozero::const_svarint_iterator<int64_t>::distance(first, last);
}
} // end namespace std
#endif // PROTOZERO_ITERATORS_HPP
byteswap.hpp
Contains functions to swap bytes in values (for different endianness).
protozero::const_fixed_iterator
Definition iterators.hpp:160
protozero::const_svarint_iterator
Definition iterators.hpp:374
protozero::const_varint_iterator
Definition iterators.hpp:289
protozero::const_varint_iterator::m_end
const char * m_end
Pointer to end iterator position.
Definition iterators.hpp:297
protozero::const_varint_iterator::m_data
const char * m_data
Pointer to current iterator position.
Definition iterators.hpp:294
protozero::iterator_range
Definition iterators.hpp:45
protozero::iterator_range::cend
constexpr iterator cend() const noexcept
Return iterator to end of range.
Definition iterators.hpp:89
protozero::iterator_range::value_type
typename std::iterator_traits< T >::value_type value_type
The value type of the underlying iterator.
Definition iterators.hpp:53
protozero::iterator_range::iterator_range
constexpr iterator_range()
Definition iterators.hpp:58
protozero::iterator_range::cbegin
constexpr iterator cbegin() const noexcept
Return iterator to beginning of range.
Definition iterators.hpp:84
protozero::iterator_range::empty
constexpr bool empty() const noexcept
Definition iterators.hpp:98
protozero::iterator_range::front
value_type front() const
Definition iterators.hpp:116
protozero::iterator_range::size
std::size_t size() const noexcept
Definition iterators.hpp:107
protozero::iterator_range::iterator_range
constexpr iterator_range(iterator &&first_iterator, iterator &&last_iterator)
Definition iterators.hpp:68
protozero::iterator_range::begin
constexpr iterator begin() const noexcept
Return iterator to beginning of range.
Definition iterators.hpp:74
protozero::iterator_range::end
constexpr iterator end() const noexcept
Return iterator to end of range.
Definition iterators.hpp:79
protozero::iterator_range::drop_front
void drop_front()
Definition iterators.hpp:126
protozero::iterator_range::swap
void swap(iterator_range &other) noexcept
Definition iterators.hpp:136
protozero::iterator_range::iterator
T iterator
The type of the iterators in this range.
Definition iterators.hpp:50
config.hpp
Contains macro checks for different configurations.
protozero
All parts of the protozero header-only library are in this namespace.
Definition basic_pbf_builder.hpp:24
protozero::operator<
bool operator<(const data_view lhs, const data_view rhs) noexcept
Definition data_view.hpp:198
protozero::swap
void swap(basic_pbf_writer< TBuffer > &lhs, basic_pbf_writer< TBuffer > &rhs) noexcept
Definition basic_pbf_writer.hpp:936
protozero::operator!=
constexpr bool operator!=(const data_view lhs, const data_view rhs) noexcept
Definition data_view.hpp:188
protozero::decode_zigzag64
constexpr int64_t decode_zigzag64(uint64_t value) noexcept
Definition varint.hpp:238
protozero::operator==
constexpr bool operator==(const data_view lhs, const data_view rhs) noexcept
Definition data_view.hpp:176
protozero::skip_varint
void skip_varint(const char **data, const char *end)
Definition varint.hpp:113
protozero::operator>=
bool operator>=(const data_view lhs, const data_view rhs) noexcept
Definition data_view.hpp:228
protozero::decode_varint
uint64_t decode_varint(const char **data, const char *end)
Definition varint.hpp:90
protozero::operator<=
bool operator<=(const data_view lhs, const data_view rhs) noexcept
Definition data_view.hpp:208
protozero::byteswap_inplace
void byteswap_inplace(uint32_t *ptr) noexcept
byteswap the data pointed to by ptr in-place.
Definition byteswap.hpp:56
protozero::operator>
bool operator>(const data_view lhs, const data_view rhs) noexcept
Definition data_view.hpp:218
varint.hpp
Contains low-level varint and zigzag encoding and decoding functions.