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)
|