This commit is contained in:
Matthias Koefferlein 2024-08-11 15:51:36 +02:00
parent 0f067e1dd8
commit 7357fe50e2
3 changed files with 170 additions and 295 deletions

View File

@ -360,45 +360,28 @@ inline size_t varint_encode (char *b, pb_varint v)
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
ProtocolBufferWriter::ProtocolBufferWriter (tl::OutputStream &stream) ProtocolBufferWriterBase::ProtocolBufferWriterBase ()
: mp_stream (&stream), m_bytes_counted (0) : m_bytes_counted (0)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
void ProtocolBufferWriter::write (int tag, float v) ProtocolBufferWriterBase::~ProtocolBufferWriterBase ()
{
// .. nothing yet ..
}
void ProtocolBufferWriterBase::write (int tag, float v)
{ {
write (tag, *reinterpret_cast<uint32_t *> (&v), true); write (tag, *reinterpret_cast<uint32_t *> (&v), true);
} }
void ProtocolBufferWriter::write (int tag, double v) void ProtocolBufferWriterBase::write (int tag, double v)
{ {
write (tag, *reinterpret_cast<uint64_t *> (&v), true); write (tag, *reinterpret_cast<uint64_t *> (&v), true);
} }
void ProtocolBufferWriter::write (int tag, uint32_t v, bool fixed) void ProtocolBufferWriterBase::write (int tag, int32_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I32), true);
if (is_counting ()) {
m_byte_counter_stack.back () += sizeof (v);
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
mp_stream->put (b, sizeof (v));
}
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v));
}
}
void ProtocolBufferWriter::write (int tag, int32_t v, bool fixed)
{ {
if (fixed) { if (fixed) {
write (tag, uint32_t (v), true); write (tag, uint32_t (v), true);
@ -407,29 +390,7 @@ void ProtocolBufferWriter::write (int tag, int32_t v, bool fixed)
} }
} }
void ProtocolBufferWriter::write (int tag, uint64_t v, bool fixed) void ProtocolBufferWriterBase::write (int tag, int64_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I64), true);
if (is_counting ()) {
m_byte_counter_stack.back () += sizeof (v);
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
mp_stream->put (b, sizeof (v));
}
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v));
}
}
void ProtocolBufferWriter::write (int tag, int64_t v, bool fixed)
{ {
if (fixed) { if (fixed) {
write (tag, uint64_t (v), true); write (tag, uint64_t (v), true);
@ -438,29 +399,46 @@ void ProtocolBufferWriter::write (int tag, int64_t v, bool fixed)
} }
} }
void ProtocolBufferWriter::write (int tag, bool b) void ProtocolBufferWriterBase::write (int tag, bool b)
{ {
write (tag, uint32_t (b ? 1 : 0)); write (tag, uint32_t (b ? 1 : 0));
} }
void ProtocolBufferWriter::write (int tag, const std::string &s) void ProtocolBufferWriterBase::write (int tag, uint32_t v, bool fixed)
{ {
write_varint (pb_varint ((tag << 3) + PB_LEN), true); if (fixed) {
write_varint (s.size ()); write_varint (pb_varint ((tag << 3) + PB_I32), true);
write_fixed (v);
if (is_counting ()) {
m_byte_counter_stack.back () += s.size ();
} else { } else {
mp_stream->put (s.c_str (), s.size ()); write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v), false);
} }
} }
bool ProtocolBufferWriter::is_counting () const void ProtocolBufferWriterBase::write (int tag, uint64_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I64), true);
write_fixed (v);
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v), false);
}
}
void ProtocolBufferWriterBase::write (int tag, const std::string &s)
{
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
write_varint (s.size (), false);
write_bytes (s);
}
bool ProtocolBufferWriterBase::is_counting () const
{ {
return ! m_byte_counter_stack.empty (); return ! m_byte_counter_stack.empty ();
} }
void ProtocolBufferWriter::begin_seq (int tag, bool counting) void ProtocolBufferWriterBase::begin_seq (int tag, bool counting)
{ {
if (counting) { if (counting) {
@ -473,12 +451,12 @@ void ProtocolBufferWriter::begin_seq (int tag, bool counting)
} else { } else {
write_varint (pb_varint ((tag << 3) + PB_LEN), true); write_varint (pb_varint ((tag << 3) + PB_LEN), true);
write_varint (m_bytes_counted); write_varint (m_bytes_counted, false);
} }
} }
void ProtocolBufferWriter::end_seq () void ProtocolBufferWriterBase::end_seq ()
{ {
if (is_counting ()) { if (is_counting ()) {
@ -488,164 +466,104 @@ void ProtocolBufferWriter::end_seq ()
// just for adding the required bytes // just for adding the required bytes
if (is_counting ()) { if (is_counting ()) {
m_byte_counter_stack.back () += m_bytes_counted; m_byte_counter_stack.back () += m_bytes_counted;
write_varint (m_bytes_counted); write_varint (m_bytes_counted, false);
} }
} }
} }
void ProtocolBufferWriterBase::add_bytes (size_t n)
{
tl_assert (! m_byte_counter_stack.empty ());
m_byte_counter_stack.back () += n;
}
// ----------------------------------------------------------------------------------
ProtocolBufferWriter::ProtocolBufferWriter (tl::OutputStream &stream)
: mp_stream (&stream)
{
// .. nothing yet ..
}
void ProtocolBufferWriter::write_fixed (uint32_t v)
{
if (is_counting ()) {
add_bytes (sizeof (v));
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
mp_stream->put (b, sizeof (v));
}
}
void ProtocolBufferWriter::write_fixed (uint64_t v)
{
if (is_counting ()) {
add_bytes (sizeof (v));
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
mp_stream->put (b, sizeof (v));
}
}
void ProtocolBufferWriter::write_bytes (const std::string &s)
{
if (is_counting ()) {
add_bytes (s.size ());
} else {
mp_stream->put (s.c_str (), s.size ());
}
}
void ProtocolBufferWriter::write_varint (pb_varint v, bool /*id*/) void ProtocolBufferWriter::write_varint (pb_varint v, bool /*id*/)
{ {
if (is_counting ()) { if (is_counting ()) {
add_bytes (count_varint_bytes (v));
m_byte_counter_stack.back () += count_varint_bytes (v);
} else { } else {
char b [max_varint_bytes]; char b [max_varint_bytes];
size_t n = varint_encode (b, v); size_t n = varint_encode (b, v);
mp_stream->put (b, n); mp_stream->put (b, n);
} }
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
ProtocolBufferDumper::ProtocolBufferDumper () ProtocolBufferDumper::ProtocolBufferDumper ()
: m_bytes_counted (0), m_debug_pos (0) : m_debug_pos (0)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
void ProtocolBufferDumper::write (int tag, float v) void ProtocolBufferDumper::write_fixed (uint32_t v)
{ {
write (tag, *reinterpret_cast<uint32_t *> (&v), true);
}
void ProtocolBufferDumper::write (int tag, double v)
{
write (tag, *reinterpret_cast<uint64_t *> (&v), true);
}
void ProtocolBufferDumper::write (int tag, uint32_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I32), true);
if (is_counting ()) {
m_byte_counter_stack.back () += sizeof (v);
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
dump (b, sizeof (v), "I32", tl::to_string (v));
}
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v));
}
}
void ProtocolBufferDumper::write (int tag, int32_t v, bool fixed)
{
if (fixed) {
write (tag, uint32_t (v), true);
} else {
write (tag, zigzag_encode (v), false);
}
}
void ProtocolBufferDumper::write (int tag, uint64_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I64), true);
if (is_counting ()) {
m_byte_counter_stack.back () += sizeof (v);
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
dump (b, sizeof (v), "I64", tl::to_string (v));
}
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v));
}
}
void ProtocolBufferDumper::write (int tag, int64_t v, bool fixed)
{
if (fixed) {
write (tag, uint64_t (v), true);
} else {
write (tag, zigzag_encode (v), false);
}
}
void ProtocolBufferDumper::write (int tag, bool b)
{
write (tag, uint32_t (b ? 1 : 0));
}
void ProtocolBufferDumper::write (int tag, const std::string &s)
{
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
write_varint (s.size ());
if (is_counting ()) { if (is_counting ()) {
add_bytes (sizeof (v));
m_byte_counter_stack.back () += s.size ();
} else { } else {
char b[sizeof (v)];
little_endian_encode (b, v);
dump (b, sizeof (v), "I32", tl::to_string (v));
}
}
void ProtocolBufferDumper::write_fixed (uint64_t v)
{
if (is_counting ()) {
add_bytes (sizeof (v));
} else {
char b[sizeof (v)];
little_endian_encode (b, v);
dump (b, sizeof (v), "I64", tl::to_string (v));
}
}
void ProtocolBufferDumper::write_bytes (const std::string &s)
{
if (is_counting ()) {
add_bytes (s.size ());
} else {
dump (s.c_str (), s.size (), "(string)", s); dump (s.c_str (), s.size (), "(string)", s);
}
}
bool ProtocolBufferDumper::is_counting () const
{
return ! m_byte_counter_stack.empty ();
}
void ProtocolBufferDumper::begin_seq (int tag, bool counting)
{
if (counting) {
if (is_counting ()) {
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
}
m_byte_counter_stack.push_back (0);
} else {
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
write_varint (m_bytes_counted);
}
}
void ProtocolBufferDumper::end_seq ()
{
if (is_counting ()) {
m_bytes_counted = m_byte_counter_stack.back ();
m_byte_counter_stack.pop_back ();
// just for adding the required bytes
if (is_counting ()) {
m_byte_counter_stack.back () += m_bytes_counted;
write_varint (m_bytes_counted);
}
} }
} }
@ -654,7 +572,7 @@ ProtocolBufferDumper::write_varint (pb_varint v, bool id)
{ {
if (is_counting ()) { if (is_counting ()) {
m_byte_counter_stack.back () += count_varint_bytes (v); add_bytes (count_varint_bytes (v));
} else { } else {

View File

@ -319,45 +319,52 @@ public:
/** /**
* @brief Constructor * @brief Constructor
*/ */
ProtocolBufferWriterBase () ProtocolBufferWriterBase ();
{
// .. nothing yet ..
}
/** /**
* @brief Destructor * @brief Destructor
*/ */
virtual ~ProtocolBufferWriterBase () virtual ~ProtocolBufferWriterBase ();
{
// .. nothing yet ..
}
/** /**
* @brief Writes a scalar tag with the given value * @brief Writes a scalar element with the given value and tag
*/ */
virtual void write (int tag, float v) = 0;
virtual void write (int tag, double v) = 0; // implicit types
virtual void write (int tag, uint32_t v, bool fixed = false) = 0; void write (int tag, float v);
virtual void write (int tag, int32_t v, bool fixed = false) = 0; void write (int tag, double v);
virtual void write (int tag, uint64_t v, bool fixed = false) = 0; void write (int tag, int32_t v, bool fixed = false);
virtual void write (int tag, int64_t v, bool fixed = false) = 0; void write (int tag, int64_t v, bool fixed = false);
virtual void write (int tag, bool b) = 0; void write (int tag, uint32_t v, bool fixed = false);
virtual void write (int tag, const std::string &s) = 0; void write (int tag, uint64_t v, bool fixed = false);
void write (int tag, bool b);
void write (int tag, const std::string &s);
/** /**
* @brief Returns true if the writer is in counting mode * @brief Returns true if the writer is in counting mode
*/ */
virtual bool is_counting () const = 0; bool is_counting () const;
/** /**
* @brief Initiates a new sequence. See class documentation for details. * @brief Initiates a new sequence. See class documentation for details.
*/ */
virtual void begin_seq (int tag, bool counting) = 0; void begin_seq (int tag, bool counting);
/** /**
* @brief Ends a sequence. See class documentation for details. * @brief Ends a sequence. See class documentation for details.
*/ */
virtual void end_seq () = 0; void end_seq ();
protected:
virtual void write_bytes (const std::string &s) = 0;
virtual void write_fixed (uint32_t v) = 0;
virtual void write_fixed (uint64_t v) = 0;
virtual void write_varint (pb_varint v, bool id) = 0;
void add_bytes (size_t n);
private:
size_t m_bytes_counted;
std::vector<size_t> m_byte_counter_stack;
}; };
/** /**
@ -376,39 +383,14 @@ public:
*/ */
ProtocolBufferWriter (tl::OutputStream &stream); ProtocolBufferWriter (tl::OutputStream &stream);
/** protected:
* @brief Writes a scalar tag with the given value virtual void write_bytes (const std::string &s);
*/ virtual void write_fixed (uint32_t v);
void write (int tag, float v); virtual void write_fixed (uint64_t v);
void write (int tag, double v); virtual void write_varint (pb_varint v, bool id = false);
void write (int tag, uint32_t v, bool fixed = false);
void write (int tag, int32_t v, bool fixed = false);
void write (int tag, uint64_t v, bool fixed = false);
void write (int tag, int64_t v, bool fixed = false);
void write (int tag, bool b);
void write (int tag, const std::string &s);
/**
* @brief Returns true if the writer is in counting mode
*/
bool is_counting () const;
/**
* @brief Initiates a new sequence. See class documentation for details.
*/
void begin_seq (int tag, bool counting);
/**
* @brief Ends a sequence. See class documentation for details.
*/
void end_seq ();
private: private:
void write_varint (pb_varint v, bool id = false);
tl::OutputStream *mp_stream; tl::OutputStream *mp_stream;
size_t m_bytes_counted;
std::vector<size_t> m_byte_counter_stack;
}; };
/** /**
@ -426,39 +408,14 @@ public:
*/ */
ProtocolBufferDumper (); ProtocolBufferDumper ();
/** protected:
* @brief Writes a scalar tag with the given value virtual void write_bytes (const std::string &s);
*/ virtual void write_fixed (uint32_t v);
void write (int tag, float v); virtual void write_fixed (uint64_t v);
void write (int tag, double v); virtual void write_varint (pb_varint v, bool id = false);
void write (int tag, uint32_t v, bool fixed = false);
void write (int tag, int32_t v, bool fixed = false);
void write (int tag, uint64_t v, bool fixed = false);
void write (int tag, int64_t v, bool fixed = false);
void write (int tag, bool b);
void write (int tag, const std::string &s);
/**
* @brief Returns true if the writer is in counting mode
*/
bool is_counting () const;
/**
* @brief Initiates a new sequence. See class documentation for details.
*/
void begin_seq (int tag, bool counting);
/**
* @brief Ends a sequence. See class documentation for details.
*/
void end_seq ();
private:
void write_varint (pb_varint v, bool id = false);
void dump (const char *cp, size_t n, const std::string &type, const std::string &value); void dump (const char *cp, size_t n, const std::string &type, const std::string &value);
size_t m_bytes_counted; private:
std::vector<size_t> m_byte_counter_stack;
size_t m_debug_pos; size_t m_debug_pos;
}; };

View File

@ -520,7 +520,7 @@ public:
virtual void parse (PBParser *, tl::ProtocolBufferReaderBase &) const = 0; virtual void parse (PBParser *, tl::ProtocolBufferReaderBase &) const = 0;
virtual void finish (const PBElementBase *parent, PBReaderState &objs) const = 0; virtual void finish (const PBElementBase *parent, PBReaderState &objs) const = 0;
virtual void write (const PBElementBase *, tl::ProtocolBufferWriter &, PBWriterState &) const { } virtual void write (const PBElementBase *, tl::ProtocolBufferWriterBase &, PBWriterState &) const { }
int tag () const int tag () const
{ {
@ -609,7 +609,7 @@ public:
reader.close (); reader.close ();
} }
virtual void write (const PBElementBase * /*parent*/, tl::ProtocolBufferWriter &writer, PBWriterState &objs) const virtual void write (const PBElementBase * /*parent*/, tl::ProtocolBufferWriterBase &writer, PBWriterState &objs) const
{ {
PBObjTag<Parent> parent_tag; PBObjTag<Parent> parent_tag;
@ -632,7 +632,7 @@ private:
Write m_w; Write m_w;
// this write helper is used if the reader delivers an object by value // this write helper is used if the reader delivers an object by value
void write_obj (Obj obj, int tag, tl::ProtocolBufferWriter &writer, tl::pass_by_value_tag, PBWriterState &objs) const void write_obj (Obj obj, int tag, tl::ProtocolBufferWriterBase &writer, tl::pass_by_value_tag, PBWriterState &objs) const
{ {
PBObjTag<Obj> self_tag; PBObjTag<Obj> self_tag;
@ -650,7 +650,7 @@ private:
} }
} }
void write_obj (const Obj &obj, int tag, tl::ProtocolBufferWriter &writer, tl::pass_by_ref_tag, PBWriterState &objs) const void write_obj (const Obj &obj, int tag, tl::ProtocolBufferWriterBase &writer, tl::pass_by_ref_tag, PBWriterState &objs) const
{ {
PBObjTag<Obj> self_tag; PBObjTag<Obj> self_tag;
@ -781,7 +781,7 @@ public:
value_obj.pop (tag); value_obj.pop (tag);
} }
virtual void write (const PBElementBase * /*parent*/, tl::ProtocolBufferWriter &writer, PBWriterState &objs) const virtual void write (const PBElementBase * /*parent*/, tl::ProtocolBufferWriterBase &writer, PBWriterState &objs) const
{ {
PBObjTag<Parent> parent_tag; PBObjTag<Parent> parent_tag;
Read r (m_r); Read r (m_r);
@ -798,68 +798,68 @@ private:
Converter m_c; Converter m_c;
// write incarnations // write incarnations
void write (tl::ProtocolBufferWriter &writer, int tag, float v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, float v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, double v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, double v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, uint8_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, uint8_t v) const
{ {
writer.write (tag, (uint32_t) v); writer.write (tag, (uint32_t) v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, int8_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, int8_t v) const
{ {
writer.write (tag, (int32_t) v); writer.write (tag, (int32_t) v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, uint16_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, uint16_t v) const
{ {
writer.write (tag, (uint32_t) v); writer.write (tag, (uint32_t) v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, int16_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, int16_t v) const
{ {
writer.write (tag, (int32_t) v); writer.write (tag, (int32_t) v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, uint32_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, uint32_t v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, int32_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, int32_t v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, uint64_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, uint64_t v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, int64_t v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, int64_t v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, bool v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, bool v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
void write (tl::ProtocolBufferWriter &writer, int tag, const std::string &v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, const std::string &v) const
{ {
writer.write (tag, v); writer.write (tag, v);
} }
template <class T> template <class T>
void write (tl::ProtocolBufferWriter &writer, int tag, const T &v) const void write (tl::ProtocolBufferWriterBase &writer, int tag, const T &v) const
{ {
writer.write (tag, m_c.to_string (v)); writer.write (tag, m_c.to_string (v));
} }
@ -982,7 +982,7 @@ public:
return new PBStruct<Obj> (*this); return new PBStruct<Obj> (*this);
} }
void write (tl::ProtocolBufferWriter &writer, const Obj &root) const void write (tl::ProtocolBufferWriterBase &writer, const Obj &root) const
{ {
PBWriterState writer_state; PBWriterState writer_state;
writer_state.push (& root); writer_state.push (& root);
@ -1006,7 +1006,7 @@ public:
} }
private: private:
virtual void write (const PBElementBase*, tl::ProtocolBufferWriter &, PBWriterState &) const virtual void write (const PBElementBase*, tl::ProtocolBufferWriterBase &, PBWriterState &) const
{ {
// disable base class implementation // disable base class implementation
} }