mirror of https://github.com/KLayout/klayout.git
WIP
This commit is contained in:
parent
ee06ac2f7a
commit
0f067e1dd8
|
|
@ -292,17 +292,78 @@ ProtocolBufferReader::error (const std::string &msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
|
// Writer utilities
|
||||||
|
|
||||||
ProtocolBufferWriter::ProtocolBufferWriter (tl::OutputStream &stream)
|
inline uint32_t zigzag_encode (int32_t v)
|
||||||
: mp_stream (&stream), m_bytes_counted (0), m_debug (false), m_debug_pos (0)
|
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
if (v < 0) {
|
||||||
|
return ((uint32_t (-v) - 1) << 1) + 1;
|
||||||
|
} else {
|
||||||
|
return uint32_t (v) << 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolBufferWriter::set_debug (bool f)
|
inline uint64_t zigzag_encode (int64_t v)
|
||||||
{
|
{
|
||||||
m_debug = f;
|
if (v < 0) {
|
||||||
m_debug_pos = 0;
|
return ((uint64_t (-v) - 1) << 1) + 1;
|
||||||
|
} else {
|
||||||
|
return uint64_t (v) << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void little_endian_encode (char *b, uint32_t v)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < sizeof (v); ++i) {
|
||||||
|
b[i] = (char) v;
|
||||||
|
v >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void little_endian_encode (char *b, uint64_t v)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < sizeof (v); ++i) {
|
||||||
|
b[i] = (char) v;
|
||||||
|
v >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t count_varint_bytes (pb_varint v)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
while (true) {
|
||||||
|
++n;
|
||||||
|
if (v < 0x80) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t max_varint_bytes = (sizeof (pb_varint) * 8) / 7 + 1;
|
||||||
|
|
||||||
|
inline size_t varint_encode (char *b, pb_varint v)
|
||||||
|
{
|
||||||
|
char *cp = b;
|
||||||
|
while (true) {
|
||||||
|
if (v < 0x80) {
|
||||||
|
*cp++ = char (v);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
*cp++ = (char (v) | 0x80);
|
||||||
|
}
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
return cp - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ProtocolBufferWriter::ProtocolBufferWriter (tl::OutputStream &stream)
|
||||||
|
: mp_stream (&stream), m_bytes_counted (0)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolBufferWriter::write (int tag, float v)
|
void ProtocolBufferWriter::write (int tag, float v)
|
||||||
|
|
@ -322,25 +383,11 @@ void ProtocolBufferWriter::write (int tag, uint32_t v, bool fixed)
|
||||||
write_varint (pb_varint ((tag << 3) + PB_I32), true);
|
write_varint (pb_varint ((tag << 3) + PB_I32), true);
|
||||||
|
|
||||||
if (is_counting ()) {
|
if (is_counting ()) {
|
||||||
|
|
||||||
m_byte_counter_stack.back () += sizeof (v);
|
m_byte_counter_stack.back () += sizeof (v);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
auto vv = v;
|
|
||||||
|
|
||||||
char b[sizeof (v)];
|
char b[sizeof (v)];
|
||||||
for (unsigned int i = 0; i < sizeof (v); ++i) {
|
little_endian_encode (b, v);
|
||||||
b[i] = (char) v;
|
|
||||||
v >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_debug) {
|
|
||||||
dump (b, sizeof (v), "I32", tl::to_string (vv));
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_stream->put (b, sizeof (v));
|
mp_stream->put (b, sizeof (v));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -356,11 +403,7 @@ 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);
|
||||||
} else {
|
} else {
|
||||||
if (v < 0) {
|
write (tag, zigzag_encode (v), false);
|
||||||
write (tag, ((uint32_t (-v) - 1) << 1) + 1, false);
|
|
||||||
} else {
|
|
||||||
write (tag, uint32_t (v) << 1, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -371,25 +414,11 @@ void ProtocolBufferWriter::write (int tag, uint64_t v, bool fixed)
|
||||||
write_varint (pb_varint ((tag << 3) + PB_I64), true);
|
write_varint (pb_varint ((tag << 3) + PB_I64), true);
|
||||||
|
|
||||||
if (is_counting ()) {
|
if (is_counting ()) {
|
||||||
|
|
||||||
m_byte_counter_stack.back () += sizeof (v);
|
m_byte_counter_stack.back () += sizeof (v);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
auto vv = v;
|
|
||||||
|
|
||||||
char b[sizeof (v)];
|
char b[sizeof (v)];
|
||||||
for (unsigned int i = 0; i < sizeof (v); ++i) {
|
little_endian_encode (b, v);
|
||||||
b[i] = (char) v;
|
|
||||||
v >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_debug) {
|
|
||||||
dump (b, sizeof (v), "I64", tl::to_string (vv));
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_stream->put (b, sizeof (v));
|
mp_stream->put (b, sizeof (v));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -405,11 +434,7 @@ 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);
|
||||||
} else {
|
} else {
|
||||||
if (v < 0) {
|
write (tag, zigzag_encode (v), false);
|
||||||
write (tag, ((uint64_t (-v) - 1) << 1) + 1, false);
|
|
||||||
} else {
|
|
||||||
write (tag, uint64_t (v) << 1, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,17 +449,9 @@ void ProtocolBufferWriter::write (int tag, const std::string &s)
|
||||||
write_varint (s.size ());
|
write_varint (s.size ());
|
||||||
|
|
||||||
if (is_counting ()) {
|
if (is_counting ()) {
|
||||||
|
|
||||||
m_byte_counter_stack.back () += s.size ();
|
m_byte_counter_stack.back () += s.size ();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (m_debug) {
|
|
||||||
dump (s.c_str (), s.size (), "(string)", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_stream->put (s.c_str (), s.size ());
|
mp_stream->put (s.c_str (), s.size ());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -477,68 +494,199 @@ void ProtocolBufferWriter::end_seq ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ProtocolBufferWriter::write_varint (pb_varint v, bool /*id*/)
|
||||||
ProtocolBufferWriter::write_varint (pb_varint v, bool id)
|
|
||||||
{
|
{
|
||||||
if (is_counting ()) {
|
if (is_counting ()) {
|
||||||
|
|
||||||
size_t n = 0;
|
m_byte_counter_stack.back () += count_varint_bytes (v);
|
||||||
while (true) {
|
|
||||||
++n;
|
|
||||||
if (v < 0x80) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
v >>= 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_byte_counter_stack.back () += n;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
auto vv = v;
|
char b [max_varint_bytes];
|
||||||
|
size_t n = varint_encode (b, v);
|
||||||
|
mp_stream->put (b, n);
|
||||||
|
|
||||||
char b[16];
|
}
|
||||||
char *cp = b;
|
}
|
||||||
while (true) {
|
|
||||||
if (v < 0x80) {
|
// ----------------------------------------------------------------------------------
|
||||||
*cp++ = char (v);
|
|
||||||
break;
|
ProtocolBufferDumper::ProtocolBufferDumper ()
|
||||||
} else {
|
: m_bytes_counted (0), m_debug_pos (0)
|
||||||
*cp++ = (char (v) | 0x80);
|
{
|
||||||
}
|
// .. nothing yet ..
|
||||||
v >>= 7;
|
}
|
||||||
|
|
||||||
|
void ProtocolBufferDumper::write (int tag, float 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_debug) {
|
} else {
|
||||||
if (id) {
|
|
||||||
unsigned int wt = v & 7;
|
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
|
||||||
std::string wire_type;
|
write_varint (pb_varint (v));
|
||||||
if (wt == PB_EGROUP) {
|
|
||||||
wire_type = "EGROUP";
|
}
|
||||||
} else if (wt == PB_SGROUP) {
|
}
|
||||||
wire_type = "SGROUP";
|
|
||||||
} else if (wt == PB_VARINT) {
|
void ProtocolBufferDumper::write (int tag, int32_t v, bool fixed)
|
||||||
wire_type = "VARINT";
|
{
|
||||||
} else if (wt == PB_I32) {
|
if (fixed) {
|
||||||
wire_type = "I32";
|
write (tag, uint32_t (v), true);
|
||||||
} else if (wt == PB_I64) {
|
} else {
|
||||||
wire_type = "I64";
|
write (tag, zigzag_encode (v), false);
|
||||||
} else if (wt == PB_LEN) {
|
}
|
||||||
wire_type = "LEN";
|
}
|
||||||
}
|
|
||||||
dump (b, cp - b, "(id)", "#" + tl::to_string (vv >> 3) + " " + wire_type);
|
void ProtocolBufferDumper::write (int tag, uint64_t v, bool fixed)
|
||||||
} else {
|
{
|
||||||
dump (b, cp - b, "VARINT", tl::to_string (vv));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_stream->put (b, cp - b);
|
} 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 ()) {
|
||||||
|
|
||||||
|
m_byte_counter_stack.back () += s.size ();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ProtocolBufferWriter::dump (const char *cp, size_t n, const std::string &type, const std::string &value)
|
ProtocolBufferDumper::write_varint (pb_varint v, bool id)
|
||||||
|
{
|
||||||
|
if (is_counting ()) {
|
||||||
|
|
||||||
|
m_byte_counter_stack.back () += count_varint_bytes (v);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
char b[max_varint_bytes];
|
||||||
|
size_t n = varint_encode (b, v);
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
tl::PBWireType wt = tl::PBWireType (v & 7);
|
||||||
|
std::string wire_type;
|
||||||
|
if (wt == PB_EGROUP) {
|
||||||
|
wire_type = "EGROUP";
|
||||||
|
} else if (wt == PB_SGROUP) {
|
||||||
|
wire_type = "SGROUP";
|
||||||
|
} else if (wt == PB_VARINT) {
|
||||||
|
wire_type = "VARINT";
|
||||||
|
} else if (wt == PB_I32) {
|
||||||
|
wire_type = "I32";
|
||||||
|
} else if (wt == PB_I64) {
|
||||||
|
wire_type = "I64";
|
||||||
|
} else if (wt == PB_LEN) {
|
||||||
|
wire_type = "LEN";
|
||||||
|
}
|
||||||
|
dump (b, n, "(id)", "#" + tl::to_string (v >> 3) + " " + wire_type);
|
||||||
|
} else {
|
||||||
|
dump (b, n, "VARINT", tl::to_string (v));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ProtocolBufferDumper::dump (const char *cp, size_t n, const std::string &type, const std::string &value)
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
size_t nn = n;
|
size_t nn = n;
|
||||||
|
|
|
||||||
|
|
@ -67,27 +67,126 @@ private:
|
||||||
*
|
*
|
||||||
* This is a low-level decoder for ProtocolBuffer files.
|
* This is a low-level decoder for ProtocolBuffer files.
|
||||||
*
|
*
|
||||||
* The following LEN-type related concepts need to be implemented by the client code:
|
* Use "read_tag" to read a new tag. Unknown tags must be skipped.
|
||||||
* - submessages
|
* Use "skip" to skip an entry.
|
||||||
* - maps
|
|
||||||
* - packed repetitions
|
|
||||||
* - strings
|
|
||||||
*
|
*
|
||||||
* Unknown tags need to be skipped with "skip".
|
|
||||||
*
|
*
|
||||||
* Submessages: if a corresponding tag is encountered with "is_seq()" true, the
|
*/
|
||||||
* reader code needs to call "open" to enter the sequence and read tags until
|
class TL_PUBLIC ProtocolBufferReaderBase
|
||||||
* "at_end" is true. Then, call "close" to leave the sequence.
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
ProtocolBufferReaderBase ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~ProtocolBufferReaderBase ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a new tag
|
||||||
|
* This method will also set the current write type.
|
||||||
|
* @returns The message ID
|
||||||
|
*/
|
||||||
|
virtual int read_tag () = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current wire type
|
||||||
|
*/
|
||||||
|
virtual PBWireType type () const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Skips the current tag
|
||||||
|
*/
|
||||||
|
virtual void skip () = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a floating-point value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a double value.
|
||||||
|
*/
|
||||||
|
virtual void read (double &d) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a floating-point value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a float value.
|
||||||
|
*/
|
||||||
|
virtual void read (float &f) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a string from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a string.
|
||||||
|
*/
|
||||||
|
virtual void read (std::string &s) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a uint32_t value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a uint32_t.
|
||||||
|
*/
|
||||||
|
virtual void read (uint32_t &ui32) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a int32_t value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a int32_t.
|
||||||
|
*/
|
||||||
|
virtual void read (int32_t &i32) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a uint64_t value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a uint64_t.
|
||||||
|
*/
|
||||||
|
virtual void read (uint64_t &ui64) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a int64_t value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a int64_t.
|
||||||
|
*/
|
||||||
|
virtual void read (int64_t &i64) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a boolean value from the current message
|
||||||
|
* Throws a reader error if the current tag's value is not compatible with a bool.
|
||||||
|
*/
|
||||||
|
virtual void read (bool &b) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens a LEN sequence
|
||||||
|
* After calling "open", the parser will continue reading messages, but
|
||||||
|
* "at_end" will report true on the end of the sequence, not at the end of the
|
||||||
|
* file.
|
||||||
|
* This method will throw an exception if not in a message of LEN type.
|
||||||
|
*/
|
||||||
|
virtual void open () = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes the LEN sequence
|
||||||
|
* This method will jump to the end of the sequence and continue reading
|
||||||
|
* messages from the previous block or file.
|
||||||
|
*/
|
||||||
|
virtual void close () = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if at the end of the file or end of a block
|
||||||
|
*/
|
||||||
|
virtual bool at_end () const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A reader for ProtocolBuffer files and streams
|
||||||
*
|
*
|
||||||
* Packed repetitions: same a submessages, but single values are read
|
* This is the reader implementation for binary files
|
||||||
* with one of the "read" types.
|
* as described here:
|
||||||
*
|
* https://protobuf.dev/programming-guides/encoding/
|
||||||
* Maps are read like submessages with key/values as tags 1 and 2.
|
|
||||||
*
|
|
||||||
* Strings: if a corresponding tag is encountered, use "read(s)" to read
|
|
||||||
* the string. "is_seq()" is required to be true, i.e. wire type is LEN.
|
|
||||||
*/
|
*/
|
||||||
class TL_PUBLIC ProtocolBufferReader
|
class TL_PUBLIC ProtocolBufferReader
|
||||||
|
: public ProtocolBufferReaderBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
@ -110,16 +209,6 @@ public:
|
||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns true, if the current message is a LEN type sequence
|
|
||||||
* Such messages can be read into strings or "open" can be used on them to
|
|
||||||
* open a submessage, map or packed repetition.
|
|
||||||
*/
|
|
||||||
bool is_seq () const
|
|
||||||
{
|
|
||||||
return m_type == PB_LEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Skips the current tag
|
* @brief Skips the current tag
|
||||||
*/
|
*/
|
||||||
|
|
@ -224,7 +313,62 @@ private:
|
||||||
* 4. if "is_counting()" is false, repeat steps 1 to 3 with
|
* 4. if "is_counting()" is false, repeat steps 1 to 3 with
|
||||||
* "counting" set to false on "begin_seq".
|
* "counting" set to false on "begin_seq".
|
||||||
*/
|
*/
|
||||||
|
class TL_PUBLIC ProtocolBufferWriterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
ProtocolBufferWriterBase ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~ProtocolBufferWriterBase ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a scalar tag with the given value
|
||||||
|
*/
|
||||||
|
virtual void write (int tag, float v) = 0;
|
||||||
|
virtual void write (int tag, double v) = 0;
|
||||||
|
virtual void write (int tag, uint32_t v, bool fixed = false) = 0;
|
||||||
|
virtual void write (int tag, int32_t v, bool fixed = false) = 0;
|
||||||
|
virtual void write (int tag, uint64_t v, bool fixed = false) = 0;
|
||||||
|
virtual void write (int tag, int64_t v, bool fixed = false) = 0;
|
||||||
|
virtual void write (int tag, bool b) = 0;
|
||||||
|
virtual void write (int tag, const std::string &s) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the writer is in counting mode
|
||||||
|
*/
|
||||||
|
virtual bool is_counting () const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initiates a new sequence. See class documentation for details.
|
||||||
|
*/
|
||||||
|
virtual void begin_seq (int tag, bool counting) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ends a sequence. See class documentation for details.
|
||||||
|
*/
|
||||||
|
virtual void end_seq () = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A writer for ProtocolBuffer files and streams
|
||||||
|
*
|
||||||
|
* This is the writer implementation for binary files
|
||||||
|
* as described here:
|
||||||
|
* https://protobuf.dev/programming-guides/encoding/
|
||||||
|
*/
|
||||||
class TL_PUBLIC ProtocolBufferWriter
|
class TL_PUBLIC ProtocolBufferWriter
|
||||||
|
: public ProtocolBufferWriterBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
@ -259,20 +403,62 @@ public:
|
||||||
*/
|
*/
|
||||||
void end_seq ();
|
void end_seq ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void write_varint (pb_varint v, bool id = false);
|
||||||
|
|
||||||
|
tl::OutputStream *mp_stream;
|
||||||
|
size_t m_bytes_counted;
|
||||||
|
std::vector<size_t> m_byte_counter_stack;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A writer implementation that dumps the file content to tl::info
|
||||||
|
*
|
||||||
|
* This implementation does a halfway job of producing binary files,
|
||||||
|
* but only insofar it is needed for dumping the binary data.
|
||||||
|
*/
|
||||||
|
class TL_PUBLIC ProtocolBufferDumper
|
||||||
|
: public ProtocolBufferWriterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Enables or disables debug mode
|
* @brief Creates the writer
|
||||||
* In debug mode, the stream will be dumped in a human readable form
|
|
||||||
*/
|
*/
|
||||||
void set_debug (bool f);
|
ProtocolBufferDumper ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a scalar tag with the given value
|
||||||
|
*/
|
||||||
|
void write (int tag, float v);
|
||||||
|
void write (int tag, double v);
|
||||||
|
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);
|
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);
|
||||||
|
|
||||||
tl::OutputStream *mp_stream;
|
|
||||||
size_t m_bytes_counted;
|
size_t m_bytes_counted;
|
||||||
std::vector<size_t> m_byte_counter_stack;
|
std::vector<size_t> m_byte_counter_stack;
|
||||||
bool m_debug;
|
|
||||||
size_t m_debug_pos;
|
size_t m_debug_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,14 @@ PBParser::~PBParser ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PBParser::parse (tl::ProtocolBufferReader &reader, const PBElementBase *root, PBReaderState *reader_state)
|
PBParser::parse (tl::ProtocolBufferReaderBase &reader, const PBElementBase *root, PBReaderState *reader_state)
|
||||||
{
|
{
|
||||||
mp_state = reader_state;
|
mp_state = reader_state;
|
||||||
parse_element (root, reader);
|
parse_element (root, reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PBParser::parse_element (const PBElementBase *parent, tl::ProtocolBufferReader &reader)
|
PBParser::parse_element (const PBElementBase *parent, tl::ProtocolBufferReaderBase &reader)
|
||||||
{
|
{
|
||||||
while (! reader.at_end ()) {
|
while (! reader.at_end ()) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,8 +296,8 @@ public:
|
||||||
PBParser ();
|
PBParser ();
|
||||||
~PBParser ();
|
~PBParser ();
|
||||||
|
|
||||||
void parse (tl::ProtocolBufferReader &reader, const PBElementBase *root, PBReaderState *reader_state);
|
void parse (tl::ProtocolBufferReaderBase &reader, const PBElementBase *root, PBReaderState *reader_state);
|
||||||
void parse_element (const PBElementBase *parent, tl::ProtocolBufferReader &reader);
|
void parse_element (const PBElementBase *parent, tl::ProtocolBufferReaderBase &reader);
|
||||||
|
|
||||||
PBReaderState &reader_state ()
|
PBReaderState &reader_state ()
|
||||||
{
|
{
|
||||||
|
|
@ -517,7 +517,7 @@ public:
|
||||||
virtual PBElementBase *clone () const = 0;
|
virtual PBElementBase *clone () const = 0;
|
||||||
|
|
||||||
virtual void create (const PBElementBase *parent, PBReaderState &objs) const = 0;
|
virtual void create (const PBElementBase *parent, PBReaderState &objs) const = 0;
|
||||||
virtual void parse (PBParser *, tl::ProtocolBufferReader &) 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::ProtocolBufferWriter &, PBWriterState &) const { }
|
||||||
|
|
@ -602,7 +602,7 @@ public:
|
||||||
objs.pop (tag);
|
objs.pop (tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void parse (PBParser *parser, tl::ProtocolBufferReader &reader) const
|
virtual void parse (PBParser *parser, tl::ProtocolBufferReaderBase &reader) const
|
||||||
{
|
{
|
||||||
reader.open ();
|
reader.open ();
|
||||||
parser->parse_element (this, reader);
|
parser->parse_element (this, reader);
|
||||||
|
|
@ -767,7 +767,7 @@ public:
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void parse (PBParser *parser, tl::ProtocolBufferReader &reader) const
|
virtual void parse (PBParser *parser, tl::ProtocolBufferReaderBase &reader) const
|
||||||
{
|
{
|
||||||
PBObjTag<Value> tag;
|
PBObjTag<Value> tag;
|
||||||
PBObjTag<Parent> parent_tag;
|
PBObjTag<Parent> parent_tag;
|
||||||
|
|
@ -865,17 +865,17 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// read incarnations
|
// read incarnations
|
||||||
void read (tl::ProtocolBufferReader &reader, float &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, float &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, double &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, double &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, uint8_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, uint8_t &v) const
|
||||||
{
|
{
|
||||||
uint32_t vv = 0;
|
uint32_t vv = 0;
|
||||||
reader.read (vv);
|
reader.read (vv);
|
||||||
|
|
@ -883,7 +883,7 @@ private:
|
||||||
v = vv;
|
v = vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, int8_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, int8_t &v) const
|
||||||
{
|
{
|
||||||
int32_t vv = 0;
|
int32_t vv = 0;
|
||||||
reader.read (vv);
|
reader.read (vv);
|
||||||
|
|
@ -891,7 +891,7 @@ private:
|
||||||
v = vv;
|
v = vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, uint16_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, uint16_t &v) const
|
||||||
{
|
{
|
||||||
uint32_t vv = 0;
|
uint32_t vv = 0;
|
||||||
reader.read (vv);
|
reader.read (vv);
|
||||||
|
|
@ -899,7 +899,7 @@ private:
|
||||||
v = vv;
|
v = vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, int16_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, int16_t &v) const
|
||||||
{
|
{
|
||||||
int32_t vv = 0;
|
int32_t vv = 0;
|
||||||
reader.read (vv);
|
reader.read (vv);
|
||||||
|
|
@ -907,38 +907,38 @@ private:
|
||||||
v = vv;
|
v = vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, uint32_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, uint32_t &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, int32_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, int32_t &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, uint64_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, uint64_t &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, int64_t &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, int64_t &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, bool &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, bool &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read (tl::ProtocolBufferReader &reader, std::string &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, std::string &v) const
|
||||||
{
|
{
|
||||||
reader.read (v);
|
reader.read (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void read (tl::ProtocolBufferReader &reader, const T &v) const
|
void read (tl::ProtocolBufferReaderBase &reader, const T &v) const
|
||||||
{
|
{
|
||||||
std::string vv;
|
std::string vv;
|
||||||
reader.read (vv);
|
reader.read (vv);
|
||||||
|
|
@ -994,7 +994,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse (tl::ProtocolBufferReader &reader, Obj &root) const
|
void parse (tl::ProtocolBufferReaderBase &reader, Obj &root) const
|
||||||
{
|
{
|
||||||
PBObjTag<Obj> tag;
|
PBObjTag<Obj> tag;
|
||||||
PBReaderState rs;
|
PBReaderState rs;
|
||||||
|
|
@ -1011,7 +1011,7 @@ private:
|
||||||
// disable base class implementation
|
// disable base class implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void parse (PBParser *, tl::ProtocolBufferReader &) const
|
virtual void parse (PBParser *, tl::ProtocolBufferReaderBase &) const
|
||||||
{
|
{
|
||||||
// disable base class implementation
|
// disable base class implementation
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue