Redis源码阅读-sds字符串源码阅读

redis使用sds代替char *字符串,

其定义如下:

typedef char *sds;

struct sdshdr {
    unsigned int len;
    unsigned int free;
    char buf[];
};

sds指向了char 字符串

 

sdshdr是字符串头

结构比较巧妙

使用char buf[]存放字符串实际内容

注意char *buf和char buf[]是不同的

sizeof(sdshdr)等于8,而不是我以为的12

连续内存结构如下:

 

0----7 sdshdr

8----以后  sds ,同时也是buf位置

建立sds的方法

sds sdsnewlen(const void *init, size_t initlen) {
    struct sdshdr *sh;

    if (init) {
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    } else {
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    }
    if (sh == NULL) return NULL;
    sh->len = initlen;
    sh->free = 0;
    if (initlen && init)
        memcpy(sh->buf, init, initlen);
    sh->buf[initlen] = '\0';
    return (char*)sh->buf;
}

释放sds的方法

void sdsfree(sds s) {
    if (s == NULL) return;
    zfree(s-sizeof(struct sdshdr));
}

注意sds指向的是实际的字符串,而不是sdshdr。

 

在sds.c里面有很多对sds字符串进行处理的函数,(毕竟为了取代char *)

 

函数名称

作用

复杂度

sdsnewlen

创建一个指定长度的sds,接受一个指定的C字符串作为初始化值

O(N)

sdsempty

创建一个只包含空字符串””的sds

O(N)

sdsnew

根据给定的C字符串,创建一个相应的sds

O(N)

sdsdup

复制给定的sds

O(N)

sdsfree

释放给定的sds

O(1)

sdsupdatelen

更新给定sds所对应的sdshdr的free与len值

O(1)

sdsclear

清除给定sds的buf,将buf初始化为””,同时修改对应sdshdr的free与len值

O(1)

sdsMakeRoomFor

对给定sds对应sdshdr的buf进行扩展

O(N)

sdsRemoveFreeSpace

在不改动sds的前提下,将buf的多余空间释放

O(N)

sdsAllocSize

计算给定的sds所占的内存大小

O(1)

sdsIncrLen

对给定sds的buf的右端进行扩展或缩小

O(1)

sdsgrowzero

将给定的sds扩展到指定的长度,空余的部分用\0进行填充

O(N)

sdscatlen

将一个C字符串追加到给定的sds对应sdshdr的buf

O(N)

sdscpylen

将一个C字符串复制到sds中,需要依据sds的总长度来判断是否需要扩展

O(N)

sdscatprintf

通过格式化输出形式,来追加到给定的sds

O(N)

sdstrim

对给定sds,删除前端/后端在给定的C字符串中的字符

O(N)

sdsrange

截取给定sds,[start,end]字符串

O(N)

sdscmp

比较两个sds的大小

O(N)

sdssplitlen

对给定的字符串s按照给定的sep分隔字符串来进行切割

O(N)

 

posted @ 2015-10-05 16:23  stonehat  阅读(429)  评论(0编辑  收藏  举报