LevelDB源码分析-编码
编码(util/coding.h util/coding.cc)
LevelDB将整型编码为二进制字符串的形式,同时又能够和ASCII字符区分。
首先是定长编码:
void EncodeFixed32(char *buf, uint32_t value)
{
if (port::kLittleEndian)
{
memcpy(buf, &value, sizeof(value));
}
else
{
buf[0] = value & 0xff;
buf[1] = (value >> 8) & 0xff;
buf[2] = (value >> 16) & 0xff;
buf[3] = (value >> 24) & 0xff;
}
}
void EncodeFixed64(char *buf, uint64_t value)
{
if (port::kLittleEndian)
{
memcpy(buf, &value, sizeof(value));
}
else
{
buf[0] = value & 0xff;
buf[1] = (value >> 8) & 0xff;
buf[2] = (value >> 16) & 0xff;
buf[3] = (value >> 24) & 0xff;
buf[4] = (value >> 32) & 0xff;
buf[5] = (value >> 40) & 0xff;
buf[6] = (value >> 48) & 0xff;
buf[7] = (value >> 56) & 0xff;
}
}
这里根据机器区分大端和小端,LevelDB编码后的字符串为小端存储。在编码时,只是简单的将8位二进制码存储在一个char字符的位置上。因为定长,所以可以和ASCII字符区分。
接下来是定长编码的一些接口函数:
void PutFixed32(std::string *dst, uint32_t value) // 将一个32位整型值定长编码后存入dst
void PutFixed64(std::string *dst, uint64_t value) // 将一个64位整型值定长编码后存入dst
然后是变长编码:
char *EncodeVarint32(char *dst, uint32_t v)
{
// Operate on characters as unsigneds
unsigned char *ptr = reinterpret_cast<unsigned char *>(dst);
static const int B = 128;
if (v < (1 << 7))
{
*(ptr++) = v;
}
else if (v < (1 << 14))
{
*(ptr++) = v | B;
*(ptr++) = v >> 7;
}
else if (v < (1 << 21))
{
*(ptr++) = v | B;
*(ptr++) = (v >> 7) | B;
*(ptr++) = v >> 14;
}
else if (v < (1 << 28))
{
*(ptr++) = v | B;
*(ptr++) = (v >> 7) | B;
*(ptr++) = (v >> 14) | B;
*(ptr++) = v >> 21;
}
else
{
*(ptr++) = v | B;
*(ptr++) = (v >> 7) | B;
*(ptr++) = (v >> 14) | B;
*(ptr++) = (v >> 21) | B;
*(ptr++) = v >> 28;
}
return reinterpret_cast<char *>(ptr);
}
char *EncodeVarint64(char *dst, uint64_t v)
{
static const int B = 128;
unsigned char *ptr = reinterpret_cast<unsigned char *>(dst);
while (v >= B)
{
*(ptr++) = (v & (B - 1)) | B;
v >>= 7;
}
*(ptr++) = static_cast<unsigned char>(v);
return reinterpret_cast<char *>(ptr);
}
LevelDB的变长编码设计的十分巧妙,它以7个二进制bit为一个单位,存入一个char中,同时为了和ASCII码进行区分,将char的最高位设为1(ASCII码为0-127),同样采用小端存储的形式。但是变长编码的最后一个char的最高位是0,以此作为变长编码后的字符串的结束标志。
例如,11001011101111001会被编码为11111001 10101110 00000110。
接下来是一些变长编码的接口函数:
void PutVarint32(std::string *dst, uint32_t v) // 将一个32位整型值变长编码后存入dst
void PutVarint64(std::string *dst, uint64_t v) // 将一个64位整型值变长编码后存入dst
int VarintLength(uint64_t v) // 获取变长编码后的字符串长度(以字节计数)
const char *GetVarint32PtrFallback(const char *p,
const char *limit,
uint32_t *value) // 将以p到limit之间的变长编码字符串解码为32位整型值
bool GetVarint32(Slice *input, uint32_t *value) // 将以p到limit之间的变长编码字符串解码为32位整型值并封装入Slice中
const char *GetVarint64Ptr(const char *p, const char *limit, uint64_t *value) // 将以p到limit之间的变长编码字符串解码为64位整型值
bool GetVarint64(Slice *input, uint64_t *value) // 将以p到limit之间的变长编码字符串解码为64位整型值并封装入Slice中
227 Love u
LevelDB源码分析-编码的更多相关文章
- leveldb源码分析--WriteBatch
从[leveldb源码分析--插入删除流程]和WriteBatch其名我们就很轻易的知道,这个是leveldb内部的一个批量写的结构,在leveldb为了提高插入和删除的效率,在其插入过程中都采用了批 ...
- leveldb源码分析--Key结构
[注]本文参考了sparkliang的专栏的Leveldb源码分析--3并进行了一定的重组和排版 经过上一篇文章的分析我们队leveldb的插入流程有了一定的认识,而该文设计最多的又是Batch的概念 ...
- leveldb源码分析--SSTable之block
在SSTable中主要存储数据的地方是data block,block_builder就是这个专门进行block的组织的地方,我们来详细看看其中的内容,其主要有Add,Finish和CurrentSi ...
- Leveldb源码分析--1
coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...
- v74.01 鸿蒙内核源码分析(编码方式篇) | 机器指令是如何编码的 | 百篇博客分析OpenHarmony源码
本篇关键词:指令格式.条件域.类型域.操作域.数据指令.访存指令.跳转指令.SVC(软件中断) 内核汇编相关篇为: v74.01 鸿蒙内核源码分析(编码方式) | 机器指令是如何编码的 v75.03 ...
- leveldb源码分析--日志
我们知道在一个数据库系统中为了保证数据的可靠性,我们都会记录对系统的操作日志.日志的功能就是用来在系统down掉的时候对数据进行恢复,所以日志系统对一个要求可靠性的存储系统是极其重要的.接下来我们分析 ...
- leveldb源码分析之Slice
转自:http://luodw.cc/2015/10/15/leveldb-02/ leveldb和redis这样的优秀开源框架都没有使用C++自带的字符串string,redis自己写了个sds,l ...
- LevelDB源码分析--Cache及Get查找流程
本打算接下来分析version相关的概念,但是在准备的过程中看到了VersionSet的table_cache_这个变量才想起还有这样一个模块尚未分析,经过权衡觉得leveldb的version相对C ...
- leveldb源码分析--SSTable之TableBuilder
上一篇文章讲述了SSTable的格式以后,本文结合源码解析SSTable是如何生成的. void TableBuilder::Add(const Slice& key, const Slice ...
随机推荐
- Postman插件使用
Postman插件:模拟前端请求后台,用于后台对外接口测试 POSTMAN解决..先解压Postman_v4.1.3.rar 然后按自己实际解压的文件夹里面的这个文件夹_metadata前面的_去掉 ...
- 剑指Offer 27. 字符串的排列 (字符串)
题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...
- 1.python+appium环境配置
环境部署 本博客以32位的Windows 7操作系统为例介绍Appium+Python的环境搭建步骤 1.安装Node.js 访问 https://nodejs.org/en/download/,下载 ...
- Day 1: ASP.NET and JavaScript Jan.16th Trying
ASP.NET has its own named controls(tags) corresponding to that in an HTML document, such as <asp: ...
- 【linux基础】cuDNN版本查询
参考 1. 查看cudnn版本; 完
- JAVA基础部分复习(七、JAVA枚举类型使用)
/** * java中的枚举 * 枚举(enum),是指一个经过排序的.被打包成一个单一实体的项列表.一个枚举的实例可以使用枚举项列表中任意单一项的值. * 枚举在各个语言当中都有着广泛的应用,通常用 ...
- tree-lstm初探
https://zhuanlan.zhihu.com/p/35252733 可以先看看上面知乎文章里面的例子 Socher 等人于2012和2013年分别提出了两种区分词或短语类型的模型,即SU-RN ...
- RESTful Loads
RESTful 一种软件架构风格.设计风格,而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. 概述 ...
- Property ‘password’ threw Exception
问题描述: Maven项目在tomcat启动的时候总是报Propety 'password' threw exception异常时,说明password不对,但核对之后没有问题 解决方案: 核对pas ...
- zabbix之 zabbix server 跟 agent 更换ip地址
描述: zabbix server端跟agent端更改 ip . 改完之后,相应配置文件 (zabbix_agentd.conf.zabbix_server.conf)的ip也进行了替换 但是依旧报错 ...