1 #ifndef PROTOZERO_PBF_WRITER_HPP 2 #define PROTOZERO_PBF_WRITER_HPP 31 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN 39 template <
typename T>
class packed_field_varint;
40 template <
typename T>
class packed_field_svarint;
41 template <
typename T>
class packed_field_fixed;
66 std::size_t m_rollback_pos = 0;
70 std::size_t m_pos = 0;
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);
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);
84 void add_tagged_varint(
pbf_tag_type tag, uint64_t value) {
85 add_field(tag, pbf_wire_type::varint);
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);
96 m_data->append(reinterpret_cast<const char*>(&value),
sizeof(T));
99 template <
typename T,
typename It>
100 void add_packed_fixed(
pbf_tag_type tag, It first, It last, std::input_iterator_tag) {
107 while (first != last) {
108 sw.add_fixed<T>(*first++);
112 template <
typename T,
typename It>
113 void add_packed_fixed(
pbf_tag_type tag, It first, It last, std::forward_iterator_tag) {
118 const auto length = std::distance(first, last);
120 reserve(
sizeof(T) * std::size_t(length));
122 while (first != last) {
123 add_fixed<T>(*first++);
127 template <
typename It>
128 void add_packed_varint(
pbf_tag_type tag, It first, It last) {
135 while (first != last) {
136 sw.add_varint(uint64_t(*first++));
140 template <
typename It>
141 void add_packed_svarint(
pbf_tag_type tag, It first, It last) {
148 while (first != last) {
156 enum constant_reserve_bytes :
int {
163 enum constant_size_is_known : std::size_t {
164 size_is_known = std::numeric_limits<std::size_t>::max()
167 void open_submessage(
pbf_tag_type tag, std::size_t size) {
168 protozero_assert(m_pos == 0);
169 protozero_assert(m_data);
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');
175 m_rollback_pos = size_is_known;
179 m_pos = m_data->size();
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);
190 void commit_submessage() {
191 protozero_assert(m_pos != 0);
192 protozero_assert(m_rollback_pos != size_is_known);
193 protozero_assert(m_data);
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);
199 m_data->erase(m_data->begin() + long(m_pos) - reserve_bytes + n, m_data->begin() + long(m_pos));
203 void close_submessage() {
204 protozero_assert(m_data);
205 if (m_pos == 0 || m_rollback_pos == size_is_known) {
208 if (m_data->size() - m_pos == 0) {
209 rollback_submessage();
216 add_field(tag, pbf_wire_type::length_delimited);
229 m_parent_writer(
nullptr),
239 m_parent_writer(
nullptr),
254 m_data(parent_writer.m_data),
255 m_parent_writer(&parent_writer),
257 m_parent_writer->open_submessage(tag, size);
273 if (m_parent_writer) {
274 m_parent_writer->close_submessage();
285 swap(m_data, other.m_data);
286 swap(m_parent_writer, other.m_parent_writer);
287 swap(m_rollback_pos, other.m_rollback_pos);
288 swap(m_pos, other.m_pos);
300 protozero_assert(m_data);
301 m_data->reserve(m_data->size() + size);
312 protozero_assert(m_parent_writer &&
"you can't call rollback() on a pbf_writer without a parent");
313 protozero_assert(m_pos == 0 &&
"you can't call rollback() on a pbf_writer that has an open nested submessage");
314 m_parent_writer->rollback_submessage();
330 add_field(tag, pbf_wire_type::varint);
331 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");
332 protozero_assert(m_data);
333 m_data->append(1, value);
343 add_tagged_varint(tag, uint64_t(value));
353 add_tagged_varint(tag, uint64_t(value));
373 add_tagged_varint(tag, value);
383 add_tagged_varint(tag, uint64_t(value));
403 add_tagged_varint(tag, value);
413 add_field(tag, pbf_wire_type::fixed32);
414 add_fixed<uint32_t>(value);
424 add_field(tag, pbf_wire_type::fixed32);
425 add_fixed<int32_t>(value);
435 add_field(tag, pbf_wire_type::fixed64);
436 add_fixed<uint64_t>(value);
446 add_field(tag, pbf_wire_type::fixed64);
447 add_fixed<int64_t>(value);
457 add_field(tag, pbf_wire_type::fixed32);
458 add_fixed<float>(value);
468 add_field(tag, pbf_wire_type::fixed64);
469 add_fixed<double>(value);
480 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");
481 protozero_assert(m_data);
482 protozero_assert(size <= std::numeric_limits<pbf_length_type>::max());
484 m_data->append(value, size);
494 add_bytes(tag, value.
data(), value.
size());
504 add_bytes(tag, value.data(), value.size());
515 add_bytes(tag, value, size);
525 add_bytes(tag, value.
data(), value.
size());
535 add_bytes(tag, value.data(), value.size());
546 add_bytes(tag, value, std::strlen(value));
557 add_bytes(tag, value, size);
567 add_bytes(tag, value.
data(), value.
size());
577 add_bytes(tag, value.data(), value.size());
596 template <
typename InputIterator>
598 add_packed_varint(tag, first, last);
610 template <
typename InputIterator>
612 add_packed_varint(tag, first, last);
624 template <
typename InputIterator>
626 add_packed_varint(tag, first, last);
638 template <
typename InputIterator>
640 add_packed_svarint(tag, first, last);
652 template <
typename InputIterator>
654 add_packed_varint(tag, first, last);
666 template <
typename InputIterator>
668 add_packed_varint(tag, first, last);
680 template <
typename InputIterator>
682 add_packed_svarint(tag, first, last);
694 template <
typename InputIterator>
696 add_packed_varint(tag, first, last);
708 template <
typename InputIterator>
710 add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
711 typename std::iterator_traits<InputIterator>::iterator_category());
723 template <
typename InputIterator>
725 add_packed_fixed<int32_t, InputIterator>(tag, first, last,
726 typename std::iterator_traits<InputIterator>::iterator_category());
738 template <
typename InputIterator>
740 add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
741 typename std::iterator_traits<InputIterator>::iterator_category());
753 template <
typename InputIterator>
755 add_packed_fixed<int64_t, InputIterator>(tag, first, last,
756 typename std::iterator_traits<InputIterator>::iterator_category());
768 template <
typename InputIterator>
770 add_packed_fixed<float, InputIterator>(tag, first, last,
771 typename std::iterator_traits<InputIterator>::iterator_category());
783 template <
typename InputIterator>
785 add_packed_fixed<double, InputIterator>(tag, first, last,
786 typename std::iterator_traits<InputIterator>::iterator_category());
791 template <
typename T>
friend class detail::packed_field_varint;
792 template <
typename T>
friend class detail::packed_field_svarint;
793 template <
typename T>
friend class detail::packed_field_fixed;
818 m_writer(parent_writer, tag) {
822 m_writer(parent_writer, tag, size) {
831 template <
typename T>
832 class packed_field_fixed :
public packed_field {
837 packed_field(parent_writer, tag) {
841 packed_field(parent_writer, tag, size *
sizeof(T)) {
844 void add_element(T value) {
845 m_writer.add_fixed<T>(value);
850 template <
typename T>
851 class packed_field_varint :
public packed_field {
856 packed_field(parent_writer, tag) {
859 void add_element(T value) {
860 m_writer.add_varint(uint64_t(value));
865 template <
typename T>
866 class packed_field_svarint :
public packed_field {
871 packed_field(parent_writer, tag) {
874 void add_element(T value) {
926 #endif // PROTOZERO_PBF_WRITER_HPP void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:739
void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:639
detail::packed_field_fixed< float > packed_field_float
Class for generating packed repeated float fields.
Definition: pbf_writer.hpp:919
void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:681
void add_string(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:545
void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:754
void rollback()
Definition: pbf_writer.hpp:311
void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:724
void reserve(std::size_t size)
Definition: pbf_writer.hpp:299
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:392
void add_message(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:556
detail::packed_field_varint< int64_t > packed_field_int64
Class for generating packed repeated int64 fields.
Definition: pbf_writer.hpp:898
void add_sfixed64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:445
void add_uint32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:372
void add_bytes(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:503
void add_string(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:514
void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:611
detail::packed_field_fixed< int64_t > packed_field_sfixed64
Class for generating packed repeated sfixed64 fields.
Definition: pbf_writer.hpp:916
void add_message(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:566
Definition: pbf_writer.hpp:51
void add_int64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:382
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:883
detail::packed_field_fixed< double > packed_field_double
Class for generating packed repeated double fields.
Definition: pbf_writer.hpp:922
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:352
void add_string(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:534
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:402
constexpr std::size_t size() const noexcept
Return length of data in bytes.
Definition: types.hpp:126
void add_string(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:524
detail::packed_field_varint< int32_t > packed_field_int32
Class for generating packed repeated int32 fields.
Definition: pbf_writer.hpp:889
pbf_wire_type
Definition: types.hpp:39
void add_message(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:576
void add_float(pbf_tag_type tag, float value)
Definition: pbf_writer.hpp:456
void swap(pbf_writer &other) noexcept
Definition: pbf_writer.hpp:283
void add_enum(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:342
detail::packed_field_svarint< int64_t > packed_field_sint64
Class for generating packed repeated sint64 fields.
Definition: pbf_writer.hpp:901
void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:695
pbf_writer() noexcept
Definition: pbf_writer.hpp:237
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:653
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:667
void add_fixed64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:434
uint32_t pbf_length_type
Definition: types.hpp:51
void add_bool(pbf_tag_type tag, bool value)
Definition: pbf_writer.hpp:329
void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:597
detail::packed_field_fixed< uint64_t > packed_field_fixed64
Class for generating packed repeated fixed64 fields.
Definition: pbf_writer.hpp:913
detail::packed_field_fixed< int32_t > packed_field_sfixed32
Class for generating packed repeated sfixed32 fields.
Definition: pbf_writer.hpp:910
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:895
void swap(pbf_writer &lhs, pbf_writer &rhs) noexcept
Definition: pbf_writer.hpp:803
void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:784
void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:769
detail::packed_field_varint< uint64_t > packed_field_uint64
Class for generating packed repeated uint64 fields.
Definition: pbf_writer.hpp:904
void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:625
pbf_writer(pbf_writer &parent_writer, pbf_tag_type tag, std::size_t size=0)
Definition: pbf_writer.hpp:253
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:423
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:362
detail::packed_field_varint< int32_t > packed_field_enum
Class for generating packed repeated enum fields.
Definition: pbf_writer.hpp:886
void add_fixed32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:412
detail::packed_field_fixed< uint32_t > packed_field_fixed32
Class for generating packed repeated fixed32 fields.
Definition: pbf_writer.hpp:907
void add_bytes(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:493
void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:709
void add_double(pbf_tag_type tag, double value)
Definition: pbf_writer.hpp:467
detail::packed_field_svarint< int32_t > packed_field_sint32
Class for generating packed repeated sint32 fields.
Definition: pbf_writer.hpp:892
void add_bytes(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:479
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24