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  detail::byteswap_inplace(&value);
95 #endif
96  m_data->append(reinterpret_cast<const char*>(&value), sizeof(T));
97  }
98 
99  template <typename T, typename It>
100  void add_packed_fixed(pbf_tag_type tag, It first, It last, std::input_iterator_tag) {
101  if (first == last) {
102  return;
103  }
104 
105  pbf_writer sw(*this, tag);
106 
107  while (first != last) {
108  sw.add_fixed<T>(*first++);
109  }
110  }
111 
112  template <typename T, typename It>
113  void add_packed_fixed(pbf_tag_type tag, It first, It last, std::forward_iterator_tag) {
114  if (first == last) {
115  return;
116  }
117 
118  const auto length = std::distance(first, last);
119  add_length_varint(tag, sizeof(T) * pbf_length_type(length));
120  reserve(sizeof(T) * std::size_t(length));
121 
122  while (first != last) {
123  add_fixed<T>(*first++);
124  }
125  }
126 
127  template <typename It>
128  void add_packed_varint(pbf_tag_type tag, It first, It last) {
129  if (first == last) {
130  return;
131  }
132 
133  pbf_writer sw(*this, tag);
134 
135  while (first != last) {
136  sw.add_varint(uint64_t(*first++));
137  }
138  }
139 
140  template <typename It>
141  void add_packed_svarint(pbf_tag_type tag, It first, It last) {
142  if (first == last) {
143  return;
144  }
145 
146  pbf_writer sw(*this, tag);
147 
148  while (first != last) {
149  sw.add_varint(encode_zigzag64(*first++));
150  }
151  }
152 
153  // The number of bytes to reserve for the varint holding the length of
154  // a length-delimited field. The length has to fit into pbf_length_type,
155  // and a varint needs 8 bit for every 7 bit.
156  enum constant_reserve_bytes : int {
157  reserve_bytes = sizeof(pbf_length_type) * 8 / 7 + 1
158  };
159 
160  // If m_rollpack_pos is set to this special value, it means that when
161  // the submessage is closed, nothing needs to be done, because the length
162  // of the submessage has already been written correctly.
163  enum constant_size_is_known : std::size_t {
164  size_is_known = std::numeric_limits<std::size_t>::max()
165  };
166 
167  void open_submessage(pbf_tag_type tag, std::size_t size) {
168  protozero_assert(m_pos == 0);
169  protozero_assert(m_data);
170  if (size == 0) {
171  m_rollback_pos = m_data->size();
172  add_field(tag, pbf_wire_type::length_delimited);
173  m_data->append(std::size_t(reserve_bytes), '\0');
174  } else {
175  m_rollback_pos = size_is_known;
176  add_length_varint(tag, pbf_length_type(size));
177  reserve(size);
178  }
179  m_pos = m_data->size();
180  }
181 
182  void rollback_submessage() {
183  protozero_assert(m_pos != 0);
184  protozero_assert(m_rollback_pos != size_is_known);
185  protozero_assert(m_data);
186  m_data->resize(m_rollback_pos);
187  m_pos = 0;
188  }
189 
190  void commit_submessage() {
191  protozero_assert(m_pos != 0);
192  protozero_assert(m_rollback_pos != size_is_known);
193  protozero_assert(m_data);
194  const auto length = pbf_length_type(m_data->size() - m_pos);
195 
196  protozero_assert(m_data->size() >= m_pos - reserve_bytes);
197  const auto n = write_varint(m_data->begin() + long(m_pos) - reserve_bytes, length);
198 
199  m_data->erase(m_data->begin() + long(m_pos) - reserve_bytes + n, m_data->begin() + long(m_pos));
200  m_pos = 0;
201  }
202 
203  void close_submessage() {
204  protozero_assert(m_data);
205  if (m_pos == 0 || m_rollback_pos == size_is_known) {
206  return;
207  }
208  if (m_data->size() - m_pos == 0) {
209  rollback_submessage();
210  } else {
211  commit_submessage();
212  }
213  }
214 
215  void add_length_varint(pbf_tag_type tag, pbf_length_type length) {
216  add_field(tag, pbf_wire_type::length_delimited);
217  add_varint(length);
218  }
219 
220 public:
221 
227  explicit pbf_writer(std::string& data) noexcept :
228  m_data(&data),
229  m_parent_writer(nullptr) {
230  }
231 
236  pbf_writer() noexcept :
237  m_data(nullptr),
238  m_parent_writer(nullptr) {
239  }
240 
251  pbf_writer(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size=0) :
252  m_data(parent_writer.m_data),
253  m_parent_writer(&parent_writer) {
254  m_parent_writer->open_submessage(tag, size);
255  }
256 
258  pbf_writer(const pbf_writer&) noexcept = default;
259 
261  pbf_writer& operator=(const pbf_writer&) noexcept = default;
262 
264  pbf_writer(pbf_writer&&) noexcept = default;
265 
267  pbf_writer& operator=(pbf_writer&&) noexcept = default;
268 
269  ~pbf_writer() {
270  if (m_parent_writer) {
271  m_parent_writer->close_submessage();
272  }
273  }
274 
280  void swap(pbf_writer& other) noexcept {
281  using std::swap;
282  swap(m_data, other.m_data);
283  swap(m_parent_writer, other.m_parent_writer);
284  swap(m_rollback_pos, other.m_rollback_pos);
285  swap(m_pos, other.m_pos);
286  }
287 
296  void reserve(std::size_t size) {
297  protozero_assert(m_data);
298  m_data->reserve(m_data->size() + size);
299  }
300 
308  void rollback() {
309  protozero_assert(m_parent_writer && "you can't call rollback() on a pbf_writer without a parent");
310  protozero_assert(m_pos == 0 && "you can't call rollback() on a pbf_writer that has an open nested submessage");
311  m_parent_writer->rollback_submessage();
312  m_data = nullptr;
313  }
314 
316 
326  void add_bool(pbf_tag_type tag, bool value) {
327  add_field(tag, pbf_wire_type::varint);
328  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");
329  protozero_assert(m_data);
330  m_data->append(1, value);
331  }
332 
339  void add_enum(pbf_tag_type tag, int32_t value) {
340  add_tagged_varint(tag, uint64_t(value));
341  }
342 
349  void add_int32(pbf_tag_type tag, int32_t value) {
350  add_tagged_varint(tag, uint64_t(value));
351  }
352 
359  void add_sint32(pbf_tag_type tag, int32_t value) {
360  add_tagged_varint(tag, encode_zigzag32(value));
361  }
362 
369  void add_uint32(pbf_tag_type tag, uint32_t value) {
370  add_tagged_varint(tag, value);
371  }
372 
379  void add_int64(pbf_tag_type tag, int64_t value) {
380  add_tagged_varint(tag, uint64_t(value));
381  }
382 
389  void add_sint64(pbf_tag_type tag, int64_t value) {
390  add_tagged_varint(tag, encode_zigzag64(value));
391  }
392 
399  void add_uint64(pbf_tag_type tag, uint64_t value) {
400  add_tagged_varint(tag, value);
401  }
402 
409  void add_fixed32(pbf_tag_type tag, uint32_t value) {
410  add_field(tag, pbf_wire_type::fixed32);
411  add_fixed<uint32_t>(value);
412  }
413 
420  void add_sfixed32(pbf_tag_type tag, int32_t value) {
421  add_field(tag, pbf_wire_type::fixed32);
422  add_fixed<int32_t>(value);
423  }
424 
431  void add_fixed64(pbf_tag_type tag, uint64_t value) {
432  add_field(tag, pbf_wire_type::fixed64);
433  add_fixed<uint64_t>(value);
434  }
435 
442  void add_sfixed64(pbf_tag_type tag, int64_t value) {
443  add_field(tag, pbf_wire_type::fixed64);
444  add_fixed<int64_t>(value);
445  }
446 
453  void add_float(pbf_tag_type tag, float value) {
454  add_field(tag, pbf_wire_type::fixed32);
455  add_fixed<float>(value);
456  }
457 
464  void add_double(pbf_tag_type tag, double value) {
465  add_field(tag, pbf_wire_type::fixed64);
466  add_fixed<double>(value);
467  }
468 
476  void add_bytes(pbf_tag_type tag, const char* value, std::size_t size) {
477  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");
478  protozero_assert(m_data);
479  protozero_assert(size <= std::numeric_limits<pbf_length_type>::max());
480  add_length_varint(tag, pbf_length_type(size));
481  m_data->append(value, size);
482  }
483 
490  void add_bytes(pbf_tag_type tag, const data_view& value) {
491  add_bytes(tag, value.data(), value.size());
492  }
493 
500  void add_bytes(pbf_tag_type tag, const std::string& value) {
501  add_bytes(tag, value.data(), value.size());
502  }
503 
511  void add_bytes(pbf_tag_type tag, const char* value) {
512  add_bytes(tag, value, std::strlen(value));
513  }
514 
534  template <typename... Ts>
535  void add_bytes_vectored(pbf_tag_type tag, Ts&&... values) {
536  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");
537  protozero_assert(m_data);
538  size_t sum_size = 0;
539  (void)std::initializer_list<size_t>{sum_size += values.size()...};
540  protozero_assert(sum_size <= std::numeric_limits<pbf_length_type>::max());
541  add_length_varint(tag, pbf_length_type(sum_size));
542  m_data->reserve(m_data->size() + sum_size);
543  (void)std::initializer_list<int>{(m_data->append(values.data(), values.size()), 0)...};
544  }
545 
553  void add_string(pbf_tag_type tag, const char* value, std::size_t size) {
554  add_bytes(tag, value, size);
555  }
556 
563  void add_string(pbf_tag_type tag, const data_view& value) {
564  add_bytes(tag, value.data(), value.size());
565  }
566 
573  void add_string(pbf_tag_type tag, const std::string& value) {
574  add_bytes(tag, value.data(), value.size());
575  }
576 
584  void add_string(pbf_tag_type tag, const char* value) {
585  add_bytes(tag, value, std::strlen(value));
586  }
587 
595  void add_message(pbf_tag_type tag, const char* value, std::size_t size) {
596  add_bytes(tag, value, size);
597  }
598 
605  void add_message(pbf_tag_type tag, const data_view& value) {
606  add_bytes(tag, value.data(), value.size());
607  }
608 
615  void add_message(pbf_tag_type tag, const std::string& value) {
616  add_bytes(tag, value.data(), value.size());
617  }
618 
620 
622 
635  template <typename InputIterator>
636  void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last) {
637  add_packed_varint(tag, first, last);
638  }
639 
649  template <typename InputIterator>
650  void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last) {
651  add_packed_varint(tag, first, last);
652  }
653 
663  template <typename InputIterator>
664  void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last) {
665  add_packed_varint(tag, first, last);
666  }
667 
677  template <typename InputIterator>
678  void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last) {
679  add_packed_svarint(tag, first, last);
680  }
681 
691  template <typename InputIterator>
692  void add_packed_uint32(pbf_tag_type tag, InputIterator first, InputIterator last) {
693  add_packed_varint(tag, first, last);
694  }
695 
705  template <typename InputIterator>
706  void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last) {
707  add_packed_varint(tag, first, last);
708  }
709 
719  template <typename InputIterator>
720  void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last) {
721  add_packed_svarint(tag, first, last);
722  }
723 
733  template <typename InputIterator>
734  void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last) {
735  add_packed_varint(tag, first, last);
736  }
737 
747  template <typename InputIterator>
748  void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last) {
749  add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
750  typename std::iterator_traits<InputIterator>::iterator_category());
751  }
752 
762  template <typename InputIterator>
763  void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last) {
764  add_packed_fixed<int32_t, InputIterator>(tag, first, last,
765  typename std::iterator_traits<InputIterator>::iterator_category());
766  }
767 
777  template <typename InputIterator>
778  void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last) {
779  add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
780  typename std::iterator_traits<InputIterator>::iterator_category());
781  }
782 
792  template <typename InputIterator>
793  void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last) {
794  add_packed_fixed<int64_t, InputIterator>(tag, first, last,
795  typename std::iterator_traits<InputIterator>::iterator_category());
796  }
797 
807  template <typename InputIterator>
808  void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last) {
809  add_packed_fixed<float, InputIterator>(tag, first, last,
810  typename std::iterator_traits<InputIterator>::iterator_category());
811  }
812 
822  template <typename InputIterator>
823  void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last) {
824  add_packed_fixed<double, InputIterator>(tag, first, last,
825  typename std::iterator_traits<InputIterator>::iterator_category());
826  }
827 
829 
830  template <typename T> friend class detail::packed_field_varint;
831  template <typename T> friend class detail::packed_field_svarint;
832  template <typename T> friend class detail::packed_field_fixed;
833 
834 }; // class pbf_writer
835 
842 inline void swap(pbf_writer& lhs, pbf_writer& rhs) noexcept {
843  lhs.swap(rhs);
844 }
845 
846 namespace detail {
847 
848  class packed_field {
849 
850  protected:
851 
852  pbf_writer m_writer;
853 
854  public:
855 
856  packed_field(const packed_field&) = delete;
857  packed_field& operator=(const packed_field&) = delete;
858 
859  packed_field(packed_field&&) = default;
860  packed_field& operator=(packed_field&&) = default;
861 
862  packed_field(pbf_writer& parent_writer, pbf_tag_type tag) :
863  m_writer(parent_writer, tag) {
864  }
865 
866  packed_field(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size) :
867  m_writer(parent_writer, tag, size) {
868  }
869 
870  void rollback() {
871  m_writer.rollback();
872  }
873 
874  }; // class packed_field
875 
876  template <typename T>
877  class packed_field_fixed : public packed_field {
878 
879  public:
880 
881  template <typename P>
882  packed_field_fixed(pbf_writer& parent_writer, P tag) :
883  packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
884  }
885 
886  template <typename P>
887  packed_field_fixed(pbf_writer& parent_writer, P tag, std::size_t size) :
888  packed_field(parent_writer, static_cast<pbf_tag_type>(tag), size * sizeof(T)) {
889  }
890 
891  void add_element(T value) {
892  m_writer.add_fixed<T>(value);
893  }
894 
895  }; // class packed_field_fixed
896 
897  template <typename T>
898  class packed_field_varint : public packed_field {
899 
900  public:
901 
902  template <typename P>
903  packed_field_varint(pbf_writer& parent_writer, P tag) :
904  packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
905  }
906 
907  void add_element(T value) {
908  m_writer.add_varint(uint64_t(value));
909  }
910 
911  }; // class packed_field_varint
912 
913  template <typename T>
914  class packed_field_svarint : public packed_field {
915 
916  public:
917 
918  template <typename P>
919  packed_field_svarint(pbf_writer& parent_writer, P tag) :
920  packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
921  }
922 
923  void add_element(T value) {
924  m_writer.add_varint(encode_zigzag64(value));
925  }
926 
927  }; // class packed_field_svarint
928 
929 } // end namespace detail
930 
932 using packed_field_bool = detail::packed_field_varint<bool>;
933 
935 using packed_field_enum = detail::packed_field_varint<int32_t>;
936 
938 using packed_field_int32 = detail::packed_field_varint<int32_t>;
939 
941 using packed_field_sint32 = detail::packed_field_svarint<int32_t>;
942 
944 using packed_field_uint32 = detail::packed_field_varint<uint32_t>;
945 
947 using packed_field_int64 = detail::packed_field_varint<int64_t>;
948 
950 using packed_field_sint64 = detail::packed_field_svarint<int64_t>;
951 
953 using packed_field_uint64 = detail::packed_field_varint<uint64_t>;
954 
956 using packed_field_fixed32 = detail::packed_field_fixed<uint32_t>;
957 
959 using packed_field_sfixed32 = detail::packed_field_fixed<int32_t>;
960 
962 using packed_field_fixed64 = detail::packed_field_fixed<uint64_t>;
963 
965 using packed_field_sfixed64 = detail::packed_field_fixed<int64_t>;
966 
968 using packed_field_float = detail::packed_field_fixed<float>;
969 
971 using packed_field_double = detail::packed_field_fixed<double>;
972 
973 } // end namespace protozero
974 
975 #endif // PROTOZERO_PBF_WRITER_HPP
void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:778
void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:678
detail::packed_field_fixed< float > packed_field_float
Class for generating packed repeated float fields.
Definition: pbf_writer.hpp:968
void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:720
void add_string(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:584
void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:793
void rollback()
Definition: pbf_writer.hpp:308
void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:763
constexpr uint64_t encode_zigzag64(int64_t value) noexcept
Definition: varint.hpp:167
void reserve(std::size_t size)
Definition: pbf_writer.hpp:296
void add_sint64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:389
void add_message(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:595
detail::packed_field_varint< int64_t > packed_field_int64
Class for generating packed repeated int64 fields.
Definition: pbf_writer.hpp:947
void add_sfixed64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:442
void add_uint32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:369
void add_bytes(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:500
void add_string(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:553
void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:650
detail::packed_field_fixed< int64_t > packed_field_sfixed64
Class for generating packed repeated sfixed64 fields.
Definition: pbf_writer.hpp:965
void add_message(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:605
Definition: pbf_writer.hpp:51
void add_int64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:379
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:932
detail::packed_field_fixed< double > packed_field_double
Class for generating packed repeated double fields.
Definition: pbf_writer.hpp:971
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:349
void add_string(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:573
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:137
void add_uint64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:399
constexpr std::size_t size() const noexcept
Return length of data in bytes.
Definition: types.hpp:138
void add_string(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:563
detail::packed_field_varint< int32_t > packed_field_int32
Class for generating packed repeated int32 fields.
Definition: pbf_writer.hpp:938
pbf_wire_type
Definition: types.hpp:40
void add_message(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:615
void add_float(pbf_tag_type tag, float value)
Definition: pbf_writer.hpp:453
void swap(pbf_writer &other) noexcept
Definition: pbf_writer.hpp:280
void add_enum(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:339
detail::packed_field_svarint< int64_t > packed_field_sint64
Class for generating packed repeated sint64 fields.
Definition: pbf_writer.hpp:950
void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:734
pbf_writer() noexcept
Definition: pbf_writer.hpp:236
void add_bytes_vectored(pbf_tag_type tag, Ts &&... values)
Definition: pbf_writer.hpp:535
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:692
void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:706
void add_fixed64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:431
uint32_t pbf_length_type
Definition: types.hpp:63
void add_bool(pbf_tag_type tag, bool value)
Definition: pbf_writer.hpp:326
void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:636
detail::packed_field_fixed< uint64_t > packed_field_fixed64
Class for generating packed repeated fixed64 fields.
Definition: pbf_writer.hpp:962
detail::packed_field_fixed< int32_t > packed_field_sfixed32
Class for generating packed repeated sfixed32 fields.
Definition: pbf_writer.hpp:959
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:944
void swap(pbf_writer &lhs, pbf_writer &rhs) noexcept
Definition: pbf_writer.hpp:842
void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:823
Definition: types.hpp:75
void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:808
detail::packed_field_varint< uint64_t > packed_field_uint64
Class for generating packed repeated uint64 fields.
Definition: pbf_writer.hpp:953
void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:664
pbf_writer(pbf_writer &parent_writer, pbf_tag_type tag, std::size_t size=0)
Definition: pbf_writer.hpp:251
constexpr const char * data() const noexcept
Return pointer to data.
Definition: types.hpp:133
void add_sfixed32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:420
pbf_writer(std::string &data) noexcept
Definition: pbf_writer.hpp:227
Contains low-level varint and zigzag encoding and decoding functions.
void add_sint32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:359
detail::packed_field_varint< int32_t > packed_field_enum
Class for generating packed repeated enum fields.
Definition: pbf_writer.hpp:935
void add_fixed32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:409
detail::packed_field_fixed< uint32_t > packed_field_fixed32
Class for generating packed repeated fixed32 fields.
Definition: pbf_writer.hpp:956
void add_bytes(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:490
void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:748
void add_double(pbf_tag_type tag, double value)
Definition: pbf_writer.hpp:464
detail::packed_field_svarint< int32_t > packed_field_sint32
Class for generating packed repeated sint32 fields.
Definition: pbf_writer.hpp:941
void add_bytes(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:511
void add_bytes(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:476
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24