1 #ifndef PROTOZERO_PBF_WRITER_HPP 2 #define PROTOZERO_PBF_WRITER_HPP 30 #if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN 65 std::size_t m_rollback_pos = 0;
69 std::size_t m_pos = 0;
71 inline void add_varint(uint64_t value) {
72 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");
73 protozero_assert(m_data);
78 protozero_assert(((tag > 0 && tag < 19000) || (tag > 19999 && tag <= ((1 << 29) - 1))) &&
"tag out of range");
79 uint32_t b = (tag << 3) | uint32_t(type);
83 inline void add_tagged_varint(
pbf_tag_type tag, uint64_t value) {
84 add_field(tag, pbf_wire_type::varint);
89 inline void add_fixed(T value) {
90 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");
91 protozero_assert(m_data);
92 #if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN 93 m_data->append(reinterpret_cast<const char*>(&value),
sizeof(T));
95 auto size = m_data->size();
96 m_data->resize(size +
sizeof(T));
97 byteswap<sizeof(T)>(
reinterpret_cast<const char*
>(&value), const_cast<char*>(m_data->data() + size));
101 template <
typename T,
typename It>
102 inline void add_packed_fixed(
pbf_tag_type tag, It first, It last, std::input_iterator_tag) {
109 while (first != last) {
110 sw.add_fixed<T>(*first++);
114 template <
typename T,
typename It>
115 inline void add_packed_fixed(
pbf_tag_type tag, It first, It last, std::forward_iterator_tag) {
120 auto length = std::distance(first, last);
122 reserve(
sizeof(T) * std::size_t(length));
124 while (first != last) {
125 add_fixed<T>(*first++);
129 template <
typename It>
130 inline void add_packed_varint(
pbf_tag_type tag, It first, It last) {
137 while (first != last) {
138 sw.add_varint(uint64_t(*first++));
142 template <
typename It>
143 inline void add_packed_svarint(
pbf_tag_type tag, It first, It last) {
150 while (first != last) {
163 static const std::size_t size_is_known = std::numeric_limits<std::size_t>::max();
165 inline void open_submessage(
pbf_tag_type tag, std::size_t size) {
166 protozero_assert(m_pos == 0);
167 protozero_assert(m_data);
169 m_rollback_pos = m_data->size();
170 add_field(tag, pbf_wire_type::length_delimited);
171 m_data->append(std::size_t(reserve_bytes),
'\0');
173 m_rollback_pos = size_is_known;
177 m_pos = m_data->size();
180 inline void rollback_submessage() {
181 protozero_assert(m_pos != 0);
182 protozero_assert(m_rollback_pos != size_is_known);
183 protozero_assert(m_data);
184 m_data->resize(m_rollback_pos);
188 inline void commit_submessage() {
189 protozero_assert(m_pos != 0);
190 protozero_assert(m_rollback_pos != size_is_known);
191 protozero_assert(m_data);
194 protozero_assert(m_data->size() >= m_pos - reserve_bytes);
195 auto n =
write_varint(m_data->begin() + long(m_pos) - reserve_bytes, length);
197 m_data->erase(m_data->begin() + long(m_pos) - reserve_bytes + n, m_data->begin() + long(m_pos));
201 inline void close_submessage() {
202 protozero_assert(m_data);
203 if (m_pos == 0 || m_rollback_pos == size_is_known) {
206 if (m_data->size() - m_pos == 0) {
207 rollback_submessage();
214 add_field(tag, pbf_wire_type::length_delimited);
227 m_parent_writer(
nullptr),
237 m_parent_writer(
nullptr),
252 m_data(parent_writer.m_data),
253 m_parent_writer(&parent_writer),
255 m_parent_writer->open_submessage(tag, size);
271 if (m_parent_writer) {
272 m_parent_writer->close_submessage();
285 protozero_assert(m_data);
286 m_data->reserve(m_data->size() + size);
289 inline void rollback() {
290 protozero_assert(m_parent_writer &&
"you can't call rollback() on a pbf_writer without a parent");
291 protozero_assert(m_pos == 0 &&
"you can't call rollback() on a pbf_writer that has an open nested submessage");
292 m_parent_writer->rollback_submessage();
308 add_field(tag, pbf_wire_type::varint);
309 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");
310 protozero_assert(m_data);
311 m_data->append(1, value);
321 add_tagged_varint(tag, uint64_t(value));
331 add_tagged_varint(tag, uint64_t(value));
351 add_tagged_varint(tag, value);
361 add_tagged_varint(tag, uint64_t(value));
381 add_tagged_varint(tag, value);
391 add_field(tag, pbf_wire_type::fixed32);
392 add_fixed<uint32_t>(value);
402 add_field(tag, pbf_wire_type::fixed32);
403 add_fixed<int32_t>(value);
413 add_field(tag, pbf_wire_type::fixed64);
414 add_fixed<uint64_t>(value);
424 add_field(tag, pbf_wire_type::fixed64);
425 add_fixed<int64_t>(value);
435 add_field(tag, pbf_wire_type::fixed32);
436 add_fixed<float>(value);
446 add_field(tag, pbf_wire_type::fixed64);
447 add_fixed<double>(value);
458 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");
459 protozero_assert(m_data);
460 protozero_assert(size <= std::numeric_limits<pbf_length_type>::max());
462 m_data->append(value, size);
472 add_bytes(tag, value.data(), value.size());
483 add_bytes(tag, value, size);
493 add_bytes(tag, value.data(), value.size());
504 add_bytes(tag, value, std::strlen(value));
515 add_bytes(tag, value, size);
525 add_bytes(tag, value.data(), value.size());
544 template <
typename InputIterator>
546 add_packed_varint(tag, first, last);
558 template <
typename InputIterator>
560 add_packed_varint(tag, first, last);
572 template <
typename InputIterator>
574 add_packed_varint(tag, first, last);
586 template <
typename InputIterator>
588 add_packed_svarint(tag, first, last);
600 template <
typename InputIterator>
602 add_packed_varint(tag, first, last);
614 template <
typename InputIterator>
616 add_packed_varint(tag, first, last);
628 template <
typename InputIterator>
630 add_packed_svarint(tag, first, last);
642 template <
typename InputIterator>
644 add_packed_varint(tag, first, last);
656 template <
typename InputIterator>
658 add_packed_fixed<uint32_t, InputIterator>(tag, first, last,
659 typename std::iterator_traits<InputIterator>::iterator_category());
671 template <
typename InputIterator>
673 add_packed_fixed<int32_t, InputIterator>(tag, first, last,
674 typename std::iterator_traits<InputIterator>::iterator_category());
686 template <
typename InputIterator>
688 add_packed_fixed<uint64_t, InputIterator>(tag, first, last,
689 typename std::iterator_traits<InputIterator>::iterator_category());
701 template <
typename InputIterator>
703 add_packed_fixed<int64_t, InputIterator>(tag, first, last,
704 typename std::iterator_traits<InputIterator>::iterator_category());
716 template <
typename InputIterator>
718 add_packed_fixed<float, InputIterator>(tag, first, last,
719 typename std::iterator_traits<InputIterator>::iterator_category());
731 template <
typename InputIterator>
733 add_packed_fixed<double, InputIterator>(tag, first, last,
734 typename std::iterator_traits<InputIterator>::iterator_category());
756 m_writer(parent_writer, tag) {
760 m_writer(parent_writer, tag, size) {
769 template <
typename T>
782 void add_element(T value) {
783 m_writer.add_fixed<T>(value);
788 template <
typename T>
797 void add_element(T value) {
798 m_writer.add_varint(uint64_t(value));
803 template <
typename T>
812 void add_element(T value) {
837 #endif // PROTOZERO_PBF_WRITER_HPP void add_packed_fixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:687
void add_packed_sint32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:587
void add_packed_sint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:629
void add_string(pbf_tag_type tag, const char *value)
Definition: pbf_writer.hpp:503
void add_packed_sfixed64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:702
void add_packed_sfixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:672
uint32_t pbf_length_type
Definition: types.hpp:45
void reserve(std::size_t size)
Definition: pbf_writer.hpp:284
uint64_t encode_zigzag64(int64_t value) noexcept
Definition: varint.hpp:112
void add_sint64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:370
void add_message(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:514
void add_sfixed64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:423
void add_uint32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:350
void add_bytes(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:471
void add_string(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:482
void add_packed_enum(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:559
Definition: pbf_writer.hpp:50
void add_int64(pbf_tag_type tag, int64_t value)
Definition: pbf_writer.hpp:360
Contains macro checks for different configurations.
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:330
Definition: pbf_writer.hpp:38
void add_string(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:492
void add_uint64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:380
pbf_wire_type
Definition: types.hpp:33
void add_message(pbf_tag_type tag, const std::string &value)
Definition: pbf_writer.hpp:524
void add_float(pbf_tag_type tag, float value)
Definition: pbf_writer.hpp:434
uint32_t pbf_tag_type
Definition: types.hpp:26
void add_enum(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:320
void add_packed_uint64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:643
pbf_writer() noexcept
Definition: pbf_writer.hpp:235
Definition: pbf_writer.hpp:39
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:601
uint32_t encode_zigzag32(int32_t value) noexcept
Definition: varint.hpp:105
void add_packed_int64(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:615
void add_fixed64(pbf_tag_type tag, uint64_t value)
Definition: pbf_writer.hpp:412
void add_bool(pbf_tag_type tag, bool value)
Definition: pbf_writer.hpp:307
void add_packed_bool(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:545
void add_packed_double(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:732
int write_varint(OutputIterator data, uint64_t value)
Definition: varint.hpp:89
void add_packed_float(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:717
void add_packed_int32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:573
pbf_writer(pbf_writer &parent_writer, pbf_tag_type tag, std::size_t size=0)
Definition: pbf_writer.hpp:251
void add_sfixed32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:401
pbf_writer(std::string &data) noexcept
Definition: pbf_writer.hpp:225
Contains low-level varint and zigzag encoding and decoding functions.
Definition: pbf_writer.hpp:40
void add_sint32(pbf_tag_type tag, int32_t value)
Definition: pbf_writer.hpp:340
void add_fixed32(pbf_tag_type tag, uint32_t value)
Definition: pbf_writer.hpp:390
Definition: pbf_writer.hpp:747
void add_packed_fixed32(pbf_tag_type tag, InputIterator first, InputIterator last)
Definition: pbf_writer.hpp:657
void add_double(pbf_tag_type tag, double value)
Definition: pbf_writer.hpp:445
void add_bytes(pbf_tag_type tag, const char *value, std::size_t size)
Definition: pbf_writer.hpp:457
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:24