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) {
238 m_parent_writer(
nullptr) {
252 m_data(parent_writer.m_data),
253 m_parent_writer(&parent_writer) {
254 m_parent_writer->open_submessage(tag, size);
270 if (m_parent_writer) {
271 m_parent_writer->close_submessage();
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);
297 protozero_assert(m_data);
298 m_data->reserve(m_data->size() + size);
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();
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);
340 add_tagged_varint(tag, uint64_t(value));
350 add_tagged_varint(tag, uint64_t(value));
370 add_tagged_varint(tag, value);
380 add_tagged_varint(tag, uint64_t(value));
400 add_tagged_varint(tag, value);
410 add_field(tag, pbf_wire_type::fixed32);
411 add_fixed<uint32_t>(value);
421 add_field(tag, pbf_wire_type::fixed32);
422 add_fixed<int32_t>(value);
432 add_field(tag, pbf_wire_type::fixed64);
433 add_fixed<uint64_t>(value);
443 add_field(tag, pbf_wire_type::fixed64);
444 add_fixed<int64_t>(value);
454 add_field(tag, pbf_wire_type::fixed32);
455 add_fixed<float>(value);
465 add_field(tag, pbf_wire_type::fixed64);
466 add_fixed<double>(value);
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());
481 m_data->append(value, size);
491 add_bytes(tag, value.
data(), value.
size());
501 add_bytes(tag, value.data(), value.size());
512 add_bytes(tag, value, std::strlen(value));
534 template <
typename... Ts>
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);
539 (void)std::initializer_list<size_t>{sum_size += values.size()...};
540 protozero_assert(sum_size <= std::numeric_limits<pbf_length_type>::max());
542 m_data->reserve(m_data->size() + sum_size);
543 (void)std::initializer_list<int>{(m_data->append(values.data(), values.size()), 0)...};
554 add_bytes(tag, value, size);
564 add_bytes(tag, value.
data(), value.
size());
574 add_bytes(tag, value.data(), value.size());
585 add_bytes(tag, value, std::strlen(value));
596 add_bytes(tag, value, size);
606 add_bytes(tag, value.
data(), value.
size());
616 add_bytes(tag, value.data(), value.size());
635 template <
typename InputIterator>
637 add_packed_varint(tag, first, last);
649 template <
typename InputIterator>
651 add_packed_varint(tag, first, last);
663 template <
typename InputIterator>
665 add_packed_varint(tag, first, last);
677 template <
typename InputIterator>
679 add_packed_svarint(tag, first, last);
691 template <
typename InputIterator>
693 add_packed_varint(tag, first, last);
705 template <
typename InputIterator>
707 add_packed_varint(tag, first, last);
719 template <
typename InputIterator>
721 add_packed_svarint(tag, first, last);
733 template <
typename InputIterator>
735 add_packed_varint(tag, first, last);
747 template <
typename InputIterator>
749 add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
750 typename std::iterator_traits<InputIterator>::iterator_category());
762 template <
typename InputIterator>
764 add_packed_fixed<int32_t, InputIterator>(tag, first, last,
765 typename std::iterator_traits<InputIterator>::iterator_category());
777 template <
typename InputIterator>
779 add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
780 typename std::iterator_traits<InputIterator>::iterator_category());
792 template <
typename InputIterator>
794 add_packed_fixed<int64_t, InputIterator>(tag, first, last,
795 typename std::iterator_traits<InputIterator>::iterator_category());
807 template <
typename InputIterator>
809 add_packed_fixed<float, InputIterator>(tag, first, last,
810 typename std::iterator_traits<InputIterator>::iterator_category());
822 template <
typename InputIterator>
824 add_packed_fixed<double, InputIterator>(tag, first, last,
825 typename std::iterator_traits<InputIterator>::iterator_category());
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;
856 packed_field(
const packed_field&) =
delete;
857 packed_field& operator=(
const packed_field&) =
delete;
859 packed_field(packed_field&&) =
default;
860 packed_field& operator=(packed_field&&) =
default;
863 m_writer(parent_writer, tag) {
867 m_writer(parent_writer, tag, size) {
876 template <
typename T>
877 class packed_field_fixed :
public packed_field {
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)) {
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)) {
891 void add_element(T value) {
892 m_writer.add_fixed<T>(value);
897 template <
typename T>
898 class packed_field_varint :
public packed_field {
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)) {
907 void add_element(T value) {
908 m_writer.add_varint(uint64_t(value));
913 template <
typename T>
914 class packed_field_svarint :
public packed_field {
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)) {
923 void add_element(T value) {
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
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