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 m_data->append(reinterpret_cast<const char*>(&value),
sizeof(T));
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));
102 template <
typename T,
typename It>
103 void add_packed_fixed(
pbf_tag_type tag, It first, It last, std::input_iterator_tag) {
110 while (first != last) {
111 sw.add_fixed<T>(*first++);
115 template <
typename T,
typename It>
116 void add_packed_fixed(
pbf_tag_type tag, It first, It last, std::forward_iterator_tag) {
121 const auto length = std::distance(first, last);
123 reserve(
sizeof(T) * std::size_t(length));
125 while (first != last) {
126 add_fixed<T>(*first++);
130 template <
typename It>
131 void add_packed_varint(
pbf_tag_type tag, It first, It last) {
138 while (first != last) {
139 sw.add_varint(uint64_t(*first++));
143 template <
typename It>
144 void add_packed_svarint(
pbf_tag_type tag, It first, It last) {
151 while (first != last) {
159 enum constant_reserve_bytes :
int {
166 enum constant_size_is_known : std::size_t {
167 size_is_known = std::numeric_limits<std::size_t>::max()
170 void open_submessage(
pbf_tag_type tag, std::size_t size) {
171 protozero_assert(m_pos == 0);
172 protozero_assert(m_data);
174 m_rollback_pos = m_data->size();
175 add_field(tag, pbf_wire_type::length_delimited);
176 m_data->append(std::size_t(reserve_bytes),
'\0');
178 m_rollback_pos = size_is_known;
182 m_pos = m_data->size();
185 void rollback_submessage() {
186 protozero_assert(m_pos != 0);
187 protozero_assert(m_rollback_pos != size_is_known);
188 protozero_assert(m_data);
189 m_data->resize(m_rollback_pos);
193 void commit_submessage() {
194 protozero_assert(m_pos != 0);
195 protozero_assert(m_rollback_pos != size_is_known);
196 protozero_assert(m_data);
199 protozero_assert(m_data->size() >= m_pos - reserve_bytes);
200 const auto n =
write_varint(m_data->begin() + long(m_pos) - reserve_bytes, length);
202 m_data->erase(m_data->begin() + long(m_pos) - reserve_bytes + n, m_data->begin() + long(m_pos));
206 void close_submessage() {
207 protozero_assert(m_data);
208 if (m_pos == 0 || m_rollback_pos == size_is_known) {
211 if (m_data->size() - m_pos == 0) {
212 rollback_submessage();
219 add_field(tag, pbf_wire_type::length_delimited);
232 m_parent_writer(
nullptr),
242 m_parent_writer(
nullptr),
257 m_data(parent_writer.m_data),
258 m_parent_writer(&parent_writer),
260 m_parent_writer->open_submessage(tag, size);
276 if (m_parent_writer) {
277 m_parent_writer->close_submessage();
288 swap(m_data, other.m_data);
289 swap(m_parent_writer, other.m_parent_writer);
290 swap(m_rollback_pos, other.m_rollback_pos);
291 swap(m_pos, other.m_pos);
303 protozero_assert(m_data);
304 m_data->reserve(m_data->size() + size);
315 protozero_assert(m_parent_writer &&
"you can't call rollback() on a pbf_writer without a parent");
316 protozero_assert(m_pos == 0 &&
"you can't call rollback() on a pbf_writer that has an open nested submessage");
317 m_parent_writer->rollback_submessage();
333 add_field(tag, pbf_wire_type::varint);
334 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");
335 protozero_assert(m_data);
336 m_data->append(1, value);
346 add_tagged_varint(tag, uint64_t(value));
356 add_tagged_varint(tag, uint64_t(value));
376 add_tagged_varint(tag, value);
386 add_tagged_varint(tag, uint64_t(value));
406 add_tagged_varint(tag, value);
416 add_field(tag, pbf_wire_type::fixed32);
417 add_fixed<uint32_t>(value);
427 add_field(tag, pbf_wire_type::fixed32);
428 add_fixed<int32_t>(value);
438 add_field(tag, pbf_wire_type::fixed64);
439 add_fixed<uint64_t>(value);
449 add_field(tag, pbf_wire_type::fixed64);
450 add_fixed<int64_t>(value);
460 add_field(tag, pbf_wire_type::fixed32);
461 add_fixed<float>(value);
471 add_field(tag, pbf_wire_type::fixed64);
472 add_fixed<double>(value);
483 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");
484 protozero_assert(m_data);
485 protozero_assert(size <= std::numeric_limits<pbf_length_type>::max());
487 m_data->append(value, size);
497 add_bytes(tag, value.
data(), value.
size());
507 add_bytes(tag, value.data(), value.size());
518 add_bytes(tag, value, size);
528 add_bytes(tag, value.
data(), value.
size());
538 add_bytes(tag, value.data(), value.size());
549 add_bytes(tag, value, std::strlen(value));
560 add_bytes(tag, value, size);
570 add_bytes(tag, value.
data(), value.
size());
580 add_bytes(tag, value.data(), value.size());
599 template <
typename InputIterator>
601 add_packed_varint(tag, first, last);
613 template <
typename InputIterator>
615 add_packed_varint(tag, first, last);
627 template <
typename InputIterator>
629 add_packed_varint(tag, first, last);
641 template <
typename InputIterator>
643 add_packed_svarint(tag, first, last);
655 template <
typename InputIterator>
657 add_packed_varint(tag, first, last);
669 template <
typename InputIterator>
671 add_packed_varint(tag, first, last);
683 template <
typename InputIterator>
685 add_packed_svarint(tag, first, last);
697 template <
typename InputIterator>
699 add_packed_varint(tag, first, last);
711 template <
typename InputIterator>
713 add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
714 typename std::iterator_traits<InputIterator>::iterator_category());
726 template <
typename InputIterator>
728 add_packed_fixed<int32_t, InputIterator>(tag, first, last,
729 typename std::iterator_traits<InputIterator>::iterator_category());
741 template <
typename InputIterator>
743 add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
744 typename std::iterator_traits<InputIterator>::iterator_category());
756 template <
typename InputIterator>
758 add_packed_fixed<int64_t, InputIterator>(tag, first, last,
759 typename std::iterator_traits<InputIterator>::iterator_category());
771 template <
typename InputIterator>
773 add_packed_fixed<float, InputIterator>(tag, first, last,
774 typename std::iterator_traits<InputIterator>::iterator_category());
786 template <
typename InputIterator>
788 add_packed_fixed<double, InputIterator>(tag, first, last,
789 typename std::iterator_traits<InputIterator>::iterator_category());
794 template <
typename T>
friend class detail::packed_field_varint;
795 template <
typename T>
friend class detail::packed_field_svarint;
796 template <
typename T>
friend class detail::packed_field_fixed;
821 m_writer(parent_writer, tag) {
825 m_writer(parent_writer, tag, size) {
834 template <
typename T>
835 class packed_field_fixed :
public packed_field {
840 packed_field(parent_writer, tag) {
844 packed_field(parent_writer, tag, size *
sizeof(T)) {
847 void add_element(T value) {
848 m_writer.add_fixed<T>(value);
853 template <
typename T>
854 class packed_field_varint :
public packed_field {
859 packed_field(parent_writer, tag) {
862 void add_element(T value) {
863 m_writer.add_varint(uint64_t(value));
868 template <
typename T>
869 class packed_field_svarint :
public packed_field {
874 packed_field(parent_writer, tag) {
877 void add_element(T value) {
929 #endif // PROTOZERO_PBF_WRITER_HPP void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:742
void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:642
detail::packed_field_fixed< float > packed_field_float
Class for generating packed repeated float fields.
Definition: pbf_writer.hpp:922
void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:684
void add_string(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:548
void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:757
void rollback()
Definition: pbf_writer.hpp:314
void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:727
void reserve(std::size_t size)
Definition: pbf_writer.hpp:302
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:395
void add_message(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:559
detail::packed_field_varint< int64_t > packed_field_int64
Class for generating packed repeated int64 fields.
Definition: pbf_writer.hpp:901
void add_sfixed64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:448
void add_uint32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:375
void add_bytes(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:506
void add_string(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:517
void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:614
detail::packed_field_fixed< int64_t > packed_field_sfixed64
Class for generating packed repeated sfixed64 fields.
Definition: pbf_writer.hpp:919
void add_message(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:569
Definition: pbf_writer.hpp:51
void add_int64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:385
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:886
detail::packed_field_fixed< double > packed_field_double
Class for generating packed repeated double fields.
Definition: pbf_writer.hpp:925
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:355
void add_string(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:537
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:405
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:527
detail::packed_field_varint< int32_t > packed_field_int32
Class for generating packed repeated int32 fields.
Definition: pbf_writer.hpp:892
pbf_wire_type
Definition: types.hpp:39
void add_message(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:579
void add_float(pbf_tag_type tag, float value)
Definition: pbf_writer.hpp:459
void swap(pbf_writer &other) noexcept
Definition: pbf_writer.hpp:286
void add_enum(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:345
detail::packed_field_svarint< int64_t > packed_field_sint64
Class for generating packed repeated sint64 fields.
Definition: pbf_writer.hpp:904
void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:698
pbf_writer() noexcept
Definition: pbf_writer.hpp:240
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:656
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:670
void add_fixed64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:437
uint32_t pbf_length_type
Definition: types.hpp:51
void add_bool(pbf_tag_type tag, bool value)
Definition: pbf_writer.hpp:332
void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:600
detail::packed_field_fixed< uint64_t > packed_field_fixed64
Class for generating packed repeated fixed64 fields.
Definition: pbf_writer.hpp:916
detail::packed_field_fixed< int32_t > packed_field_sfixed32
Class for generating packed repeated sfixed32 fields.
Definition: pbf_writer.hpp:913
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:898
void swap(pbf_writer &lhs, pbf_writer &rhs) noexcept
Definition: pbf_writer.hpp:806
void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:787
void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:772
detail::packed_field_varint< uint64_t > packed_field_uint64
Class for generating packed repeated uint64 fields.
Definition: pbf_writer.hpp:907
void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:628
pbf_writer(pbf_writer &parent_writer, pbf_tag_type tag, std::size_t size=0)
Definition: pbf_writer.hpp:256
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:426
pbf_writer(std::string &data) noexcept
Definition: pbf_writer.hpp:230
Contains low-level varint and zigzag encoding and decoding functions.
void add_sint32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:365
detail::packed_field_varint< int32_t > packed_field_enum
Class for generating packed repeated enum fields.
Definition: pbf_writer.hpp:889
void add_fixed32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:415
detail::packed_field_fixed< uint32_t > packed_field_fixed32
Class for generating packed repeated fixed32 fields.
Definition: pbf_writer.hpp:910
void add_bytes(pbf_tag_type tag, const data_view &value)
Definition: pbf_writer.hpp:496
void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:712
void add_double(pbf_tag_type tag, double value)
Definition: pbf_writer.hpp:470
detail::packed_field_svarint< int32_t > packed_field_sint32
Class for generating packed repeated sint32 fields.
Definition: pbf_writer.hpp:895
void add_bytes(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:482
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24