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 <iterator>
23 #include <limits>
24 #include <string>
25 #include <utility>
26 
27 #include <protozero/config.hpp>
28 #include <protozero/types.hpp>
29 #include <protozero/varint.hpp>
30 
31 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
32 # include <protozero/byteswap.hpp>
33 #endif
34 
35 namespace protozero {
36 
37 namespace detail {
38 
39  template <typename T> class packed_field_varint;
40  template <typename T> class packed_field_svarint;
41  template <typename T> class packed_field_fixed;
42 
43 } // end namespace detail
44 
51 class pbf_writer {
52 
53  // A pointer to a string buffer holding the data already written to the
54  // PBF message. For default constructed writers or writers that have been
55  // rolled back, this is a nullptr.
56  std::string* m_data;
57 
58  // A pointer to a parent writer object if this is a submessage. If this
59  // is a top-level writer, it is a nullptr.
60  pbf_writer* m_parent_writer;
61 
62  // This is usually 0. If there is an open submessage, this is set in the
63  // parent to the rollback position, ie. the last position before the
64  // submessage was started. This is the position where the header of the
65  // submessage starts.
66  std::size_t m_rollback_pos = 0;
67 
68  // This is usually 0. If there is an open submessage, this is set in the
69  // parent to the position where the data of the submessage is written to.
70  std::size_t m_pos = 0;
71 
72  void add_varint(uint64_t value) {
73  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");
74  protozero_assert(m_data);
75  write_varint(std::back_inserter(*m_data), value);
76  }
77 
78  void add_field(pbf_tag_type tag, pbf_wire_type type) {
79  protozero_assert(((tag > 0 && tag < 19000) || (tag > 19999 && tag <= ((1 << 29) - 1))) && "tag out of range");
80  const uint32_t b = (tag << 3) | uint32_t(type);
81  add_varint(b);
82  }
83 
84  void add_tagged_varint(pbf_tag_type tag, uint64_t value) {
85  add_field(tag, pbf_wire_type::varint);
86  add_varint(value);
87  }
88 
89  template <typename T>
90  void add_fixed(T value) {
91  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");
92  protozero_assert(m_data);
93 #if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN
94  m_data->append(reinterpret_cast<const char*>(&value), sizeof(T));
95 #else
96  const auto size = m_data->size();
97  m_data->resize(size + sizeof(T));
98  byteswap<sizeof(T)>(reinterpret_cast<const char*>(&value), const_cast<char*>(m_data->data() + size));
99 #endif
100  }
101 
102  template <typename T, typename It>
103  void add_packed_fixed(pbf_tag_type tag, It first, It last, std::input_iterator_tag) {
104  if (first == last) {
105  return;
106  }
107 
108  pbf_writer sw(*this, tag);
109 
110  while (first != last) {
111  sw.add_fixed<T>(*first++);
112  }
113  }
114 
115  template <typename T, typename It>
116  void add_packed_fixed(pbf_tag_type tag, It first, It last, std::forward_iterator_tag) {
117  if (first == last) {
118  return;
119  }
120 
121  const auto length = std::distance(first, last);
122  add_length_varint(tag, sizeof(T) * pbf_length_type(length));
123  reserve(sizeof(T) * std::size_t(length));
124 
125  while (first != last) {
126  add_fixed<T>(*first++);
127  }
128  }
129 
130  template <typename It>
131  void add_packed_varint(pbf_tag_type tag, It first, It last) {
132  if (first == last) {
133  return;
134  }
135 
136  pbf_writer sw(*this, tag);
137 
138  while (first != last) {
139  sw.add_varint(uint64_t(*first++));
140  }
141  }
142 
143  template <typename It>
144  void add_packed_svarint(pbf_tag_type tag, It first, It last) {
145  if (first == last) {
146  return;
147  }
148 
149  pbf_writer sw(*this, tag);
150 
151  while (first != last) {
152  sw.add_varint(encode_zigzag64(*first++));
153  }
154  }
155 
156  // The number of bytes to reserve for the varint holding the length of
157  // a length-delimited field. The length has to fit into pbf_length_type,
158  // and a varint needs 8 bit for every 7 bit.
159  static constexpr const int reserve_bytes = sizeof(pbf_length_type) * 8 / 7 + 1;
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  static constexpr const std::size_t size_is_known = std::numeric_limits<std::size_t>::max();
165 
166  void open_submessage(pbf_tag_type tag, std::size_t size) {
167  protozero_assert(m_pos == 0);
168  protozero_assert(m_data);
169  if (size == 0) {
170  m_rollback_pos = m_data->size();
171  add_field(tag, pbf_wire_type::length_delimited);
172  m_data->append(std::size_t(reserve_bytes), '\0');
173  } else {
174  m_rollback_pos = size_is_known;
175  add_length_varint(tag, pbf_length_type(size));
176  reserve(size);
177  }
178  m_pos = m_data->size();
179  }
180 
181  void rollback_submessage() {
182  protozero_assert(m_pos != 0);
183  protozero_assert(m_rollback_pos != size_is_known);
184  protozero_assert(m_data);
185  m_data->resize(m_rollback_pos);
186  m_pos = 0;
187  }
188 
189  void commit_submessage() {
190  protozero_assert(m_pos != 0);
191  protozero_assert(m_rollback_pos != size_is_known);
192  protozero_assert(m_data);
193  const auto length = pbf_length_type(m_data->size() - m_pos);
194 
195  protozero_assert(m_data->size() >= m_pos - reserve_bytes);
196  const auto n = write_varint(m_data->begin() + long(m_pos) - reserve_bytes, length);
197 
198  m_data->erase(m_data->begin() + long(m_pos) - reserve_bytes + n, m_data->begin() + long(m_pos));
199  m_pos = 0;
200  }
201 
202  void close_submessage() {
203  protozero_assert(m_data);
204  if (m_pos == 0 || m_rollback_pos == size_is_known) {
205  return;
206  }
207  if (m_data->size() - m_pos == 0) {
208  rollback_submessage();
209  } else {
210  commit_submessage();
211  }
212  }
213 
214  void add_length_varint(pbf_tag_type tag, pbf_length_type length) {
215  add_field(tag, pbf_wire_type::length_delimited);
216  add_varint(length);
217  }
218 
219 public:
220 
226  explicit pbf_writer(std::string& data) noexcept :
227  m_data(&data),
228  m_parent_writer(nullptr),
229  m_pos(0) {
230  }
231 
236  pbf_writer() noexcept :
237  m_data(nullptr),
238  m_parent_writer(nullptr),
239  m_pos(0) {
240  }
241 
252  pbf_writer(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size=0) :
253  m_data(parent_writer.m_data),
254  m_parent_writer(&parent_writer),
255  m_pos(0) {
256  m_parent_writer->open_submessage(tag, size);
257  }
258 
260  pbf_writer(const pbf_writer&) noexcept = default;
261 
263  pbf_writer& operator=(const pbf_writer&) noexcept = default;
264 
266  pbf_writer(pbf_writer&&) noexcept = default;
267 
269  pbf_writer& operator=(pbf_writer&&) noexcept = default;
270 
271  ~pbf_writer() {
272  if (m_parent_writer) {
273  m_parent_writer->close_submessage();
274  }
275  }
276 
282  void swap(pbf_writer& other) noexcept {
283  using std::swap;
284  swap(m_data, other.m_data);
285  swap(m_parent_writer, other.m_parent_writer);
286  swap(m_rollback_pos, other.m_rollback_pos);
287  swap(m_pos, other.m_pos);
288  }
289 
298  void reserve(std::size_t size) {
299  protozero_assert(m_data);
300  m_data->reserve(m_data->size() + size);
301  }
302 
310  void rollback() {
311  protozero_assert(m_parent_writer && "you can't call rollback() on a pbf_writer without a parent");
312  protozero_assert(m_pos == 0 && "you can't call rollback() on a pbf_writer that has an open nested submessage");
313  m_parent_writer->rollback_submessage();
314  m_data = nullptr;
315  }
316 
318 
328  void add_bool(pbf_tag_type tag, bool value) {
329  add_field(tag, pbf_wire_type::varint);
330  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");
331  protozero_assert(m_data);
332  m_data->append(1, value);
333  }
334 
341  void add_enum(pbf_tag_type tag, int32_t value) {
342  add_tagged_varint(tag, uint64_t(value));
343  }
344 
351  void add_int32(pbf_tag_type tag, int32_t value) {
352  add_tagged_varint(tag, uint64_t(value));
353  }
354 
361  void add_sint32(pbf_tag_type tag, int32_t value) {
362  add_tagged_varint(tag, encode_zigzag32(value));
363  }
364 
371  void add_uint32(pbf_tag_type tag, uint32_t value) {
372  add_tagged_varint(tag, value);
373  }
374 
381  void add_int64(pbf_tag_type tag, int64_t value) {
382  add_tagged_varint(tag, uint64_t(value));
383  }
384 
391  void add_sint64(pbf_tag_type tag, int64_t value) {
392  add_tagged_varint(tag, encode_zigzag64(value));
393  }
394 
401  void add_uint64(pbf_tag_type tag, uint64_t value) {
402  add_tagged_varint(tag, value);
403  }
404 
411  void add_fixed32(pbf_tag_type tag, uint32_t value) {
412  add_field(tag, pbf_wire_type::fixed32);
413  add_fixed<uint32_t>(value);
414  }
415 
422  void add_sfixed32(pbf_tag_type tag, int32_t value) {
423  add_field(tag, pbf_wire_type::fixed32);
424  add_fixed<int32_t>(value);
425  }
426 
433  void add_fixed64(pbf_tag_type tag, uint64_t value) {
434  add_field(tag, pbf_wire_type::fixed64);
435  add_fixed<uint64_t>(value);
436  }
437 
444  void add_sfixed64(pbf_tag_type tag, int64_t value) {
445  add_field(tag, pbf_wire_type::fixed64);
446  add_fixed<int64_t>(value);
447  }
448 
455  void add_float(pbf_tag_type tag, float value) {
456  add_field(tag, pbf_wire_type::fixed32);
457  add_fixed<float>(value);
458  }
459 
466  void add_double(pbf_tag_type tag, double value) {
467  add_field(tag, pbf_wire_type::fixed64);
468  add_fixed<double>(value);
469  }
470 
478  void add_bytes(pbf_tag_type tag, const char* value, std::size_t size) {
479  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");
480  protozero_assert(m_data);
481  protozero_assert(size <= std::numeric_limits<pbf_length_type>::max());
482  add_length_varint(tag, pbf_length_type(size));
483  m_data->append(value, size);
484  }
485 
492  void add_bytes(pbf_tag_type tag, const data_view& value) {
493  add_bytes(tag, value.data(), value.size());
494  }
495 
502  void add_bytes(pbf_tag_type tag, const std::string& value) {
503  add_bytes(tag, value.data(), value.size());
504  }
505 
513  void add_string(pbf_tag_type tag, const char* value, std::size_t size) {
514  add_bytes(tag, value, size);
515  }
516 
523  void add_string(pbf_tag_type tag, const data_view& value) {
524  add_bytes(tag, value.data(), value.size());
525  }
526 
533  void add_string(pbf_tag_type tag, const std::string& value) {
534  add_bytes(tag, value.data(), value.size());
535  }
536 
544  void add_string(pbf_tag_type tag, const char* value) {
545  add_bytes(tag, value, std::strlen(value));
546  }
547 
555  void add_message(pbf_tag_type tag, const char* value, std::size_t size) {
556  add_bytes(tag, value, size);
557  }
558 
565  void add_message(pbf_tag_type tag, const data_view& value) {
566  add_bytes(tag, value.data(), value.size());
567  }
568 
575  void add_message(pbf_tag_type tag, const std::string& value) {
576  add_bytes(tag, value.data(), value.size());
577  }
578 
580 
582 
595  template <typename InputIterator>
596  void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last) {
597  add_packed_varint(tag, first, last);
598  }
599 
609  template <typename InputIterator>
610  void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last) {
611  add_packed_varint(tag, first, last);
612  }
613 
623  template <typename InputIterator>
624  void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last) {
625  add_packed_varint(tag, first, last);
626  }
627 
637  template <typename InputIterator>
638  void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last) {
639  add_packed_svarint(tag, first, last);
640  }
641 
651  template <typename InputIterator>
652  void add_packed_uint32(pbf_tag_type tag, InputIterator first, InputIterator last) {
653  add_packed_varint(tag, first, last);
654  }
655 
665  template <typename InputIterator>
666  void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last) {
667  add_packed_varint(tag, first, last);
668  }
669 
679  template <typename InputIterator>
680  void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last) {
681  add_packed_svarint(tag, first, last);
682  }
683 
693  template <typename InputIterator>
694  void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last) {
695  add_packed_varint(tag, first, last);
696  }
697 
707  template <typename InputIterator>
708  void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last) {
709  add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
710  typename std::iterator_traits<InputIterator>::iterator_category());
711  }
712 
722  template <typename InputIterator>
723  void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last) {
724  add_packed_fixed<int32_t, InputIterator>(tag, first, last,
725  typename std::iterator_traits<InputIterator>::iterator_category());
726  }
727 
737  template <typename InputIterator>
738  void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last) {
739  add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
740  typename std::iterator_traits<InputIterator>::iterator_category());
741  }
742 
752  template <typename InputIterator>
753  void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last) {
754  add_packed_fixed<int64_t, InputIterator>(tag, first, last,
755  typename std::iterator_traits<InputIterator>::iterator_category());
756  }
757 
767  template <typename InputIterator>
768  void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last) {
769  add_packed_fixed<float, InputIterator>(tag, first, last,
770  typename std::iterator_traits<InputIterator>::iterator_category());
771  }
772 
782  template <typename InputIterator>
783  void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last) {
784  add_packed_fixed<double, InputIterator>(tag, first, last,
785  typename std::iterator_traits<InputIterator>::iterator_category());
786  }
787 
789 
790  template <typename T> friend class detail::packed_field_varint;
791  template <typename T> friend class detail::packed_field_svarint;
792  template <typename T> friend class detail::packed_field_fixed;
793 
794 }; // class pbf_writer
795 
802 inline void swap(pbf_writer& lhs, pbf_writer& rhs) noexcept {
803  lhs.swap(rhs);
804 }
805 
806 namespace detail {
807 
808  class packed_field {
809 
810  protected:
811 
812  pbf_writer m_writer;
813 
814  public:
815 
816  packed_field(pbf_writer& parent_writer, pbf_tag_type tag) :
817  m_writer(parent_writer, tag) {
818  }
819 
820  packed_field(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size) :
821  m_writer(parent_writer, tag, size) {
822  }
823 
824  void rollback() {
825  m_writer.rollback();
826  }
827 
828  }; // class packed_field
829 
830  template <typename T>
831  class packed_field_fixed : public packed_field {
832 
833  public:
834 
835  packed_field_fixed(pbf_writer& parent_writer, pbf_tag_type tag) :
836  packed_field(parent_writer, tag) {
837  }
838 
839  packed_field_fixed(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size) :
840  packed_field(parent_writer, tag, size * sizeof(T)) {
841  }
842 
843  void add_element(T value) {
844  m_writer.add_fixed<T>(value);
845  }
846 
847  }; // class packed_field_fixed
848 
849  template <typename T>
850  class packed_field_varint : public packed_field {
851 
852  public:
853 
854  packed_field_varint(pbf_writer& parent_writer, pbf_tag_type tag) :
855  packed_field(parent_writer, tag) {
856  }
857 
858  void add_element(T value) {
859  m_writer.add_varint(uint64_t(value));
860  }
861 
862  }; // class packed_field_varint
863 
864  template <typename T>
865  class packed_field_svarint : public packed_field {
866 
867  public:
868 
869  packed_field_svarint(pbf_writer& parent_writer, pbf_tag_type tag) :
870  packed_field(parent_writer, tag) {
871  }
872 
873  void add_element(T value) {
874  m_writer.add_varint(encode_zigzag64(value));
875  }
876 
877  }; // class packed_field_svarint
878 
879 } // end namespace detail
880 
882 using packed_field_bool = detail::packed_field_varint<bool>;
883 
885 using packed_field_enum = detail::packed_field_varint<int32_t>;
886 
888 using packed_field_int32 = detail::packed_field_varint<int32_t>;
889 
891 using packed_field_sint32 = detail::packed_field_svarint<int32_t>;
892 
894 using packed_field_uint32 = detail::packed_field_varint<uint32_t>;
895 
897 using packed_field_int64 = detail::packed_field_varint<int64_t>;
898 
900 using packed_field_sint64 = detail::packed_field_svarint<int64_t>;
901 
903 using packed_field_uint64 = detail::packed_field_varint<uint64_t>;
904 
906 using packed_field_fixed32 = detail::packed_field_fixed<uint32_t>;
907 
909 using packed_field_sfixed32 = detail::packed_field_fixed<int32_t>;
910 
912 using packed_field_fixed64 = detail::packed_field_fixed<uint64_t>;
913 
915 using packed_field_sfixed64 = detail::packed_field_fixed<int64_t>;
916 
918 using packed_field_float = detail::packed_field_fixed<float>;
919 
921 using packed_field_double = detail::packed_field_fixed<double>;
922 
923 } // end namespace protozero
924 
925 #endif // PROTOZERO_PBF_WRITER_HPP
void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:738
void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:638
detail::packed_field_fixed< float > packed_field_float
Class for generating packed repeated float fields.
Definition: pbf_writer.hpp:918
void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:680
void add_string(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:544
void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:753
void rollback()
Definition: pbf_writer.hpp:310
void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:723
void reserve(std::size_t size)
Definition: pbf_writer.hpp:298
uint64_t encode_zigzag64(int64_t value) noexcept
Definition: varint.hpp:167
void add_sint64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:391
void add_message(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:555
detail::packed_field_varint< int64_t > packed_field_int64
Class for generating packed repeated int64 fields.
Definition: pbf_writer.hpp:897
void add_sfixed64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:444
void add_uint32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:371
void add_bytes(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:502
void add_string(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:513
void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:610
detail::packed_field_fixed< int64_t > packed_field_sfixed64
Class for generating packed repeated sfixed64 fields.
Definition: pbf_writer.hpp:915
void add_message(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:565
Definition: pbf_writer.hpp:51
void add_int64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:381
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:882
detail::packed_field_fixed< double > packed_field_double
Class for generating packed repeated double fields.
Definition: pbf_writer.hpp:921
Contains the declaration of low-level types used in the pbf format.
void add_int32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:351
void add_string(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:533
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:152
void add_uint64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:401
void add_string(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:523
detail::packed_field_varint< int32_t > packed_field_int32
Class for generating packed repeated int32 fields.
Definition: pbf_writer.hpp:888
pbf_wire_type
Definition: types.hpp:39
void add_message(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:575
void add_float(pbf_tag_type tag, float value)
Definition: pbf_writer.hpp:455
void swap(pbf_writer &other) noexcept
Definition: pbf_writer.hpp:282
void add_enum(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:341
detail::packed_field_svarint< int64_t > packed_field_sint64
Class for generating packed repeated sint64 fields.
Definition: pbf_writer.hpp:900
void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:694
pbf_writer() noexcept
Definition: pbf_writer.hpp:236
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:652
uint32_t encode_zigzag32(int32_t value) noexcept
Definition: varint.hpp:160
void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:666
void add_fixed64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:433
uint32_t pbf_length_type
Definition: types.hpp:51
void add_bool(pbf_tag_type tag, bool value)
Definition: pbf_writer.hpp:328
void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:596
detail::packed_field_fixed< uint64_t > packed_field_fixed64
Class for generating packed repeated fixed64 fields.
Definition: pbf_writer.hpp:912
detail::packed_field_fixed< int32_t > packed_field_sfixed32
Class for generating packed repeated sfixed32 fields.
Definition: pbf_writer.hpp:909
uint32_t pbf_tag_type
Definition: types.hpp:32
detail::packed_field_varint< uint32_t > packed_field_uint32
Class for generating packed repeated uint32 fields.
Definition: pbf_writer.hpp:894
void swap(pbf_writer &lhs, pbf_writer &rhs) noexcept
Definition: pbf_writer.hpp:802
void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:783
Definition: types.hpp:63
void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:768
detail::packed_field_varint< uint64_t > packed_field_uint64
Class for generating packed repeated uint64 fields.
Definition: pbf_writer.hpp:903
constexpr std::size_t size() const noexcept
Return length of data in bytes.
Definition: types.hpp:126
void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:624
pbf_writer(pbf_writer &parent_writer, pbf_tag_type tag, std::size_t size=0)
Definition: pbf_writer.hpp:252
constexpr const char * data() const noexcept
Return pointer to data.
Definition: types.hpp:121
void add_sfixed32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:422
pbf_writer(std::string &data) noexcept
Definition: pbf_writer.hpp:226
Contains low-level varint and zigzag encoding and decoding functions.
void add_sint32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:361
detail::packed_field_varint< int32_t > packed_field_enum
Class for generating packed repeated enum fields.
Definition: pbf_writer.hpp:885
void add_fixed32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:411
detail::packed_field_fixed< uint32_t > packed_field_fixed32
Class for generating packed repeated fixed32 fields.
Definition: pbf_writer.hpp:906
void add_bytes(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:492
void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:708
void add_double(pbf_tag_type tag, double value)
Definition: pbf_writer.hpp:466
detail::packed_field_svarint< int32_t > packed_field_sint32
Class for generating packed repeated sint32 fields.
Definition: pbf_writer.hpp:891
void add_bytes(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:478
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24