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,其 ...
随机推荐
- [JS5] 利用onload执行脚本
<html> <head> <title>利用onload执行脚本</title> <SCRIPT TYPE="text/JavaScr ...
- AngularJS快速入门指南07:Http对象
$http是AngularJS提供的一个服务,用来从远程服务器读取数据. 提供数据 下面的数据由Web服务器提供: { "records": [ { "Name" ...
- webView文本长按显示英文
webView文本长按显示英文时,在info.plist文件中添加如下内容: <key>CFBundleLocalizations</key> <array> &l ...
- paip.java 调用c++ dll so总结
paip.java 调用c++ dll so总结 ///////JNA (这个ms sun 的) 我目前正做着一个相关的项目,说白了JNA就是JNI的替代品,以前用JNI需要编译一层中间库,现在JNA ...
- iOS开发---集成百度地图,位置偏移问题
iOS 集成百度SDK 请参考 百度地图官方文档 ,这里不就多啰嗦了 本文介绍的是在百度地图上根据经纬度,自定义气泡时,气泡位置的偏移,在我们天朝这种事是很常见的,也见怪不怪了,在项目中使用的百度地图 ...
- super和this区别
* super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法. 4.super和this的异同: 1)super(参数):调用基类中的某一 ...
- javaweb回顾第二篇tomcat和web程序部署
前言这篇主要说下关于tomcat中一些属性和web程序的简单部署,可能在实际开发有更好的部署方式,但是这也是一个基础. 1:tomcat 关于tomcat估计只要接触java的人都听过这个名字,那我们 ...
- activiti 介绍
工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现某个预期的业务目标 ...
- 记一次Nginx 400错误
在一个非CDN的域名下有一个页面,需要请求CDN域名下的资源.所以在CDN的那台源站的Nginx上设置了 add_header 'Access-Control-Allow-Headers' 'X- ...
- 用C/C++实现对STORM的执行信息查看和控制
近期公司有个需求.须要在后端应用server上实时获取STORM集群的执行信息和topology相关的提交和控制,经过几天对STORM UI和CMD源代码的分析,得出能够通过其thrift接口调用实现 ...