Hacking Strings

The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dynamic Strings ).
The C structure sdshdr declared in sds.h represents a Redis string:

struct sdshdr {
long len;
long free;
char buf[];
};

The buf character array stores the actual string.
The len field stores the length of buf. This makes obtaining the length of a Redis string an O(1) operation.
The free field stores the number of additional bytes available for use.
Together the len and free field can be thought of as holding the metadata of the buf character array.

Creating Redis Strings

A new data type named sds is defined in sds.h to be a synonymn for a character pointer:

typedef char *sds;

sdsnewlen function defined in sds.c creates a new Redis String:

sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
#ifdef SDS_ABORT_ON_OOM
if (sh == NULL) sdsOomAbort();
#else
if (sh == NULL) return NULL;
#endif
sh->len = initlen;
sh->free = 0;
if (initlen) {
if (init) memcpy(sh->buf, init, initlen);
else memset(sh->buf,0,initlen);
}
sh->buf[initlen] = '\0';
return (char*)sh->buf;
}

Remember a Redis string is a variable of type struct sdshdr. But sdsnewlen returns a character pointer!!
That's a trick and needs some explanation.
Suppose I create a Redis string using sdsnewlen like below:

sdsnewlen("redis", 5);

This creates a new variable of type struct sdshdr allocating memory for len and free fields as well as for the buf character array.

sh = zmalloc(sizeof(struct sdshdr)+initlen+1); // initlen is length of init argument.

After sdsnewlen succesfully creates a Redis string the result is something like:

-----------
|5|0|redis|
-----------
^ ^
sh sh->buf

sdsnewlen returns sh->buf to the caller.

What do you do if you need to free the Redis string pointed by sh?
You want the pointer sh but you only have the pointer sh->buf.
Can you get the pointer sh from sh->buf?
Yes. Pointer arithmetic. Notice from the above ASCII art that if you subtract the size of two longs from sh->buf you get the pointer sh
The sizeof two longs happens to be the size of struct sdshdr.
Look at sdslen function and see this trick at work:

size_t sdslen(const sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
return sh->len;
}

Knowing this trick you could easily go through the rest of the functions in sds.c.
The Redis string implementation is hidden behind an interface that accepts only character pointers. The users of Redis strings need not care about how its implemented and treat Redis strings as a character pointer.

C Struct array member without specific length

Redis代码阅读之Hacking Strings的更多相关文章

  1. 代码阅读分析工具Understand 2.0试用

    Understand 2.0是一款源代码阅读分析软件,功能强大.试用过一段时间后,感觉相当不错,确实可以大大提高代码阅读效率.由于Understand功能十分强大,本文不可能详尽地介绍它的所有功能,所 ...

  2. Android 上的代码阅读器 CoderBrowserHD 修改支持 go 语言代码

    我在Android上的代码阅读器用的是 https://github.com/zerob13/CoderBrowserHD 改造的版本,改造后的版本我放在 https://github.com/ghj ...

  3. Linux协议栈代码阅读笔记(二)网络接口的配置

    Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...

  4. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  5. Session for Tornado(Redis) - 代码分享

    Session for Tornado(Redis) - 代码分享   Session for Tornado(Redis) session id的生成借用了web.py. 使用了 redis 的 h ...

  6. 图形化代码阅读工具——Scitools Understand

    Scitools出品的Understand 2.0.用了很多年了,比Source Insight强大很多.以前的名字叫Understand for C/C++,Understand for Java, ...

  7. Python - 关于代码阅读的一些建议

    初始能力 让阅读思路保持清晰连贯,主力关注在流程架构和逻辑实现上,不被语法.技巧和业务流程等频繁地阻碍和打断. 建议基本满足以下条件,再开始进行代码阅读: 具备一定的语言基础:熟悉基础语法,常用的函数 ...

  8. MediaInfo代码阅读

      MediaInfo是一个用来分析媒体文件的开源工具. 支持的文件非常全面,基本上支持所有的媒体文件. 最近是在做HEVC开发,所以比较关注MediaInfo中关于HEVC的分析与处理. 从Meid ...

  9. Tools - 一些代码阅读的方法

    1 初始能力 让阅读思路清晰连贯,保持在程序的流程架构和逻辑实现上,不被语法.编程技巧和业务流程等频繁地阻碍和打断. 语言基础:熟悉基础语法,常用的函数.库.编程技巧等: 了解设计模式.构建工具.代码 ...

随机推荐

  1. 从3D Touch 看 原生快速开发

    全新的按压方式苹果继续为我们带来革命性的交互:Peek和Pop,Peek 和 Pop 让你能够预览所有类型的内容,甚至可对内容进行操作,却不必真的打开它们.例如,轻按屏幕,可用 Peek 预览收件箱中 ...

  2. 通过分析iframe和无阻塞脚本关系能让我们更懂iframe

    在我上篇文章里,我提到一种使用iframe完成无阻塞脚本加载的方式,因为我对iframe的偏见很大,所以上篇文章里我没有展开讨论这个问题. 文章发表后有位网友问了我这样一个问题,下面是他问题的原文,如 ...

  3. 使用OData技术遇到的问题及解决办法

    “System.NotSupportedException”类型的未经处理的异常在 Microsoft.Data.Services.Client.dll 中发生 其他信息: 对此 POST 请求的响应 ...

  4. Java连接Oracle数据库开发银行管理系统【二、设计篇】

    一.总体分析     此系统的实现并不难,但是如何更好的设计出实现方式还是需要更深入的分析,例如:如果再增加其他功能,是不是需要变动的 代码很少,只是直接再增加一点功能就可以了呢?如果使用的不是Ora ...

  5. Java连接Oracle数据库开发银行管理系统【一、需求篇】

    此系统开发共分为三篇完成. 第一篇[需求篇]:效果展示图,也就是需求部分的展示 第二篇[设计篇]:需求分析和类,接口的设计 第三篇[实现篇]:具体代码实现

  6. 爱上MVC~AuthorizeAttribute验证不通过如何停止当前上下文

    回到目录 我们知道mvc里有一些过滤器,AuthorizeAttribute用来做授权,一般在用户授权方面可以使用它,当使用没有登陆,我们直接跳到登陆页,这是没有问题的,可我要说的是,当用户对某个Ac ...

  7. [Spring框架]Spring 事务管理基础入门总结.

    前言:在之前的博客中已经说过了数据库的事务, 不过那里面更多的是说明事务的一些锁机制, 今天来说一下Spring管理事务的一些基础知识. 之前的文章: [数据库事务与锁]详解一: 彻底理解数据库事务一 ...

  8. HQL查询语言——转载(http://www.cnblogs.com/20gg-com/p/6045739.html)

    Hibernate查询语言(HQL)是一种面向对象的查询语言,类似于SQL,但不是对表和列操作,HQL适用于持久对象和它们的属性. HQL查询由Hibernate转换成传统的SQL查询,这在圈上的数据 ...

  9. web应用程序性能优化

    web应用程序基本上都是在浏览器地址栏输入一段网站,然后进入,最后浏览器显示你想要的东西. 这就是用户所能体会到的东西.那作为程序员我们看到了什么呢? 一次HTTP 请求主要的流程是: 1.DNS服务 ...

  10. jquery.validate 基础

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...