1 #ifndef PROTOZERO_PBF_READER_HPP 2 #define PROTOZERO_PBF_READER_HPP 31 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN 64 const char *m_data =
nullptr;
67 const char *m_end =
nullptr;
78 static void copy_or_byteswap(
const char* src,
void* dest) noexcept {
79 #if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN 82 byteswap<N>(src,
reinterpret_cast<char*
>(dest));
87 inline T get_fixed() {
89 skip_bytes(
sizeof(T));
90 copy_or_byteswap<sizeof(T)>(m_data -
sizeof(T), &result);
94 #ifdef PROTOZERO_USE_BARE_POINTER_FOR_PACKED_FIXED 97 using const_fixed_iterator =
const T*;
100 inline std::pair<const_fixed_iterator<T>, const_fixed_iterator<T>> create_fixed_iterator_pair(
const char* first,
const char* last) {
101 return std::make_pair(reinterpret_cast<const T*>(first),
102 reinterpret_cast<const T*>(last));
107 template <
typename T>
108 class const_fixed_iterator :
public std::iterator<std::forward_iterator_tag, T> {
115 const_fixed_iterator() noexcept :
120 const_fixed_iterator(
const char *data,
const char* end) noexcept :
125 const_fixed_iterator(
const const_fixed_iterator&) noexcept =
default;
126 const_fixed_iterator(const_fixed_iterator&&) noexcept =
default;
128 const_fixed_iterator&
operator=(
const const_fixed_iterator&) noexcept =
default;
129 const_fixed_iterator&
operator=(const_fixed_iterator&&) noexcept =
default;
131 ~const_fixed_iterator() noexcept =
default;
135 copy_or_byteswap<sizeof(T)>(m_data , &result);
139 const_fixed_iterator& operator++() {
144 const_fixed_iterator operator++(
int) {
145 const const_fixed_iterator tmp(*
this);
150 bool operator==(
const const_fixed_iterator& rhs)
const noexcept {
151 return m_data == rhs.m_data && m_end == rhs.m_end;
154 bool operator!=(
const const_fixed_iterator& rhs)
const noexcept {
155 return !(*
this == rhs);
160 template <
typename T>
161 inline std::pair<const_fixed_iterator<T>, const_fixed_iterator<T>> create_fixed_iterator_pair(
const char* first,
const char* last) {
162 return std::make_pair(const_fixed_iterator<T>(first, last),
163 const_fixed_iterator<T>(last, last));
168 template <
typename T>
169 inline std::pair<const_fixed_iterator<T>, const_fixed_iterator<T>> packed_fixed() {
170 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
171 auto len = get_len_and_skip();
172 protozero_assert(len %
sizeof(T) == 0);
173 return create_fixed_iterator_pair<T>(m_data-len, m_data);
176 template <
typename T>
inline T get_varint();
177 template <
typename T>
inline T get_svarint();
179 inline pbf_length_type get_length() {
return get_varint<pbf_length_type>(); }
207 inline pbf_reader(std::pair<const char *, std::size_t> data) noexcept;
219 inline pbf_reader(
const std::string& data) noexcept;
245 inline operator bool()
const noexcept;
257 return std::size_t(m_end - m_data);
370 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
371 return get_varint<int32_t>();
382 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
383 return get_varint<int32_t>();
394 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
395 return get_svarint<int32_t>();
406 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
407 return get_varint<uint32_t>();
418 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
419 return get_varint<int64_t>();
430 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
431 return get_svarint<int64_t>();
442 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
443 return get_varint<uint64_t>();
508 inline std::pair<const char*, pbf_length_type>
get_data();
543 template <
typename T>
544 class const_varint_iterator :
public std::iterator<std::forward_iterator_tag, T> {
553 const_varint_iterator() noexcept :
558 const_varint_iterator(
const char *data,
const char* end) noexcept :
563 const_varint_iterator(
const const_varint_iterator&) noexcept =
default;
564 const_varint_iterator(const_varint_iterator&&) noexcept =
default;
566 const_varint_iterator&
operator=(
const const_varint_iterator&) noexcept =
default;
567 const_varint_iterator&
operator=(const_varint_iterator&&) noexcept =
default;
569 ~const_varint_iterator() noexcept =
default;
572 const char* d = m_data;
576 const_varint_iterator& operator++() {
583 const_varint_iterator operator++(
int) {
584 const const_varint_iterator tmp(*
this);
589 bool operator==(
const const_varint_iterator& rhs)
const noexcept {
590 return m_data == rhs.m_data && m_end == rhs.m_end;
593 bool operator!=(
const const_varint_iterator& rhs)
const noexcept {
594 return !(*
this == rhs);
599 template <
typename T>
600 class const_svarint_iterator :
public const_varint_iterator<T> {
604 const_svarint_iterator() noexcept :
605 const_varint_iterator<T>() {
608 const_svarint_iterator(
const char *data,
const char* end) noexcept :
609 const_varint_iterator<T>(data, end) {
612 const_svarint_iterator(
const const_svarint_iterator&) =
default;
613 const_svarint_iterator(const_svarint_iterator&&) =
default;
615 const_svarint_iterator&
operator=(
const const_svarint_iterator&) =
default;
616 const_svarint_iterator&
operator=(const_svarint_iterator&&) =
default;
618 ~const_svarint_iterator() =
default;
621 const char* d = this->m_data;
625 const_svarint_iterator& operator++() {
632 const_svarint_iterator operator++(
int) {
633 const const_svarint_iterator tmp(*
this);
680 inline std::pair<pbf_reader::const_bool_iterator, pbf_reader::const_bool_iterator>
get_packed_bool();
691 inline std::pair<pbf_reader::const_enum_iterator, pbf_reader::const_enum_iterator>
get_packed_enum();
702 inline std::pair<pbf_reader::const_int32_iterator, pbf_reader::const_int32_iterator>
get_packed_int32();
713 inline std::pair<pbf_reader::const_sint32_iterator, pbf_reader::const_sint32_iterator>
get_packed_sint32();
724 inline std::pair<pbf_reader::const_uint32_iterator, pbf_reader::const_uint32_iterator>
get_packed_uint32();
735 inline std::pair<pbf_reader::const_int64_iterator, pbf_reader::const_int64_iterator>
get_packed_int64();
746 inline std::pair<pbf_reader::const_sint64_iterator, pbf_reader::const_sint64_iterator>
get_packed_sint64();
757 inline std::pair<pbf_reader::const_uint64_iterator, pbf_reader::const_uint64_iterator>
get_packed_uint64();
769 return packed_fixed<uint32_t>();
782 return packed_fixed<int32_t>();
795 return packed_fixed<uint64_t>();
808 return packed_fixed<int64_t>();
821 return packed_fixed<float>();
834 return packed_fixed<double>();
843 m_end(data + length),
844 m_wire_type(pbf_wire_type::unknown),
849 : m_data(data.first),
850 m_end(data.first + data.second),
851 m_wire_type(pbf_wire_type::unknown),
856 : m_data(data.data()),
857 m_end(data.data() + data.size()),
858 m_wire_type(pbf_wire_type::unknown),
862 pbf_reader::operator bool() const noexcept {
863 return m_data < m_end;
867 if (m_data == m_end) {
871 auto value = get_varint<uint32_t>();
876 protozero_assert(((m_tag > 0 && m_tag < 19000) || (m_tag > 19999 && m_tag <= ((1 << 29) - 1))) &&
"tag out of range");
879 switch (m_wire_type) {
880 case pbf_wire_type::varint:
881 case pbf_wire_type::fixed64:
882 case pbf_wire_type::length_delimited:
883 case pbf_wire_type::fixed32:
894 if (m_tag == requested_tag) {
916 if (m_data + len > m_end) {
929 protozero_assert(
tag() != 0 &&
"call next() before calling skip()");
931 case pbf_wire_type::varint:
934 case pbf_wire_type::fixed64:
937 case pbf_wire_type::length_delimited:
938 skip_bytes(get_length());
940 case pbf_wire_type::fixed32:
944 protozero_assert(
false &&
"can not be here because next() should have thrown already");
949 auto len = get_length();
954 template <
typename T>
955 T pbf_reader::get_varint() {
959 template <
typename T>
960 T pbf_reader::get_svarint() {
966 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
967 protozero_assert(
has_wire_type(pbf_wire_type::fixed32) &&
"not a 32-bit fixed");
968 return get_fixed<uint32_t>();
972 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
973 protozero_assert(
has_wire_type(pbf_wire_type::fixed32) &&
"not a 32-bit fixed");
974 return get_fixed<int32_t>();
978 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
979 protozero_assert(
has_wire_type(pbf_wire_type::fixed64) &&
"not a 64-bit fixed");
980 return get_fixed<uint64_t>();
984 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
985 protozero_assert(
has_wire_type(pbf_wire_type::fixed64) &&
"not a 64-bit fixed");
986 return get_fixed<int64_t>();
990 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
991 protozero_assert(
has_wire_type(pbf_wire_type::fixed32) &&
"not a 32-bit fixed");
992 return get_fixed<float>();
996 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
997 protozero_assert(
has_wire_type(pbf_wire_type::fixed64) &&
"not a 64-bit fixed");
998 return get_fixed<double>();
1002 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1003 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
1004 protozero_assert((*m_data & 0x80) == 0 &&
"not a 1 byte varint");
1006 return m_data[-1] != 0;
1010 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1011 protozero_assert(
has_wire_type(pbf_wire_type::length_delimited) &&
"not of type string, bytes or message");
1012 auto len = get_len_and_skip();
1013 return std::make_pair(m_data-len, len);
1018 return std::string(d.first, d.second);
1034 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1035 auto len = get_len_and_skip();
1041 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1042 auto len = get_len_and_skip();
1048 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1049 auto len = get_len_and_skip();
1055 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1056 auto len = get_len_and_skip();
1062 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1063 auto len = get_len_and_skip();
1069 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1070 auto len = get_len_and_skip();
1077 #endif // PROTOZERO_PBF_READER_HPP int64_t get_sfixed64()
Definition: pbf_reader.hpp:983
uint32_t get_uint32()
Definition: pbf_reader.hpp:405
uint64_t get_fixed64()
Definition: pbf_reader.hpp:977
int32_t get_sfixed32()
Definition: pbf_reader.hpp:971
Definition: exception.hpp:48
uint64_t get_uint64()
Definition: pbf_reader.hpp:441
auto get_packed_double() -> decltype(packed_fixed< double >())
Definition: pbf_reader.hpp:833
std::size_t length() const noexcept
Definition: pbf_reader.hpp:256
int32_t get_int32()
Definition: pbf_reader.hpp:381
uint32_t pbf_length_type
Definition: types.hpp:45
std::pair< pbf_reader::const_sint32_iterator, pbf_reader::const_sint32_iterator > get_packed_sint32()
Definition: pbf_reader.hpp:1047
auto get_packed_float() -> decltype(packed_fixed< float >())
Definition: pbf_reader.hpp:820
auto get_packed_fixed32() -> decltype(packed_fixed< uint32_t >())
Definition: pbf_reader.hpp:768
std::pair< const char *, pbf_length_type > get_data()
Definition: pbf_reader.hpp:1009
Contains macro checks for different configurations.
pbf_tag_type tag() const noexcept
Definition: pbf_reader.hpp:903
Contains the declaration of low-level types used in the pbf format.
void skip()
Definition: pbf_reader.hpp:928
const_varint_iterator< uint32_t > const_uint32_iterator
Forward iterator for iterating over uint32 (varint) values.
Definition: pbf_reader.hpp:655
pbf_reader get_message()
Definition: pbf_reader.hpp:535
pbf_reader() noexcept=default
std::pair< pbf_reader::const_bool_iterator, pbf_reader::const_bool_iterator > get_packed_bool()
Definition: pbf_reader.hpp:1025
auto get_packed_sfixed64() -> decltype(packed_fixed< int64_t >())
Definition: pbf_reader.hpp:807
auto get_packed_sfixed32() -> decltype(packed_fixed< int32_t >())
Definition: pbf_reader.hpp:781
pbf_wire_type
Definition: types.hpp:33
uint32_t pbf_tag_type
Definition: types.hpp:26
std::pair< pbf_reader::const_int32_iterator, pbf_reader::const_int32_iterator > get_packed_int32()
Definition: pbf_reader.hpp:1033
int64_t get_sint64()
Definition: pbf_reader.hpp:429
auto get_packed_fixed64() -> decltype(packed_fixed< uint64_t >())
Definition: pbf_reader.hpp:794
pbf_wire_type wire_type() const noexcept
Definition: pbf_reader.hpp:907
Contains functions to swap bytes in values (for different endianness).
int32_t get_sint32()
Definition: pbf_reader.hpp:393
std::string get_bytes()
Definition: pbf_reader.hpp:1016
double get_double()
Definition: pbf_reader.hpp:995
pbf_reader & operator=(const pbf_reader &other) noexcept=default
pbf_reader messages can be copied trivially.
const_svarint_iterator< int64_t > const_sint64_iterator
Forward iterator for iterating over sint64 (varint) values.
Definition: pbf_reader.hpp:661
bool get_bool()
Definition: pbf_reader.hpp:1001
std::string get_string()
Definition: pbf_reader.hpp:1021
const_varint_iterator< int32_t > const_enum_iterator
Forward iterator for iterating over enum (int32 varint) values.
Definition: pbf_reader.hpp:646
Contains the exceptions used in the protozero library.
uint32_t get_fixed32()
Definition: pbf_reader.hpp:965
const_varint_iterator< int32_t > const_int32_iterator
Forward iterator for iterating over int32 (varint) values.
Definition: pbf_reader.hpp:649
std::pair< pbf_reader::const_int64_iterator, pbf_reader::const_int64_iterator > get_packed_int64()
Definition: pbf_reader.hpp:1054
const_varint_iterator< int32_t > const_bool_iterator
Forward iterator for iterating over bool (int32 varint) values.
Definition: pbf_reader.hpp:643
int32_t get_enum()
Definition: pbf_reader.hpp:369
Definition: pbf_reader.hpp:61
const_varint_iterator< uint64_t > const_uint64_iterator
Forward iterator for iterating over uint64 (varint) values.
Definition: pbf_reader.hpp:664
float get_float()
Definition: pbf_reader.hpp:989
Definition: exception.hpp:61
Contains low-level varint and zigzag encoding and decoding functions.
const_varint_iterator< int64_t > const_int64_iterator
Forward iterator for iterating over int64 (varint) values.
Definition: pbf_reader.hpp:658
std::pair< pbf_reader::const_uint64_iterator, pbf_reader::const_uint64_iterator > get_packed_uint64()
Definition: pbf_reader.hpp:1061
uint64_t decode_varint(const char **data, const char *end)
Definition: varint.hpp:48
std::pair< pbf_reader::const_enum_iterator, pbf_reader::const_enum_iterator > get_packed_enum()
Definition: pbf_reader.hpp:1029
const_svarint_iterator< int32_t > const_sint32_iterator
Forward iterator for iterating over sint32 (varint) values.
Definition: pbf_reader.hpp:652
bool next()
Definition: pbf_reader.hpp:866
int64_t get_int64()
Definition: pbf_reader.hpp:417
int64_t decode_zigzag64(uint64_t value) noexcept
Definition: varint.hpp:126
std::pair< pbf_reader::const_sint64_iterator, pbf_reader::const_sint64_iterator > get_packed_sint64()
Definition: pbf_reader.hpp:1068
bool has_wire_type(pbf_wire_type type) const noexcept
Definition: pbf_reader.hpp:911
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24
std::pair< pbf_reader::const_uint32_iterator, pbf_reader::const_uint32_iterator > get_packed_uint32()
Definition: pbf_reader.hpp:1040