摘要:
针对protobuf中的varint, 写一个简单的测试, 标明编码是如何具体存储的
说明:
将整形压缩后的字节流, 放进string里, 因为在linux中, 整形是以小端存储, 所以要注意这点
特性如下:
- varint小端编码, 以最高位为控制连续位. 当最高位控制位为0时, 表面整数编码的最后一个字节. 即最后的结束字节, 最高位永远为0
- varint对于int类型, 因为截取最高位, 则编码后, 最多为5个字节
- 当整数 <=63, varint编码后为0X7F, 最高位被占用
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdint.h>
#include <string>
#include <iostream>
#include <typeinfo>
static inline void ToVarInt(int64_t value, std::string& str)
{
uint64_t lvalue = static_cast<uint64_t>((value << 1) ^ (value >> 63));
for (;;)
{
uint8_t aByte = lvalue & 0x7f;
lvalue >>= 7;
if (0 == lvalue)
{
str += (char)(aByte);
break;
}
else
{
aByte |= 0x80;
str += (char)(aByte);
}
}
}
static inline int64_t FromVarInt(const std::string& str)
{
int i = 0;
int64_t n = 0;
int shift = 0;
for (;;)
{
uint8_t aByte = (uint8_t) str[i++];
int64_t bvar = aByte & 0x7f;
n += (bvar << shift);
shift += 7;
if (0 == (aByte & 0x80))
{
break;
}
}
return ((uint64_t)n >> 1) ^ (-(n & 1));
}
union Value
{
int64_t v;
char c[sizeof(int64_t)];
};
int main()
{
int64_t t = 64;
printf("%X\n\n", t);
std::string str;
ToVarInt(t, str);
for (size_t i = 0; i < str.length(); i++)
{
uint8_t c = (uint8_t)str[i];
printf("%X\n", c);
}
str.clear();
str += (char) (0xfe);
str += (char) (0xff);
int64_t nt = FromVarInt(str);
printf("%X\n\n", (int)nt);
Value vl;
vl.v = nt;
for (size_t i = 0; i < sizeof(vl.c); i++)
{
printf("%X\n", (uint8_t)vl.c[i]);
}
return 0;
}