深入redis内部--实现字符串

redis字符串的定义和实现在Ssd.h和Ssd.c中。

1.定义

typedef char *sds; //本质是字符char的指针

2.字符串的操作

sds sdsnew(const char *init) {    size_t initlen = (init == NULL) ? 0 : strlen(init);    return sdsnewlen(init,initlen);}

调用sdsnewlen,看一下该函数的实现

sds sdsnewlen(const void *init,size_t initlen) {    struct *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;}

该函数使用redis自定义函数的zmalloc或者zcalloc分配内存(以后章节会专门深入这些函数)。

3.创建字符串使用了另一个结构(红色标注)

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

从上面的函数可以得出创建字符串时,返回的是一个字符数组的指针。

该结构和字符串的关系如下:

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

4. 操作字符串的方法

sds sdsnewlen(const void *init,size_t initlen);      //实际真正创建字符串的函数,使用sdsnew创建字符串时该函数被调用。

sds sdsnew(const char *init);                             //创建字符串函数

sds sdsempty(void);                                        //创建一个长度为0的空字符串

size_t sdslen(const sds s);                              //计算字符串的长度

 sds sdsdup(const sds s);                                //复制字符串

void sdsfree(sds s);                                        //从内存中释放字符串,调用zfree方法

size_t sdsavail(const sds s);                                       //计算字符串的可用长度(字符数组中还没有使用的长度)

sds sdsgrowzero(sds s,size_t len);                              //增加字符串的内存,并使用'\0'填充

sds sdscatlen(sds s,const void *t,size_t len);              //字符串拼接常量实现函数,使用sdscat时调用该函数

sds sdscat(sds s,const char *t);                                  //字符串拼接常量函数

                 sds sdscatsds(sds s,const sds t);                                //字符串拼接字符串函数

sds sdscpylen(sds s,const char *t,size_t len);              //字符串复制的执行函数

sds sdscpy(sds s,const char *t);                                 //将字符串t复制到s中,若s空间不足,使用sdsgrowzero增加空间sds sdscatvprintf(sds s,const char *fmt,va_list ap);    //类似sdscatprintf,但参数不是变长的,是固定的#ifdef __GNUC__                                                       //如果是linux平台,使用GNU编译器sds sdscatprintf(sds s,...)    __attribute__((format(printf,2,3)));                      //

#elsesds sdscatprintf(sds s,...);            //向参数s添加字符串,实例:s = sdscatprintf(s,"%d+%d = %d",a,b,a+b).#endifsds sdstrim(sds s,const char *cset);                     //从左边或者后边移除制定的字符串cset,

                                                                          * Example:                                                                          * s = sdsnew("AA...AA.a.aa.aHelloWorld     :::");                                                                          * s = sdstrim(s,"A. :");                                                                          * printf("%s\n",s);                                                                          * Output will be just "Hello World".

sds sdsrange(sds s,int start,int end);           //从字符串s中截取制定索引位置的子字符串。

void sdsupdatelen(sds s);                            //更新字符串的长度。应用实例: 如果没有sdsupdatelen,则结果为2,有则结果为6

                                                                   * s = sdsnew("foobar");                                                                   * s[2] = '\0';

                                                                   * sdsupdatelen(s);                                                                  * printf("%d\n",sdslen(s));

void sdsclear(sds s);                                     //将字符串的buf设置为'\0'

int sdscmp(const sds s1,const sds s2);        //使用memcpy()比较两个字符串,如果s1>s2则结果为1,s1=s2则结果为0,s1

sds *sdssplitlen(const char *s,int len,const char *sep,int seplen,int *count);//使用sep分隔符分割s,返回字符串数组

void sdsfreesplitres(sds *tokens,int count); //tokens为null时不执行任何操作,否则清空sdssplitlen()函数返回的结果。

void sdstolower(sds s);                             //将字符串的每个字符转换为小写形式

void sdstoupper(sds s);                           //将字符串的每个字符转换为大写形式

sds sdsfromlonglong(long long value);                  //当数字太大的时候,直接将数字转化为字符串.sds sdscatrepr(sds s,const char *p,size_t len);   //添加引用字符串sds *sdssplitargs(const char *line,int *argc);       //反向解析,可以做命令行解析

sds sdsmapchars(sds s,const char *from,const char *to,size_t setlen); 

                        /* 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.                        * For instance: sdsmapchars(mystring,"ho","01",2)                        * will have the effect of turning the string "hello" into "0ell1".

sds sdsMakeRoomFor(sds s,size_t addlen);

                           * Enlarge the free space at the end of the sds string so that the caller

void sdsIncrLen(sds s,int incr);                //根据incr来在字符串的尾部增加字符串长度或者减少剩余字符串空间sds sdsRemoveFreeSpace(sds s);            //当字符串没有剩余空间时,重新分配字符串。size_t sdsAllocSize(sds s);                      //

相关文章

文章浏览阅读1.3k次。在 Redis 中,键(Keys)是非常重要的概...
文章浏览阅读3.3k次,点赞44次,收藏88次。本篇是对单节点的...
文章浏览阅读8.4k次,点赞8次,收藏18次。Spring Boot 整合R...
文章浏览阅读978次,点赞25次,收藏21次。在Centos上安装Red...
文章浏览阅读1.2k次,点赞21次,收藏22次。Docker-Compose部...
文章浏览阅读2.2k次,点赞59次,收藏38次。合理的JedisPool资...