protozero
Minimalistic protocol buffer decoder and encoder in C++.
pbf_writer.hpp
Go to the documentation of this file.
1 #ifndef PROTOZERO_PBF_WRITER_HPP
2 #define PROTOZERO_PBF_WRITER_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 <cstddef>
20 #include <cstdint>
21 #include <cstring>
22 #include <initializer_list>
23 #include <iterator>
24 #include <limits>
25 #include <string>
26 #include <utility>
27 
28 #include <protozero/config.hpp>
29 #include <protozero/types.hpp>
30 #include <protozero/varint.hpp>
31 
32 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
33 # include <protozero/byteswap.hpp>
34 #endif
35 
36 namespace protozero {
37 
38 namespace detail {
39 
40  template <typename T> class packed_field_varint;
41  template <typename T> class packed_field_svarint;
42  template <typename T> class packed_field_fixed;
43 
44 } // end namespace detail
45 
52 class pbf_writer {
53 
54  // A pointer to a string buffer holding the data already written to the
55  // PBF message. For default constructed writers or writers that have been
56  // rolled back, this is a nullptr.
57  std::string* m_data = nullptr;
58 
59  // A pointer to a parent writer object if this is a submessage. If this
60  // is a top-level writer, it is a nullptr.
61  pbf_writer* m_parent_writer = nullptr;
62 
63  // This is usually 0. If there is an open submessage, this is set in the
64  // parent to the rollback position, ie. the last position before the
65  // submessage was started. This is the position where the header of the
66  // submessage starts.
67  std::size_t m_rollback_pos = 0;
68 
69  // This is usually 0. If there is an open submessage, this is set in the
70  // parent to the position where the data of the submessage is written to.
71  std::size_t m_pos = 0;
72 
73  void add_varint(uint64_t value) {
74  protozero_assert(m_pos == 0 && "you can't add fields to a parent pbf_writer if there is an existing pbf_writer for a submessage");
75  protozero_assert(m_data);
76  write_varint(std::back_inserter(*m_data), value);
77  }
78 
79  void add_field(pbf_tag_type tag, pbf_wire_type type) {
80  protozero_assert(((tag > 0 && tag < 19000) || (tag > 19999 && tag <= ((1 << 29) - 1))) && "tag out of range");
81  const uint32_t b = (tag << 3) | uint32_t(type);
82  add_varint(b);
83  }
84 
85  void add_tagged_varint(pbf_tag_type tag, uint64_t value) {
86  add_field(tag, pbf_wire_type::varint);
87  add_varint(value);
88  }
89 
90  template <typename T>
91  void add_fixed(T value) {
92  protozero_assert(m_pos == 0 && "you can't add fields to a parent pbf_writer if there is an existing pbf_writer for a submessage");
93  protozero_assert(m_data);
94 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
95  detail::byteswap_inplace(&value);
96 #endif
97  m_data->append(reinterpret_cast<const char*>(&value), sizeof(T));
98  }
99 
100  template <typename T, typename It>
101  void add_packed_fixed(pbf_tag_type tag, It first, It last, std::input_iterator_tag /*unused*/) {
102  if (first == last) {
103  return;
104  }
105 
106  pbf_writer sw{*this, tag};
107 
108  while (first != last) {
109  sw.add_fixed<T>(*first++);
110  }
111  }
112 
113  template <typename T, typename It>
114  void add_packed_fixed(pbf_tag_type tag, It first, It last, std::forward_iterator_tag /*unused*/) {
115  if (first == last) {
116  return;
117  }
118 
119  const auto length = std::distance(first, last);
120  add_length_varint(tag, sizeof(T) * pbf_length_type(length));
121  reserve(sizeof(T) * std::size_t(length));
122 
123  while (first != last) {
124  add_fixed<T>(*first++);
125  }
126  }
127 
128  template <typename It>
129  void add_packed_varint(pbf_tag_type tag, It first, It last) {
130  if (first == last) {
131  return;
132  }
133 
134  pbf_writer sw{*this, tag};
135 
136  while (first != last) {
137  sw.add_varint(uint64_t(*first++));
138  }
139  }
140 
141  template <typename It>
142  void add_packed_svarint(pbf_tag_type tag, It first, It last) {
143  if (first == last) {
144  return;
145  }
146 
147  pbf_writer sw{*this, tag};
148 
149  while (first != last) {
150  sw.add_varint(encode_zigzag64(*first++));
151  }
152  }
153 
154  // The number of bytes to reserve for the varint holding the length of
155  // a length-delimited field. The length has to fit into pbf_length_type,
156  // and a varint needs 8 bit for every 7 bit.
157  enum constant_reserve_bytes : int {
158  reserve_bytes = sizeof(pbf_length_type) * 8 / 7 + 1
159  };
160 
161  // If m_rollpack_pos is set to this special value, it means that when
162  // the submessage is closed, nothing needs to be done, because the length
163  // of the submessage has already been written correctly.
164  enum constant_size_is_known : std::size_t {
165  size_is_known = std::numeric_limits<std::size_t>::max()
166  };
167 
168  void open_submessage(pbf_tag_type tag, std::size_t size) {
169  protozero_assert(m_pos == 0);
170  protozero_assert(m_data);
171  if (size == 0) {
172  m_rollback_pos = m_data->size();
173  add_field(tag, pbf_wire_type::length_delimited);
174  m_data->append(std::size_t(reserve_bytes), '\0');
175  } else {
176  m_rollback_pos = size_is_known;
177  add_length_varint(tag, pbf_length_type(size));
178  reserve(size);
179  }
180  m_pos = m_data->size();
181  }
182 
183  void rollback_submessage() {
184  protozero_assert(m_pos != 0);
185  protozero_assert(m_rollback_pos != size_is_known);
186  protozero_assert(m_data);
187  m_data->resize(m_rollback_pos);
188  m_pos = 0;
189  }
190 
191  void commit_submessage() {
192  protozero_assert(m_pos != 0);
193  protozero_assert(m_rollback_pos != size_is_known);
194  protozero_assert(m_data);
195  const auto length = pbf_length_type(m_data->size() - m_pos);
196 
197  protozero_assert(m_data->size() >= m_pos - reserve_bytes);
198  const auto n = write_varint(m_data->begin() + int64_t(m_pos) - reserve_bytes, length);
199 
200  m_data->erase(m_data->begin() + int64_t(m_pos) - reserve_bytes + n, m_data->begin() + int64_t(m_pos));
201  m_pos = 0;
202  }
203 
204  void close_submessage() {
205  protozero_assert(m_data);
206  if (m_pos == 0 || m_rollback_pos == size_is_known) {
207  return;
208  }
209  if (m_data->size() - m_pos == 0) {
210  rollback_submessage();
211  } else {
212  commit_submessage();
213  }
214  }
215 
216  void add_length_varint(pbf_tag_type tag, pbf_length_type length) {
217  add_field(tag, pbf_wire_type::length_delimited);
218  add_varint(length);
219  }
220 
221 public:
222 
228  explicit pbf_writer(std::string& data) noexcept :
229  m_data(&data) {
230  }
231 
236  pbf_writer() noexcept = default;
237 
248  pbf_writer(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size=0) :
249  m_data(parent_writer.m_data),
250  m_parent_writer(&parent_writer) {
251  m_parent_writer->open_submessage(tag, size);
252  }
253 
255  pbf_writer(const pbf_writer&) = delete;
256 
258  pbf_writer& operator=(const pbf_writer&) = delete;
259 
264  pbf_writer(pbf_writer&& other) noexcept :
265  m_data(other.m_data),
266  m_parent_writer(other.m_parent_writer),
267  m_rollback_pos(other.m_rollback_pos),
268  m_pos(other.m_pos) {
269  other.m_data = nullptr;
270  other.m_parent_writer = nullptr;
271  other.m_rollback_pos = 0;
272  other.m_pos = 0;
273  }
274 
279  pbf_writer& operator=(pbf_writer&& other) noexcept {
280  m_data = other.m_data;
281  m_parent_writer = other.m_parent_writer;
282  m_rollback_pos = other.m_rollback_pos;
283  m_pos = other.m_pos;
284  other.m_data = nullptr;
285  other.m_parent_writer = nullptr;
286  other.m_rollback_pos = 0;
287  other.m_pos = 0;
288  return *this;
289  }
290 
291  ~pbf_writer() {
292  if (m_parent_writer != nullptr) {
293  m_parent_writer->close_submessage();
294  }
295  }
296 
302  bool valid() const noexcept {
303  return m_data != nullptr;
304  }
305 
311  void swap(pbf_writer& other) noexcept {
312  using std::swap;
313  swap(m_data, other.m_data);
314  swap(m_parent_writer, other.m_parent_writer);
315  swap(m_rollback_pos, other.m_rollback_pos);
316  swap(m_pos, other.m_pos);
317  }
318 
327  void reserve(std::size_t size) {
328  protozero_assert(m_data);
329  m_data->reserve(m_data->size() + size);
330  }
331 
340  void commit() {
341  protozero_assert(m_parent_writer && "you can't call commit() on a pbf_writer without a parent");
342  protozero_assert(m_pos == 0 && "you can't call commit() on a pbf_writer that has an open nested submessage");
343  m_parent_writer->close_submessage();
344  m_parent_writer = nullptr;
345  m_data = nullptr;
346  }
347 
356  void rollback() {
357  protozero_assert(m_parent_writer && "you can't call rollback() on a pbf_writer without a parent");
358  protozero_assert(m_pos == 0 && "you can't call rollback() on a pbf_writer that has an open nested submessage");
359  m_parent_writer->rollback_submessage();
360  m_parent_writer = nullptr;
361  m_data = nullptr;
362  }
363 
365 
375  void add_bool(pbf_tag_type tag, bool value) {
376  add_field(tag, pbf_wire_type::varint);
377  protozero_assert(m_pos == 0 && "you can't add fields to a parent pbf_writer if there is an existing pbf_writer for a submessage");
378  protozero_assert(m_data);
379  m_data->append(1, char(value));
380  }
381 
388  void add_enum(pbf_tag_type tag, int32_t value) {
389  add_tagged_varint(tag, uint64_t(value));
390  }
391 
398  void add_int32(pbf_tag_type tag, int32_t value) {
399  add_tagged_varint(tag, uint64_t(value));
400  }
401 
408  void add_sint32(pbf_tag_type tag, int32_t value) {
409  add_tagged_varint(tag, encode_zigzag32(value));
410  }
411 
418  void add_uint32(pbf_tag_type tag, uint32_t value) {
419  add_tagged_varint(tag, value);
420  }
421 
428  void add_int64(pbf_tag_type tag, int64_t value) {
429  add_tagged_varint(tag, uint64_t(value));
430  }
431 
438  void add_sint64(pbf_tag_type tag, int64_t value) {
439  add_tagged_varint(tag, encode_zigzag64(value));
440  }
441 
448  void add_uint64(pbf_tag_type tag, uint64_t value) {
449  add_tagged_varint(tag, value);
450  }
451 
458  void add_fixed32(pbf_tag_type tag, uint32_t value) {
459  add_field(tag, pbf_wire_type::fixed32);
460  add_fixed<uint32_t>(value);
461  }
462 
469  void add_sfixed32(pbf_tag_type tag, int32_t value) {
470  add_field(tag, pbf_wire_type::fixed32);
471  add_fixed<int32_t>(value);
472  }
473 
480  void add_fixed64(pbf_tag_type tag, uint64_t value) {
481  add_field(tag, pbf_wire_type::fixed64);
482  add_fixed<uint64_t>(value);
483  }
484 
491  void add_sfixed64(pbf_tag_type tag, int64_t value) {
492  add_field(tag, pbf_wire_type::fixed64);
493  add_fixed<int64_t>(value);
494  }
495 
502  void add_float(pbf_tag_type tag, float value) {
503  add_field(tag, pbf_wire_type::fixed32);
504  add_fixed<float>(value);
505  }
506 
513  void add_double(pbf_tag_type tag, double value) {
514  add_field(tag, pbf_wire_type::fixed64);
515  add_fixed<double>(value);
516  }
517 
525  void add_bytes(pbf_tag_type tag, const char* value, std::size_t size) {
526  protozero_assert(m_pos == 0 && "you can't add fields to a parent pbf_writer if there is an existing pbf_writer for a submessage");
527  protozero_assert(m_data);
528  protozero_assert(size <= std::numeric_limits<pbf_length_type>::max());
529  add_length_varint(tag, pbf_length_type(size));
530  m_data->append(value, size);
531  }
532 
539  void add_bytes(pbf_tag_type tag, const data_view& value) {
540  add_bytes(tag, value.data(), value.size());
541  }
542 
549  void add_bytes(pbf_tag_type tag, const std::string& value) {
550  add_bytes(tag, value.data(), value.size());
551  }
552 
560  void add_bytes(pbf_tag_type tag, const char* value) {
561  add_bytes(tag, value, std::strlen(value));
562  }
563 
583  template <typename... Ts>
584  void add_bytes_vectored(pbf_tag_type tag, Ts&&... values) {
585  protozero_assert(m_pos == 0 && "you can't add fields to a parent pbf_writer if there is an existing pbf_writer for a submessage");
586  protozero_assert(m_data);
587  size_t sum_size = 0;
588  (void)std::initializer_list<size_t>{sum_size += values.size()...};
589  protozero_assert(sum_size <= std::numeric_limits<pbf_length_type>::max());
590  add_length_varint(tag, pbf_length_type(sum_size));
591  m_data->reserve(m_data->size() + sum_size);
592  (void)std::initializer_list<int>{(m_data->append(values.data(), values.size()), 0)...};
593  }
594 
602  void add_string(pbf_tag_type tag, const char* value, std::size_t size) {
603  add_bytes(tag, value, size);
604  }
605 
612  void add_string(pbf_tag_type tag, const data_view& value) {
613  add_bytes(tag, value.data(), value.size());
614  }
615 
622  void add_string(pbf_tag_type tag, const std::string& value) {
623  add_bytes(tag, value.data(), value.size());
624  }
625 
633  void add_string(pbf_tag_type tag, const char* value) {
634  add_bytes(tag, value, std::strlen(value));
635  }
636 
644  void add_message(pbf_tag_type tag, const char* value, std::size_t size) {
645  add_bytes(tag, value, size);
646  }
647 
654  void add_message(pbf_tag_type tag, const data_view& value) {
655  add_bytes(tag, value.data(), value.size());
656  }
657 
664  void add_message(pbf_tag_type tag, const std::string& value) {
665  add_bytes(tag, value.data(), value.size());
666  }
667 
669 
671 
684  template <typename InputIterator>
685  void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last) {
686  add_packed_varint(tag, first, last);
687  }
688 
698  template <typename InputIterator>
699  void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last) {
700  add_packed_varint(tag, first, last);
701  }
702 
712  template <typename InputIterator>
713  void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last) {
714  add_packed_varint(tag, first, last);
715  }
716 
726  template <typename InputIterator>
727  void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last) {
728  add_packed_svarint(tag, first, last);
729  }
730 
740  template <typename InputIterator>
741  void add_packed_uint32(pbf_tag_type tag, InputIterator first, InputIterator last) {
742  add_packed_varint(tag, first, last);
743  }
744 
754  template <typename InputIterator>
755  void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last) {
756  add_packed_varint(tag, first, last);
757  }
758 
768  template <typename InputIterator>
769  void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last) {
770  add_packed_svarint(tag, first, last);
771  }
772 
782  template <typename InputIterator>
783  void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last) {
784  add_packed_varint(tag, first, last);
785  }
786 
796  template <typename InputIterator>
797  void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last) {
798  add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
799  typename std::iterator_traits<InputIterator>::iterator_category());
800  }
801 
811  template <typename InputIterator>
812  void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last) {
813  add_packed_fixed<int32_t, InputIterator>(tag, first, last,
814  typename std::iterator_traits<InputIterator>::iterator_category());
815  }
816 
826  template <typename InputIterator>
827  void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last) {
828  add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
829  typename std::iterator_traits<InputIterator>::iterator_category());
830  }
831 
841  template <typename InputIterator>
842  void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last) {
843  add_packed_fixed<int64_t, InputIterator>(tag, first, last,
844  typename std::iterator_traits<InputIterator>::iterator_category());
845  }
846 
856  template <typename InputIterator>
857  void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last) {
858  add_packed_fixed<float, InputIterator>(tag, first, last,
859  typename std::iterator_traits<InputIterator>::iterator_category());
860  }
861 
871  template <typename InputIterator>
872  void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last) {
873  add_packed_fixed<double, InputIterator>(tag, first, last,
874  typename std::iterator_traits<InputIterator>::iterator_category());
875  }
876 
878 
879  template <typename T> friend class detail::packed_field_varint;
880  template <typename T> friend class detail::packed_field_svarint;
881  template <typename T> friend class detail::packed_field_fixed;
882 
883 }; // class pbf_writer
884 
891 inline void swap(pbf_writer& lhs, pbf_writer& rhs) noexcept {
892  lhs.swap(rhs);
893 }
894 
895 namespace detail {
896 
897  class packed_field {
898 
899  protected:
900 
901  pbf_writer m_writer{};
902 
903  public:
904 
905  packed_field(const packed_field&) = delete;
906  packed_field& operator=(const packed_field&) = delete;
907 
908  packed_field(packed_field&&) noexcept = default;
909  packed_field& operator=(packed_field&&) noexcept = default;
910 
911  packed_field() = default;
912 
913  packed_field(pbf_writer& parent_writer, pbf_tag_type tag) :
914  m_writer(parent_writer, tag) {
915  }
916 
917  packed_field(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size) :
918  m_writer(parent_writer, tag, size) {
919  }
920 
921  ~packed_field() noexcept = default;
922 
923  bool valid() const noexcept {
924  return m_writer.valid();
925  }
926 
927  void commit() {
928  m_writer.commit();
929  }
930 
931  void rollback() {
932  m_writer.rollback();
933  }
934 
935  }; // class packed_field
936 
937  template <typename T>
938  class packed_field_fixed : public packed_field {
939 
940  public:
941 
942  packed_field_fixed() :
943  packed_field() {
944  }
945 
946  template <typename P>
947  packed_field_fixed(pbf_writer& parent_writer, P tag) :
948  packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
949  }
950 
951  template <typename P>
952  packed_field_fixed(pbf_writer& parent_writer, P tag, std::size_t size) :
953  packed_field(parent_writer, static_cast<pbf_tag_type>(tag), size * sizeof(T)) {
954  }
955 
956  void add_element(T value) {
957  m_writer.add_fixed<T>(value);
958  }
959 
960  }; // class packed_field_fixed
961 
962  template <typename T>
963  class packed_field_varint : public packed_field {
964 
965  public:
966 
967  packed_field_varint() :
968  packed_field() {
969  }
970 
971  template <typename P>
972  packed_field_varint(pbf_writer& parent_writer, P tag) :
973  packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
974  }
975 
976  void add_element(T value) {
977  m_writer.add_varint(uint64_t(value));
978  }
979 
980  }; // class packed_field_varint
981 
982  template <typename T>
983  class packed_field_svarint : public packed_field {
984 
985  public:
986 
987  packed_field_svarint() :
988  packed_field() {
989  }
990 
991  template <typename P>
992  packed_field_svarint(pbf_writer& parent_writer, P tag) :
993  packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
994  }
995 
996  void add_element(T value) {
997  m_writer.add_varint(encode_zigzag64(value));
998  }
999 
1000  }; // class packed_field_svarint
1001 
1002 } // end namespace detail
1003 
1005 using packed_field_bool = detail::packed_field_varint<bool>;
1006 
1008 using packed_field_enum = detail::packed_field_varint<int32_t>;
1009 
1011 using packed_field_int32 = detail::packed_field_varint<int32_t>;
1012 
1014 using packed_field_sint32 = detail::packed_field_svarint<int32_t>;
1015 
1017 using packed_field_uint32 = detail::packed_field_varint<uint32_t>;
1018 
1020 using packed_field_int64 = detail::packed_field_varint<int64_t>;
1021 
1023 using packed_field_sint64 = detail::packed_field_svarint<int64_t>;
1024 
1026 using packed_field_uint64 = detail::packed_field_varint<uint64_t>;
1027 
1029 using packed_field_fixed32 = detail::packed_field_fixed<uint32_t>;
1030 
1032 using packed_field_sfixed32 = detail::packed_field_fixed<int32_t>;
1033 
1035 using packed_field_fixed64 = detail::packed_field_fixed<uint64_t>;
1036 
1038 using packed_field_sfixed64 = detail::packed_field_fixed<int64_t>;
1039 
1041 using packed_field_float = detail::packed_field_fixed<float>;
1042 
1044 using packed_field_double = detail::packed_field_fixed<double>;
1045 
1046 } // end namespace protozero
1047 
1048 #endif // PROTOZERO_PBF_WRITER_HPP
void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:827
void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:727
detail::packed_field_fixed< float > packed_field_float
Class for generating packed repeated float fields.
Definition: pbf_writer.hpp:1041
void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:769
void add_string(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:633
void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:842
void rollback()
Definition: pbf_writer.hpp:356
void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:812
constexpr uint64_t encode_zigzag64(int64_t value) noexcept
Definition: varint.hpp:167
void reserve(std::size_t size)
Definition: pbf_writer.hpp:327
void add_sint64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:438
void add_message(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:644
pbf_writer(pbf_writer &&other) noexcept
Definition: pbf_writer.hpp:264
detail::packed_field_varint< int64_t > packed_field_int64
Class for generating packed repeated int64 fields.
Definition: pbf_writer.hpp:1020
void add_sfixed64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:491
void add_uint32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:418
void add_bytes(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:549
void add_string(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:602
void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:699
detail::packed_field_fixed< int64_t > packed_field_sfixed64
Class for generating packed repeated sfixed64 fields.
Definition: pbf_writer.hpp:1038
void add_message(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:654
Definition: pbf_writer.hpp:52
void add_int64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:428
Contains macro checks for different configurations.
detail::packed_field_varint< bool > packed_field_bool
Class for generating packed repeated bool fields.
Definition: pbf_writer.hpp:1005
detail::packed_field_fixed< double > packed_field_double
Class for generating packed repeated double fields.
Definition: pbf_writer.hpp:1044
Contains the declaration of low-level types used in the pbf format.
constexpr uint32_t encode_zigzag32(int32_t value) noexcept
Definition: varint.hpp:160
void add_int32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:398
void add_string(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:622
pbf_writer & operator=(pbf_writer &&other) noexcept
Definition: pbf_writer.hpp:279
int write_varint(T data, uint64_t value)
Definition: varint.hpp:144
void swap(iterator_range< T > &lhs, iterator_range< T > &rhs) noexcept
Definition: iterators.hpp:151
void add_uint64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:448
constexpr std::size_t size() const noexcept
Return length of data in bytes.
Definition: types.hpp:135
void add_string(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:612
detail::packed_field_varint< int32_t > packed_field_int32
Class for generating packed repeated int32 fields.
Definition: pbf_writer.hpp:1011
pbf_wire_type
Definition: types.hpp:40
void add_message(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:664
void add_float(pbf_tag_type tag, float value)
Definition: pbf_writer.hpp:502
void swap(pbf_writer &other) noexcept
Definition: pbf_writer.hpp:311
void add_enum(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:388
detail::packed_field_svarint< int64_t > packed_field_sint64
Class for generating packed repeated sint64 fields.
Definition: pbf_writer.hpp:1023
void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:783
void add_bytes_vectored(pbf_tag_type tag, Ts &&... values)
Definition: pbf_writer.hpp:584
Contains functions to swap bytes in values (for different endianness).
void add_packed_uint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:741
void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:755
void add_fixed64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:480
uint32_t pbf_length_type
Definition: types.hpp:63
void add_bool(pbf_tag_type tag, bool value)
Definition: pbf_writer.hpp:375
void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:685
detail::packed_field_fixed< uint64_t > packed_field_fixed64
Class for generating packed repeated fixed64 fields.
Definition: pbf_writer.hpp:1035
detail::packed_field_fixed< int32_t > packed_field_sfixed32
Class for generating packed repeated sfixed32 fields.
Definition: pbf_writer.hpp:1032
uint32_t pbf_tag_type
Definition: types.hpp:33
detail::packed_field_varint< uint32_t > packed_field_uint32
Class for generating packed repeated uint32 fields.
Definition: pbf_writer.hpp:1017
void commit()
Definition: pbf_writer.hpp:340
void swap(pbf_writer &lhs, pbf_writer &rhs) noexcept
Definition: pbf_writer.hpp:891
void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:872
Definition: types.hpp:75
void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:857
detail::packed_field_varint< uint64_t > packed_field_uint64
Class for generating packed repeated uint64 fields.
Definition: pbf_writer.hpp:1026
void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:713
pbf_writer(pbf_writer &parent_writer, pbf_tag_type tag, std::size_t size=0)
Definition: pbf_writer.hpp:248
constexpr const char * data() const noexcept
Return pointer to data.
Definition: types.hpp:130
void add_sfixed32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:469
pbf_writer(std::string &data) noexcept
Definition: pbf_writer.hpp:228
Contains low-level varint and zigzag encoding and decoding functions.
void add_sint32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:408
detail::packed_field_varint< int32_t > packed_field_enum
Class for generating packed repeated enum fields.
Definition: pbf_writer.hpp:1008
void add_fixed32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:458
detail::packed_field_fixed< uint32_t > packed_field_fixed32
Class for generating packed repeated fixed32 fields.
Definition: pbf_writer.hpp:1029
void add_bytes(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:539
bool valid() const noexcept
Definition: pbf_writer.hpp:302
void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:797
void add_double(pbf_tag_type tag, double value)
Definition: pbf_writer.hpp:513
detail::packed_field_svarint< int32_t > packed_field_sint32
Class for generating packed repeated sint32 fields.
Definition: pbf_writer.hpp:1014
void add_bytes(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:560
void add_bytes(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:525
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24