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 static constexpr
const int reserve_bytes =
sizeof(
pbf_length_type) * 8 / 7 + 1;
164 static constexpr
const std::size_t size_is_known = std::numeric_limits<std::size_t>::max();
166 void open_submessage(
pbf_tag_type tag, std::size_t size) {
167 protozero_assert(m_pos == 0);
168 protozero_assert(m_data);
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');
174 m_rollback_pos = size_is_known;
178 m_pos = m_data->size();
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);
189 void commit_submessage() {
190 protozero_assert(m_pos != 0);
191 protozero_assert(m_rollback_pos != size_is_known);
192 protozero_assert(m_data);
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);
198 m_data->erase(m_data->begin() + long(m_pos) - reserve_bytes + n, m_data->begin() + long(m_pos));
202 void close_submessage() {
203 protozero_assert(m_data);
204 if (m_pos == 0 || m_rollback_pos == size_is_known) {
207 if (m_data->size() - m_pos == 0) {
208 rollback_submessage();
215 add_field(tag, pbf_wire_type::length_delimited);
228 m_parent_writer(
nullptr),
238 m_parent_writer(
nullptr),
253 m_data(parent_writer.m_data),
254 m_parent_writer(&parent_writer),
256 m_parent_writer->open_submessage(tag, size);
272 if (m_parent_writer) {
273 m_parent_writer->close_submessage();
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);
299 protozero_assert(m_data);
300 m_data->reserve(m_data->size() + size);
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();
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);
342 add_tagged_varint(tag, uint64_t(value));
352 add_tagged_varint(tag, uint64_t(value));
372 add_tagged_varint(tag, value);
382 add_tagged_varint(tag, uint64_t(value));
402 add_tagged_varint(tag, value);
412 add_field(tag, pbf_wire_type::fixed32);
413 add_fixed<uint32_t>(value);
423 add_field(tag, pbf_wire_type::fixed32);
424 add_fixed<int32_t>(value);
434 add_field(tag, pbf_wire_type::fixed64);
435 add_fixed<uint64_t>(value);
445 add_field(tag, pbf_wire_type::fixed64);
446 add_fixed<int64_t>(value);
456 add_field(tag, pbf_wire_type::fixed32);
457 add_fixed<float>(value);
467 add_field(tag, pbf_wire_type::fixed64);
468 add_fixed<double>(value);
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());
483 m_data->append(value, size);
493 add_bytes(tag, value.
data(), value.
size());
503 add_bytes(tag, value.data(), value.size());
514 add_bytes(tag, value, size);
524 add_bytes(tag, value.
data(), value.
size());
534 add_bytes(tag, value.data(), value.size());
545 add_bytes(tag, value, std::strlen(value));
556 add_bytes(tag, value, size);
566 add_bytes(tag, value.
data(), value.
size());
576 add_bytes(tag, value.data(), value.size());
595 template <
typename InputIterator>
597 add_packed_varint(tag, first, last);
609 template <
typename InputIterator>
611 add_packed_varint(tag, first, last);
623 template <
typename InputIterator>
625 add_packed_varint(tag, first, last);
637 template <
typename InputIterator>
639 add_packed_svarint(tag, first, last);
651 template <
typename InputIterator>
653 add_packed_varint(tag, first, last);
665 template <
typename InputIterator>
667 add_packed_varint(tag, first, last);
679 template <
typename InputIterator>
681 add_packed_svarint(tag, first, last);
693 template <
typename InputIterator>
695 add_packed_varint(tag, first, last);
707 template <
typename InputIterator>
709 add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
710 typename std::iterator_traits<InputIterator>::iterator_category());
722 template <
typename InputIterator>
724 add_packed_fixed<int32_t, InputIterator>(tag, first, last,
725 typename std::iterator_traits<InputIterator>::iterator_category());
737 template <
typename InputIterator>
739 add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
740 typename std::iterator_traits<InputIterator>::iterator_category());
752 template <
typename InputIterator>
754 add_packed_fixed<int64_t, InputIterator>(tag, first, last,
755 typename std::iterator_traits<InputIterator>::iterator_category());
767 template <
typename InputIterator>
769 add_packed_fixed<float, InputIterator>(tag, first, last,
770 typename std::iterator_traits<InputIterator>::iterator_category());
782 template <
typename InputIterator>
784 add_packed_fixed<double, InputIterator>(tag, first, last,
785 typename std::iterator_traits<InputIterator>::iterator_category());
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;
817 m_writer(parent_writer, tag) {
821 m_writer(parent_writer, tag, size) {
830 template <
typename T>
831 class packed_field_fixed :
public packed_field {
836 packed_field(parent_writer, tag) {
840 packed_field(parent_writer, tag, size *
sizeof(T)) {
843 void add_element(T value) {
844 m_writer.add_fixed<T>(value);
849 template <
typename T>
850 class packed_field_varint :
public packed_field {
855 packed_field(parent_writer, tag) {
858 void add_element(T value) {
859 m_writer.add_varint(uint64_t(value));
864 template <
typename T>
865 class packed_field_svarint :
public packed_field {
870 packed_field(parent_writer, tag) {
873 void add_element(T value) {
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
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