一个轻量的 wire format 解释器(google protobuf 的二进制格式)

本文介绍Google Protobuf项目的底层二进制格式设计,包括wire format的基本概念、不同数据类型的编码方式及其应用场景。深入探讨了varint、64bit、32bit和length-delimited等类型的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

google 的 protobuf 项目,底层的二进制格式设计很精简,格式的详细描述参考下面的链接:
[url]http://code.google.com/apis/protocolbuffers/docs/encoding.html[/url]

下载链接
[url]http://spjson.googlecode.com/files/spjson-0.3.src.tar.gz[/url]
暂时是作为 spjson 的一部分。

这个格式被 google 才称为 wire format ,实质是一个用于保存 key/value 对的二进制格式。
key 被称为 fieldNumber 。
value 分为几种类型:varint,64bit,32bit,Length-delimited 。

varint 是指变长整数,实质上可能对应 int8,int16,int32,int64 和他们的有符号类型。varint 对于保存小整数有非常好的压缩效果,对于 <= 128 的整数只需要一个字节。具体的算法可以参考上面的链接。

64bit 和 32bit 按我的理解主要可能是用于映射 double 和 float 。因为整数本身已经全部可以通过 varint 来解决了。 把 double 和 float 按 little-endian byte order 进行保存。

Length-delimited 用于保存字符串和二进制数据。二进制数据可能是另外一个 protobuf ,这样就可以实现支持内嵌复杂类型的功能。

实现用典型的 codec 的方式来实现,一个 encoder 和一个 decoder 。
[code]
class SP_ProtoBufEncoder
{
public:
SP_ProtoBufEncoder( int initLen = 0 );
~SP_ProtoBufEncoder();

int addVarint( int fieldNumber, uint64_t value );
int addDouble( int fieldNumber, double value );
int addFloat( int fieldNumber, float value );

int addBinary( int fieldNumber, const char * buffer, int len );

const char * getBuffer();
int getSize();
};

class SP_ProtoBufDecoder
{
public:
SP_ProtoBufDecoder( const char * buffer, int len );
~SP_ProtoBufDecoder();

bool getNext( KeyValPair_t * pair );

bool find( int fieldNumber, KeyValPair_t * pair, int index = 0 );
};

[/code]

encoder 对于不同的类型,提供了对应的 add 方法。在任何时候,都可以调用 encoder 的 getBuffer 和 getSize 获取当前已经生成的 buffer 。

decoder 提供 getNext 和 find 两个方法。getNext 用于遍历 protobuf 的所有字段。find 方法用于根据 fieldNumber 来获取对应的字段。定义了一个辅助数据结构 KeyValPair_t 来简化这个两个方法的参数。find 方法内部使用二分查找法来加速。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值