您的位置:首页 > Web前端

google protocol buffer 编码详解(1)

2012-09-11 16:09 176 查看


google protocol buffer 编码详解(1)

分类: 技术类2012-05-27
22:56 73人阅读 评论(0) 收藏 举报

在进行前,需要阅读下基础知识

基本知识:https://developers.google.com/protocol-buffers/docs/encoding

中文译文:http://www.wuzesheng.com/?p=1258

1. 从最简单的开始

message Info

{

optional int32 m_iValue = 1;

}

Test::Info stInfo;

stInfo.set_m_ivalue(2);

输出:

buf size:2, content:

Bin: 0000100000000010

Hex: 0802

解释: 00001000 (field number 1 左移3位) 00000010(2)

2. optional 定义的成员,如果没有设置值,那么不会被编码

message Info

{

optional int32 m_iValue = 1;

}

Test::Info stInfo;

不设置成员值
buf size:0, content:

Bin:

Hex:

3. required vs optional

message Info

{

required int32 m_iValue = 1;

}

设置成员值和不设置成员值,输入跟上面的optional是一样的,难道在c++的实现下,required和optional没区别?

diff查看2者生成的文件,cc文件区别如下:

optional.cc

bool Info::IsInitialized() const {

return true;

}

void protobuf_AddDesc_test_2eproto() {

static bool already_here = false;

if (already_here) return;

already_here = true;

GOOGLE_PROTOBUF_VERIFY_VERSION;

::google::protobuf::DescriptorPool::InternalAddGeneratedFile(

"\n\ntest.proto\022\004Test\"\030\n\004Info\022\020\n\010m_iValue\030\001"

" \001(\005", 44);//这里是001

::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(

"test.proto", &protobuf_RegisterTypes);

Info::default_instance_ = new Info();

Info::default_instance_->InitAsDefaultInstance();

::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_test_2eproto);

}

required.cc

bool Info::IsInitialized() const {

if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;//多了这样一行

return true;

}

void protobuf_AddDesc_test_2eproto() {

static bool already_here = false;

if (already_here) return;

already_here = true;

GOOGLE_PROTOBUF_VERIFY_VERSION;

::google::protobuf::DescriptorPool::InternalAddGeneratedFile(

"\n\ntest.proto\022\004Test\"\030\n\004Info\022\020\n\010m_iValue\030\001"

" \002(\005", 44);//这里是002

::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(

"test.proto", &protobuf_RegisterTypes);

Info::default_instance_ = new Info();

Info::default_instance_->InitAsDefaultInstance();

::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_test_2eproto);

}

也就是说在required生成的文件中是有生成函数IsInitialized()来检测成员是否赋值,但是在真正serialize的时候并没有调用该函数去检查是否设置成员值。难道是需要程序员自己来主动调用该函数进行检查。

4. 负数的编码 int vs sint

message Info

{

optional int32 m_iValue = 1;

}

Test::Info stInfo;

stInfo.set_m_ivalue(-1);

output:

buf size:11, content:

Bin: 0000100011111111111111111111111111111111111111111111111111111111111111111111111100000001

Hex: 08ffffffffffffffffff01

解释:64位的int(为什么是64位,不是指明32位吗?)-1,编码为8个f,因为pb每个byte需要一位来指明编码是否结束,每个byte的实际有效位只有7位,所以编码-1,需要10个byte(64除以7=9,余1)。综合起来,那么编码-1就需要11个byte

Test::Info stInfo;

stInfo.set_m_ivalue(-3);

buf size:11, content:

Bin: 0000100011111101111111111111111111111111111111111111111111111111111111111111111100000001

Hex: 08fdffffffffffffffff01

解释:-3的编码为fd+7个f,其它的解释同上

message Info

{

optional sint32 m_iValue = 1;

}

Test::Info stInfo;

stInfo.set_m_ivalue(-1);

buf size:2, content:

Bin: 0000100000000001

Hex: 0801

解释:sint使用zig-zags来编码 (00001000是field number 偏移3位) 00000001为-1的zig-zags编码

分享到:

上一篇:字符串hash函数
下一篇:linux文件空洞

查看评论

暂无评论

您还没有登录,请[登录][注册]

* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: