LevelDB(v1.3) 源码阅读之 Slice
LevelDB(v1.3) 源码阅读系列使用 LevelDB v1.3 版本的代码,可以通过如下方式下载并切换到 v1.3 版本的代码:
$ git clone https://github.com/google/leveldb.git
$ cd leveldb
$ git checkout -b v1.3 v1.3
本文涉及的代码文件为:
include/slice.h
1. Slice 简介
LevelDB Slice 对经常使用的字符串进行了简单的封装,它自己不管理内存,仅仅提供对已有字符串的简单操作:这就是不使用 std::string 的原因:避免不必要的内存拷贝。因此,Slice 要求用户:
The user of a Slice must ensure that the slice is not used after the corresponding external storage has been deallocated.
我们需要时刻牢记:Slice 不负责管理内存,它只操作已有的字符串,这些字符串的内存由用户自己管理,还有一点,Slice 不能修改所操作的字符串
本文是 LevelDB(v1.3) 源码阅读系列第一篇文章,并且 Slice 也比较简单,所以这篇文章我会写的尽量详细,以后的文章我会更加注重设计,代码我不会像这篇文章一样贴的那么多
2. Slice 对外提供的接口
2.1. 构造函数
Slice() : data_(""), size_(0) { }
Slice(const char* d, size_t n) : data_(d), size_(n) { }
Slice(const std::string& s) : data_(s.data()), size_(s.size()) { }
Slice(const char* s) : data_(s), size_(strlen(s)) { }
第一个是默认构造函数,它会初始化一个空的 slice 出来,这个 slice 的长度为 0
第二个构造函数要求提供一个 char* 和 size_t 的参数分别来初始化 slice 的两个成员变量
第三个构造函数的参数是一个 string 类型的字符串
第四个构造函数的参数是一个 C 语言类型的字符串,该字符串以 '\0' 结尾,并且用 strlen(s) 来初始化 slice 的长度
通过构造函数我们很清晰的看到:Slice 不对它所操作的字符串进行拷贝复制,仅安排一个指针指向该字符串,并用一个整型变量记录该字符串的长度。事实上,Slice 仅仅只有他们两个成员变量:
const char* data_;
size_t size_;
注意到 data_ 的底层 const 修饰: Slice 不能修改所操作的字符串。
还需要注意的是,Slice 将拷贝构造函数和拷贝赋值函数声明为私有的,也就直接造成了 Slice 对象之间不可以直接的拷贝赋值。实际上也没有这样的必要和使用场景,Slice 仅仅是一个对字符串操作的函数集合,用户根本没必要拷贝两个工具集合。
2.2. 运算符重载
Slice 重载了三个运算符:[]、== 和 !=,[] 是 Slice 的成员函数,== 和 != 是对标准函数的重载,他们的代码如下:
char operator[](size_t n) const {
assert(n < size());
return data_[n];
}
inline bool operator==(const Slice& x, const Slice& y) {
return ((x.size() == y.size()) && (memcmp(x.data(), y.data(), x.size()) == 0));
}
inline bool operator!=(const Slice& x, const Slice& y) {
return !(x == y);
}
因为 Slice 不能修改其操作的字符串,[] 的重载函数返回的是该位置字符的一个拷贝而不是引用,不能通过 slice[i] = 'a' 的方式来改变 slice 第 i 个字节的内容
对于 == 和 !=:两个 Slice 相等指的是是他们的长度相等,并且所有的字节也相等(一个代码 tip:if 短路,先判断两个字符串的长度,再判断内容)
2.3. 常规函数
const char* data() const { return data_; }
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
void clear() { data_ = ""; size_ = 0; }
std::string ToString() const { return std::string(data_, size_); }
void remove_prefix(size_t n) {
assert(n <= size());
data_ += n;
size_ -= n;
}
inline int Slice::compare(const Slice& b) const {
const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
int r = memcmp(data_, b.data_, min_len);
if (r == 0) {
if (size_ < b.size_) r = -1;
else if (size_ > b.size_) r = +1;
}
return r;
}
bool starts_with(const Slice& x) const {
return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
}
这几个函数都比较简单:
- data() 和 size() 类似于 string 的 data() 和 size(),直接返回成员变量
- empty() 用来判断 Slice 中是否有字符串,这是通过判断 size 是否为 0 来实现的
- clear() 直接让当前这个 Slice 指向一个空字符串,并设置 size 为 0,再次印证:Slice 不负责内存的管理
- ToString() 就直接调用 string 的构造函数生成一个 string 对象,并把这个对象拷贝给调用者
- starts_with(),两个 Slice a 和 b,a.start_with(b) 判断 b 是否是 a 的一个前缀
- compare(),比较两个 Slice a 和 b 的大小,a.compare(b) 判断的是 a 是否小于 b,采用字典序比较大小
3. 总结
关于 Slice 记住两点就行了:
- Slice 不管理内存,它只操作用户提供的字符串,用户需要自己管理该字符串的内存
- Slice 不改变所操作字符串的内容
LevelDB(v1.3) 源码阅读之 Slice的更多相关文章
- LevelDB(v1.3) 源码阅读之 Arena(内存管理器)
LevelDB(v1.3) 源码阅读系列使用 LevelDB v1.3 版本的代码,可以通过如下方式下载并切换到 v1.3 版本的代码: $ git clone https://github.com/ ...
- kubernetes源码阅读及编译
kubernetes源码阅读 工欲善其事,必先利其器.在阅读kubernetes源码时,我也先后使用过多个IDE,最终还是停留在IDEA上. 我惯用的是pycharm(IDEA的python IDE版 ...
- 【 js 基础 】【 源码学习 】backbone 源码阅读(二)
最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(source-code-study)进行参考交流,有详细的源码注释,以及知识总结,同时 ...
- koa源码阅读[2]-koa-router
koa源码阅读[2]-koa-router 第三篇,有关koa生态中比较重要的一个中间件:koa-router 第一篇:koa源码阅读-0第二篇:koa源码阅读-1-koa与koa-compose k ...
- JDK源码阅读(一):Object源码分析
最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...
- 如何进行高效的源码阅读:以Spring Cache扩展为例带你搞清楚
摘要 日常开发中,需要用到各种各样的框架来实现API.系统的构建.作为程序员,除了会使用框架还必须要了解框架工作的原理.这样可以便于我们排查问题,和自定义的扩展.那么如何去学习框架呢.通常我们通过阅读 ...
- Sping学习笔记(一)----Spring源码阅读环境的搭建
idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...
- Kubernetes 学习(九)Kubernetes 源码阅读之正式篇------核心组件之 Scheduler
0. 前言 继续上一篇博客阅读 Kubernetes 源码,参照<k8s 源码阅读>首先学习 Kubernetes 的一些核心组件,首先是 kube-scheduler 本文严重参考原文: ...
- go 中 select 源码阅读
深入了解下 go 中的 select 前言 1.栗子一 2.栗子二 3.栗子三 看下源码实现 1.不存在 case 2.select 中仅存在一个 case 3.select 中存在两个 case,其 ...
随机推荐
- [游戏模版3] Win32 画笔 画刷 图形
>_<:introduce the functions of define\create\use pen and brush to draw all kinds of line and s ...
- SharePoint 2013 REST 以及 OData 基础
这篇文章会介绍: 简单的介绍REST,OData OData实现细节 OData在SharePoint 2013中的实现 为什么REST很重要 过去几年基于REST的webservice在IT企业越来 ...
- C++ 标准IO库
<C++ Primer 4th>读书笔记 C++ 的输入/输出(input/output)由标准库提供.标准库定义了一族类型,支持对文件和控制窗口等设备的读写(IO).还定义了其他一些类型 ...
- Atitit.词法分析的原理 理论
Atitit.词法分析的原理 理论 1. 分词 .词法分析lexical analysis 1 1.1. 分词主要流程 1 1.2. 分词的属性如下表token 1 1.3. 词法分析器主要包括:构造 ...
- Atitit org.eclipse.jdt 的ast 架构 Eclipse JDT API spec
Atitit org.eclipse.jdt 的ast 架构 Eclipse JDT API spec 继承树1 Expression的子类1 获取子类2 继承树 Astnode>express ...
- Jenkins + GitHub + fir-cli 一行命令从源码到fir.im
上周简书作者宣X_x 分享了一篇文章--用Jenkins+GitHub+Xcode+fir搭了一个持续集成环境,整个记录见(传送门). _______ 其实fir.im为我们提供了一个更简单的方式: ...
- c#之第二课
输出语句: /////////////////////////////// public class Hello1 { public static void Main() { System.Conso ...
- 使用VSTS/TFS搭建iOS持续集成环境
TFS 自2015版开始支持跨平台的持续集成环境,通过提供开源的build agent为 Windows / linux / macOS 提供了统一的持续集成环境管理能力.这篇文章给大家介绍一下如何使 ...
- eclipse web项目转maven项目
ps:好久没写博客了,工作了人就懒了,加油加油,up,up 1 eclipse web项目目录 /web app src com.xx.xx *.properties *.xml WebRoot W ...
- Windows XP 中设置VPN(PPTP连接方式)
第一步:点开始-网上邻居或者控制面板-网络连接,选择-创建一个新的连接 第二步:点击-下一步 第三步:选择-连接到我的工作场所的网络,点击-下一步 第四步:选择-虚拟专用网络连接,点击-下一步 第五步 ...