SDS相比传统C语言的字符串有以下好处:

(1)空间预分配和惰性释放,这就可以减少内存重新分配的次数

(2)O(1)的时间复杂度获取字符串的长度

(3)二进制安全

主要总结一下sds.c和sds.h中的关键函数

1、sdsmapchars

 /* Modify the string substituting all the occurrences of the set of
* characters specified in the 'from' string to the corresponding character
* in the 'to' array.
*
* 将字符串 s 中,
* 所有在 from 中出现的字符,替换成 to 中的字符
*
* For instance: sdsmapchars(mystring, "ho", "01", 2)
* will have the effect of turning the string "hello" into "0ell1".
*
* 比如调用 sdsmapchars(mystring, "ho", "01", 2)
* 就会将 "hello" 转换为 "0ell1"
*
* The function returns the sds string pointer, that is always the same
* as the input pointer since no resize is needed.
* 因为无须对 sds 进行大小调整,
* 所以返回的 sds 输入的 sds 一样
*
* T = O(N^2)
*/
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {
size_t j, i, l = sdslen(s); // 遍历输入字符串
for (j = ; j < l; j++) {
// 遍历映射
for (i = ; i < setlen; i++) {
// 替换字符串
if (s[j] == from[i]) {
s[j] = to[i];
break;
}
}
}
return s;
}

2、sdstrim

/*
* 对 sds 左右两端进行修剪,清除其中 cset 指定的所有字符
*
* 比如 sdsstrim(xxyyabcyyxy, "xy") 将返回 "abc"
*
* 复杂性:
* T = O(M*N),M 为 SDS 长度, N 为 cset 长度。
*/
/* Remove the part of the string from left and from right composed just of
* contiguous characters found in 'cset', that is a null terminted C string.
*
* After the call, the modified sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call.
*
* Example:
*
* s = sdsnew("AA...AA.a.aa.aHelloWorld :::");
* s = sdstrim(s,"A. :");
* printf("%s\n", s);
*
* Output will be just "Hello World".
*/ /*
惰性空间释放 惰性空间释放用于优化 SDS 的字符串缩短操作: 当 SDS 的 API 需要缩短 SDS 保存的字符串时,
程序并不立即使用内存重分配来回收缩短后多出来的字节,
而是使用 free 属性将这些字节的数量记录起来, 并等待将来使用。 举个例子, sdstrim 函数接受一个 SDS 和一个 C 字符串作为参数,
从 SDS 左右两端分别移除所有在 C 字符串中出现过的字符。
*/
//把释放的字符串字节数添加到free中,凭借free和len就可以有效管理空间 //接受一个 SDS 和一个 C 字符串作为参数, 从 SDS 左右两端分别移除所有在 C 字符串中出现过的字符。 sds sdstrim(sds s, const char *cset) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
char *start, *end, *sp, *ep;
size_t len; // 设置和记录指针
sp = start = s;
ep = end = s+sdslen(s)-; // 修剪, T = O(N^2)
/***
* 函数原型:extern char *strchr(char *str,char character)
* 参数说明:str为一个字符串的指针,character为一个待查找字符。
* 所在库名:#include <string.h>
* 函数功能:从字符串str中寻找字符character第一次出现的位置。
* 返回说明:返回指向第一次出现字符character位置的指针,如果没找到则返回NULL。
* 其它说明:还有一种格式char *strchr( const char *string, int c ),这里字符串是以int型给出的。
*
* cset是我们要在首尾trim的字符串 在原始字符串里面的首尾分别取一个字符判断是否在cset中
* 双指针操作去找到最后有效的首尾指针的地址
***/
while(sp <= end && strchr(cset, *sp)) sp++;
while(ep > start && strchr(cset, *ep)) ep--; // 计算 trim 完毕之后剩余的字符串长度
len = (sp > ep) ? : ((ep-sp)+); // 如果有需要,前移字符串内容
// T = O(N)
if (sh->buf != sp) memmove(sh->buf, sp, len); // 添加终结符
sh->buf[len] = '\0'; // 更新属性
sh->free = sh->free+(sh->len-len);
sh->len = len; // 返回修剪后的 sds
return s;
}

3、sdsll2str

 int sdsll2str(char *s, long long value) {
char *p, aux;
unsigned long long v;
size_t l; /* Generate the string representation, this method produces
* an reversed string. */
v = (value < ) ? -value : value;
p = s;
do {
*p++ = ''+(v%);
v /= ;
} while(v);
if (value < ) *p++ = '-'; /* Compute length and add null term. */
l = p-s;
*p = '\0'; /* Reverse the string. */
p--;
while(s < p) {
aux = *s;
*s = *p;
*p = aux;
s++;
p--;
}
return l;
}

4、sdssplitlen

 /* Split 's' with separator in 'sep'. An array
* of sds strings is returned. *count will be set
* by reference to the number of tokens returned.
*
* 使用分隔符 sep 对 s 进行分割,返回一个 sds 字符串的数组。
* *count 会被设置为返回数组元素的数量。
*
* On out of memory, zero length string, zero length
* separator, NULL is returned.
*
* 如果出现内存不足、字符串长度为 0 或分隔符长度为 0
* 的情况,返回 NULL
*
* Note that 'sep' is able to split a string using
* a multi-character separator. For example
* sdssplit("foo_-_bar","_-_"); will return two
* elements "foo" and "bar".
*
* 注意分隔符可以的是包含多个字符的字符串
*
* This version of the function is binary-safe but
* requires length arguments. sdssplit() is just the
* same function but for zero-terminated strings.
*
* 这个函数接受 len 参数,因此它是二进制安全的。
* (文档中提到的 sdssplit() 已废弃)
*
* T = O(N^2)
*/
sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {
int elements = , slots = , start = , j;
sds *tokens; if (seplen < || len < ) return NULL; tokens = zmalloc(sizeof(sds)*slots);
if (tokens == NULL) return NULL; if (len == ) {
*count = ;
return tokens;
} // T = O(N^2)
for (j = ; j < (len-(seplen-)); j++) {
/* make sure there is room for the next element and the final one */
if (slots < elements+) {
sds *newtokens; slots *= ;
newtokens = zrealloc(tokens,sizeof(sds)*slots);
if (newtokens == NULL) goto cleanup;
tokens = newtokens;
}
/* search the separator */
// T = O(N)
if ((seplen == && *(s+j) == sep[]) || (memcmp(s+j,sep,seplen) == )) {
tokens[elements] = sdsnewlen(s+start,j-start);
if (tokens[elements] == NULL) goto cleanup;
elements++;
start = j+seplen;
j = j+seplen-; /* skip the separator */
}
}
/* Add the final element. We are sure there is room in the tokens array. */
tokens[elements] = sdsnewlen(s+start,len-start);
if (tokens[elements] == NULL) goto cleanup;
elements++;
*count = elements;
return tokens; cleanup:
{
int i;
for (i = ; i < elements; i++) sdsfree(tokens[i]);
zfree(tokens);
*count = ;
return NULL;
}
}

redis源码学习_简单动态字符串的更多相关文章

  1. Redis源码阅读一:简单动态字符串SDS

    源码阅读基于Redis4.0.9 SDS介绍 redis 127.0.0.1:6379> SET dbname redis OK redis 127.0.0.1:6379> GET dbn ...

  2. redis源码学习_整数集合

    redis里面的整数集合保存的都是整数,有int_16.int_32和int_64这3种类型,和C++中的set容器差不多. 同时具备如下特点: 1.set里面的数不重复,均为唯一. 2.set里面的 ...

  3. redis源码学习_字典

    redis中字典有以下要点: (1)它就是一个键值对,对于hash冲突的处理采用了头插法的链式存储来解决. (2)对rehash,扩展就是取第一个大于等于used * 2的2 ^ n的数作为新的has ...

  4. redis源码学习_链表

    redis的链表是双向链表,该链表不带头结点,具体如下: 主要总结一下adlist.c和adlist.h里面的关键结构体和函数. 链表节点结构如下: /* * 双端链表节点 */ typedef st ...

  5. Redis源码学习:字符串

    Redis源码学习:字符串 1.初识SDS 1.1 SDS定义 Redis定义了一个叫做sdshdr(SDS or simple dynamic string)的数据结构.SDS不仅用于 保存字符串, ...

  6. Redis源码学习:Lua脚本

    Redis源码学习:Lua脚本 1.Sublime Text配置 我是在Win7下,用Sublime Text + Cygwin开发的,配置方法请参考<Sublime Text 3下C/C++开 ...

  7. 柔性数组(Redis源码学习)

    柔性数组(Redis源码学习) 1. 问题背景 在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到.其实在工作中有遇到过这 ...

  8. 『TensorFlow』SSD源码学习_其一:论文及开源项目文档介绍

    一.论文介绍 读论文系列:Object Detection ECCV2016 SSD 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层feature map 多层feat ...

  9. __sync_fetch_and_add函数(Redis源码学习)

    __sync_fetch_and_add函数(Redis源码学习) 在学习redis-3.0源码中的sds文件时,看到里面有如下的C代码,之前从未接触过,所以为了全面学习redis源码,追根溯源,学习 ...

随机推荐

  1. Windows7下安装与破解IntelliJ IDEA2017(转载)

    IDEA 全称 IntelliJ IDEA,是Java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持.各类版本工具( ...

  2. etcd,Docker问题汇总

    单节点etcd publish error 正在愉快的进行jenkins流程,突然发现etcd连接不上去了.重新reboot后发现日志publish error Oct :: k8s-master e ...

  3. ASP.NET MVC & Web API Brief Introduction

    Pure Web Service(ASMX): Starting back in 2002 with the original release of .NET, a developer could f ...

  4. NSPredicate模糊搜索和精确搜索

    #pragma mark ------------ searchBar 代理方法 -------------------------- - (void)searchBar:(UISearchBar * ...

  5. 一步一步学Spring.NET——1、Spring.NET环境准备

    Spring.NET 1.3.2下载地址:http://down.51cto.com/data/861700 下载后解压 Spring.NET-1.3.2.7z:这个里面有我们须要用到的全部东西. S ...

  6. Hadoop-2.4.1学习之怎样确定Mapper数量

    MapReduce框架的优势是能够在集群中并行运行mapper和reducer任务,那怎样确定mapper和reducer的数量呢,或者说怎样以编程的方式控制作业启动的mapper和reducer数量 ...

  7. js实现页面元素随着内容的滚动而滚动

      CreateTime--2017年9月4日16:55:06 Author:Marydon js实现页面元素随着内容的滚动而滚动 分析: CSS样式,使用绝对定位确定好页面元素在屏幕的位置(如:正中 ...

  8. C语言中函数和指针的參数传递

    近期写二叉树的数据结构实验.想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个样例讨论一下c语言中指针作为形參的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个 ...

  9. oracle update left join查询

    对于有的更新语句,要更新的表可能条件不够,需要用到left join关联其他表, 但是不能直接关联,否则报错:错误如下: update imim_gireqbillitems gi left join ...

  10. JDBC:数据库操作:BLOB数据处理

    CLOB主要保存海量文字,而BLOB是专门保存二进制数据:包括,图片,音乐,影片.等. 在MYSQL中,BLOB类型使用LONGBLOB声明,最高可存储4G内容. 创建一个表: create tabl ...