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 inline std::pair<const T*, const T*> packed_fixed() {
98 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
99 auto len = get_len_and_skip();
100 protozero_assert(len %
sizeof(T) == 0);
101 return std::make_pair(reinterpret_cast<const T*>(m_data-len), reinterpret_cast<const T*>(m_data));
106 template <
typename T>
107 class const_fixed_iterator :
public std::iterator<std::forward_iterator_tag, T> {
114 const_fixed_iterator() noexcept :
119 const_fixed_iterator(
const char *data,
const char* end) noexcept :
124 const_fixed_iterator(
const const_fixed_iterator&) noexcept =
default;
125 const_fixed_iterator(const_fixed_iterator&&) noexcept =
default;
127 const_fixed_iterator&
operator=(
const const_fixed_iterator&) noexcept =
default;
128 const_fixed_iterator&
operator=(const_fixed_iterator&&) noexcept =
default;
130 ~const_fixed_iterator() noexcept =
default;
134 copy_or_byteswap<sizeof(T)>(m_data , &result);
138 const_fixed_iterator& operator++() {
143 const_fixed_iterator operator++(
int) {
144 const const_fixed_iterator tmp(*
this);
149 bool operator==(
const const_fixed_iterator& rhs)
const noexcept {
150 return m_data == rhs.m_data && m_end == rhs.m_end;
153 bool operator!=(
const const_fixed_iterator& rhs)
const noexcept {
154 return !(*
this == rhs);
159 template <
typename T>
160 inline std::pair<const_fixed_iterator<T>, const_fixed_iterator<T>> packed_fixed() {
161 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
162 auto len = get_len_and_skip();
163 protozero_assert(len %
sizeof(T) == 0);
164 return std::make_pair(const_fixed_iterator<T>(m_data-len, m_data),
165 const_fixed_iterator<T>(m_data, m_data));
170 template <
typename T>
inline T get_varint();
171 template <
typename T>
inline T get_svarint();
173 inline pbf_length_type get_length() {
return get_varint<pbf_length_type>(); }
201 inline pbf_reader(std::pair<const char *, size_t> data) noexcept;
213 inline pbf_reader(
const std::string& data) noexcept;
239 inline operator bool()
const noexcept;
251 return size_t(m_end - m_data);
364 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
365 return get_varint<int32_t>();
376 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
377 return get_varint<int32_t>();
388 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
389 return get_svarint<int32_t>();
400 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
401 return get_varint<uint32_t>();
412 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
413 return get_varint<int64_t>();
424 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
425 return get_svarint<int64_t>();
436 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
437 return get_varint<uint64_t>();
502 inline std::pair<const char*, pbf_length_type>
get_data();
537 template <
typename T>
538 class const_varint_iterator :
public std::iterator<std::forward_iterator_tag, T> {
547 const_varint_iterator() noexcept :
552 const_varint_iterator(
const char *data,
const char* end) noexcept :
557 const_varint_iterator(
const const_varint_iterator&) noexcept = default;
558 const_varint_iterator(const_varint_iterator&&) noexcept = default;
560 const_varint_iterator& operator=(const const_varint_iterator&) noexcept = default;
561 const_varint_iterator& operator=(const_varint_iterator&&) noexcept = default;
563 ~const_varint_iterator() noexcept = default;
566 const char* d = m_data;
570 const_varint_iterator& operator++() {
577 const_varint_iterator operator++(
int) {
578 const const_varint_iterator tmp(*
this);
583 bool operator==(
const const_varint_iterator& rhs)
const noexcept {
584 return m_data == rhs.m_data && m_end == rhs.m_end;
587 bool operator!=(
const const_varint_iterator& rhs)
const noexcept {
588 return !(*
this == rhs);
593 template <
typename T>
594 class const_svarint_iterator :
public const_varint_iterator<T> {
598 const_svarint_iterator() noexcept :
599 const_varint_iterator<T>() {
602 const_svarint_iterator(
const char *data,
const char* end) noexcept :
603 const_varint_iterator<T>(data, end) {
606 const_svarint_iterator(
const const_svarint_iterator&) =
default;
607 const_svarint_iterator(const_svarint_iterator&&) =
default;
609 const_svarint_iterator&
operator=(
const const_svarint_iterator&) =
default;
610 const_svarint_iterator&
operator=(const_svarint_iterator&&) =
default;
612 ~const_svarint_iterator() =
default;
615 const char* d = this->m_data;
619 const_svarint_iterator& operator++() {
626 const_svarint_iterator operator++(
int) {
627 const const_svarint_iterator tmp(*
this);
674 inline std::pair<pbf_reader::const_bool_iterator, pbf_reader::const_bool_iterator>
get_packed_bool();
685 inline std::pair<pbf_reader::const_enum_iterator, pbf_reader::const_enum_iterator>
get_packed_enum();
696 inline std::pair<pbf_reader::const_int32_iterator, pbf_reader::const_int32_iterator>
get_packed_int32();
707 inline std::pair<pbf_reader::const_sint32_iterator, pbf_reader::const_sint32_iterator>
get_packed_sint32();
718 inline std::pair<pbf_reader::const_uint32_iterator, pbf_reader::const_uint32_iterator>
get_packed_uint32();
729 inline std::pair<pbf_reader::const_int64_iterator, pbf_reader::const_int64_iterator>
get_packed_int64();
740 inline std::pair<pbf_reader::const_sint64_iterator, pbf_reader::const_sint64_iterator>
get_packed_sint64();
751 inline std::pair<pbf_reader::const_uint64_iterator, pbf_reader::const_uint64_iterator>
get_packed_uint64();
763 return packed_fixed<uint32_t>();
776 return packed_fixed<int32_t>();
789 return packed_fixed<uint64_t>();
802 return packed_fixed<int64_t>();
815 return packed_fixed<float>();
828 return packed_fixed<double>();
837 m_end(data + length),
838 m_wire_type(pbf_wire_type::unknown),
843 : m_data(data.first),
844 m_end(data.first + data.second),
845 m_wire_type(pbf_wire_type::unknown),
850 : m_data(data.data()),
851 m_end(data.data() + data.size()),
852 m_wire_type(pbf_wire_type::unknown),
856 pbf_reader::operator bool() const noexcept {
857 return m_data < m_end;
861 if (m_data == m_end) {
865 auto value = get_varint<uint32_t>();
870 protozero_assert(((m_tag > 0 && m_tag < 19000) || (m_tag > 19999 && m_tag <= ((1 << 29) - 1))) &&
"tag out of range");
873 switch (m_wire_type) {
874 case pbf_wire_type::varint:
875 case pbf_wire_type::fixed64:
876 case pbf_wire_type::length_delimited:
877 case pbf_wire_type::fixed32:
888 if (m_tag == requested_tag) {
906 return wire_type() == type;
910 if (m_data + len > m_end) {
923 protozero_assert(
tag() != 0 &&
"call next() before calling skip()");
925 case pbf_wire_type::varint:
928 case pbf_wire_type::fixed64:
931 case pbf_wire_type::length_delimited:
932 skip_bytes(get_length());
934 case pbf_wire_type::fixed32:
943 auto len = get_length();
948 template <
typename T>
949 T pbf_reader::get_varint() {
953 template <
typename T>
954 T pbf_reader::get_svarint() {
960 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
961 protozero_assert(
has_wire_type(pbf_wire_type::fixed32) &&
"not a 32-bit fixed");
962 return get_fixed<uint32_t>();
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<int32_t>();
972 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
973 protozero_assert(
has_wire_type(pbf_wire_type::fixed64) &&
"not a 64-bit fixed");
974 return get_fixed<uint64_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<int64_t>();
984 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
985 protozero_assert(
has_wire_type(pbf_wire_type::fixed32) &&
"not a 32-bit fixed");
986 return get_fixed<float>();
990 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
991 protozero_assert(
has_wire_type(pbf_wire_type::fixed64) &&
"not a 64-bit fixed");
992 return get_fixed<double>();
996 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
997 protozero_assert(
has_wire_type(pbf_wire_type::varint) &&
"not a varint");
998 protozero_assert((*m_data & 0x80) == 0 &&
"not a 1 byte varint");
1000 return m_data[-1] != 0;
1004 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1005 protozero_assert(
has_wire_type(pbf_wire_type::length_delimited) &&
"not of type string, bytes or message");
1006 auto len = get_len_and_skip();
1007 return std::make_pair(m_data-len, len);
1012 return std::string(d.first, d.second);
1028 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1029 auto len = get_len_and_skip();
1035 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1036 auto len = get_len_and_skip();
1042 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1043 auto len = get_len_and_skip();
1049 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1050 auto len = get_len_and_skip();
1056 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1057 auto len = get_len_and_skip();
1063 protozero_assert(
tag() != 0 &&
"call next() before accessing field value");
1064 auto len = get_len_and_skip();
1071 #endif // PROTOZERO_PBF_READER_HPP
int64_t get_sfixed64()
Definition: pbf_reader.hpp:977
uint32_t get_uint32()
Definition: pbf_reader.hpp:399
uint64_t get_fixed64()
Definition: pbf_reader.hpp:971
int32_t get_sfixed32()
Definition: pbf_reader.hpp:965
Definition: exception.hpp:48
uint64_t get_uint64()
Definition: pbf_reader.hpp:435
auto get_packed_double() -> decltype(packed_fixed< double >())
Definition: pbf_reader.hpp:827
int32_t get_int32()
Definition: pbf_reader.hpp:375
uint32_t pbf_length_type
Definition: pbf_types.hpp:45
std::pair< pbf_reader::const_sint32_iterator, pbf_reader::const_sint32_iterator > get_packed_sint32()
Definition: pbf_reader.hpp:1041
auto get_packed_float() -> decltype(packed_fixed< float >())
Definition: pbf_reader.hpp:814
auto get_packed_fixed32() -> decltype(packed_fixed< uint32_t >())
Definition: pbf_reader.hpp:762
std::pair< const char *, pbf_length_type > get_data()
Definition: pbf_reader.hpp:1003
Contains macro checks for different configurations.
bool has_wire_type(pbf_wire_type type) const noexcept
Definition: pbf_reader.hpp:905
void skip()
Definition: pbf_reader.hpp:922
const_varint_iterator< uint32_t > const_uint32_iterator
Forward iterator for iterating over uint32 (varint) values.
Definition: pbf_reader.hpp:649
pbf_reader get_message()
Definition: pbf_reader.hpp:529
pbf_reader() noexcept=default
std::pair< pbf_reader::const_bool_iterator, pbf_reader::const_bool_iterator > get_packed_bool()
Definition: pbf_reader.hpp:1019
auto get_packed_sfixed64() -> decltype(packed_fixed< int64_t >())
Definition: pbf_reader.hpp:801
auto get_packed_sfixed32() -> decltype(packed_fixed< int32_t >())
Definition: pbf_reader.hpp:775
pbf_wire_type
Definition: pbf_types.hpp:33
Contains the declaration of low-level types used in the pbf format.
pbf_wire_type wire_type() const noexcept
Definition: pbf_reader.hpp:901
uint32_t pbf_tag_type
Definition: pbf_types.hpp:26
std::pair< pbf_reader::const_int32_iterator, pbf_reader::const_int32_iterator > get_packed_int32()
Definition: pbf_reader.hpp:1027
int64_t get_sint64()
Definition: pbf_reader.hpp:423
auto get_packed_fixed64() -> decltype(packed_fixed< uint64_t >())
Definition: pbf_reader.hpp:788
Contains functions to swap bytes in values (for different endianness).
int32_t get_sint32()
Definition: pbf_reader.hpp:387
std::string get_bytes()
Definition: pbf_reader.hpp:1010
double get_double()
Definition: pbf_reader.hpp:989
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:655
bool get_bool()
Definition: pbf_reader.hpp:995
std::string get_string()
Definition: pbf_reader.hpp:1015
const_varint_iterator< int32_t > const_enum_iterator
Forward iterator for iterating over enum (int32 varint) values.
Definition: pbf_reader.hpp:640
Contains the exceptions used in the protozero library.
uint32_t get_fixed32()
Definition: pbf_reader.hpp:959
pbf_tag_type tag() const noexcept
Definition: pbf_reader.hpp:897
const_varint_iterator< int32_t > const_int32_iterator
Forward iterator for iterating over int32 (varint) values.
Definition: pbf_reader.hpp:643
std::pair< pbf_reader::const_int64_iterator, pbf_reader::const_int64_iterator > get_packed_int64()
Definition: pbf_reader.hpp:1048
const_varint_iterator< int32_t > const_bool_iterator
Forward iterator for iterating over bool (int32 varint) values.
Definition: pbf_reader.hpp:637
int32_t get_enum()
Definition: pbf_reader.hpp:363
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:658
float get_float()
Definition: pbf_reader.hpp:983
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:652
std::pair< pbf_reader::const_uint64_iterator, pbf_reader::const_uint64_iterator > get_packed_uint64()
Definition: pbf_reader.hpp:1055
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:1023
const_svarint_iterator< int32_t > const_sint32_iterator
Forward iterator for iterating over sint32 (varint) values.
Definition: pbf_reader.hpp:646
bool next()
Definition: pbf_reader.hpp:860
size_t length() const noexcept
Definition: pbf_reader.hpp:250
int64_t get_int64()
Definition: pbf_reader.hpp:411
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:1062
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:1034