redis源码解析 动态字符串- sds (6.2.3版本)

redis封装了C语言的字符串形成动态字符串(SDS)机制,SDS与纯C字符串对比为:

C字符串SDS
获取长度O(n)获取长度O(1)
API不安全,可能造成缓冲区溢出API安全,不会造成缓冲区溢出
不能操作二进制字符串,容易被截断能操作二进制字符串
不能扩容,只能深拷贝另外一个缓存区域扩容能动态扩容,而不用深拷贝字符串
修改字符串效率低修改字符串效率高

1,sds数据结构

分sdshdr5(1byte),sdshdr8(3byte),sdshdr16(5byte),sdshdr32(9byte),sdshdr64(17byte),完全是为了节省空间,不同大小的字符串,对应选择不同的头。

如过10W能用sdshdr16存储的字符串,使用sdshdr32储存,那将多用40w个字节。而在缓存服务中,内存又是稀缺资源,所以能节省就节省,存储的数据多了,就积少成多。

实际应用中,sdshdr5会自动转换为sdshdr8。

typedef char *sds;

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; //低3位代表类型,高5位为长度
    char buf[];//buf字符串
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len;//字符串长度
    uint8_t alloc; //buf开启空间的大小,可用空间为alloc-len
    unsigned char flags; //低3位代表类型,高5位未使用
    char buf[];//buf字符串
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; //字符串长度
    uint16_t alloc; //buf开启空间的大小,可用空间为alloc-len
    unsigned char flags;//低3位代表类型,高5位未使用
    char buf[];//buf字符串
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len;//字符串长度
    uint32_t alloc; //buf开启空间的大小,可用空间为alloc-len
    unsigned char flags;//低3位代表类型,高5位未使用
    char buf[];//buf字符串
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; //字符串长度
    uint64_t alloc;//buf开启空间的大小,可用空间为alloc-len
    unsigned char flags;//低3位代表类型,高5位未使用
    char buf[];//buf字符串
};

2,函数说明

SDS只是在C字符串上套了一个头,形成动态控制。实现基本也是操作char指针而已。

下面只列出函数注释即可


//创建一个initlen长度的sds字符串,如果创建不成功会返回异常
sds sdsnewlen(const void *init, size_t initlen);

//尝试创建initlen长度的sds字符串,创建不成功返回NULL
sds sdstrynewlen(const void *init, size_t initlen);

//给字符串init创建一个sdh
sds sdsnew(const char *init);

//创建一个空字符串
sds sdsempty(void);


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

//释放字符串
void sdsfree(sds s);

//扩展sds字符串长度
sds sdsgrowzero(sds s, size_t len);

//sds连接固定长度len的char字符串
sds sdscatlen(sds s, const void *t, size_t len);

//sds连接char字符串,模仿strcat
sds sdscat(sds s, const char *t);

//sds连接sds字符串,模仿strcat
sds sdscatsds(sds s, const sds t);

//sds拷贝固定长度len的char字符串
sds sdscpylen(sds s, const char *t, size_t len);

//sds拷贝char字符串
sds sdscpy(sds s, const char *t);

//sds连接格式化字符串,采用C实现格式功能
sds sdscatvprintf(sds s, const char *fmt, va_list ap);
#ifdef __GNUC__
sds sdscatprintf(sds s, const char *fmt, ...)
    __attribute__((format(printf, 2, 3)));
#else
sds sdscatprintf(sds s, const char *fmt, ...);
#endif

//sds连接格式化字符串,自定义格式化功能
sds sdscatfmt(sds s, char const *fmt, ...);

//前后去掉字符cset
sds sdstrim(sds s, const char *cset);

//截断字符串
void sdsrange(sds s, ssize_t start, ssize_t end);
//更新字符串长度
void sdsupdatelen(sds s);

//清空sds字符串
void sdsclear(sds s);

//比较两个sds字符串
int sdscmp(const sds s1, const sds s2);

//sds分割函数  对于strsplit
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count);

//释放分割出来的sds
void sdsfreesplitres(sds *tokens, int count);

//sds转小写
void sdstolower(sds s);
//sds转大写
void sdstoupper(sds s);

//longlong类型转化为sds字符串
sds sdsfromlonglong(long long value);

//sds添加转义字符字符串
sds sdscatrepr(sds s, const char *p, size_t len);

//sds根据转义字符分割,必须用sdsfreesplitres().
sds *sdssplitargs(const char *line, int *argc);

sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
//字符串连接后,转化为sds
sds sdsjoin(char **argv, int argc, char *sep);

//sds 连接sds
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);

/* Callback for sdstemplate. The function gets called by sdstemplate
 * every time a variable needs to be expanded. The variable name is
 * provided as variable, and the callback is expected to return a
 * substitution value. Returning a NULL indicates an error.
 */
typedef sds (*sdstemplate_callback_t)(const sds variable, void *arg);

//sds回调模板函数
sds sdstemplate(const char *template, sdstemplate_callback_t cb_func, void *cb_arg);

/* Low level functions exposed to the user API */
//sds扩展函数
sds sdsMakeRoomFor(sds s, size_t addlen);

//配合sdsMakeRoomFor使用,重置sds长度
void sdsIncrLen(sds s, ssize_t incr);
//sds释放空闲空间
sds sdsRemoveFreeSpace(sds s);
//计算sds开辟空间的大小
size_t sdsAllocSize(sds s);
//返回buf缓冲指针
void *sdsAllocPtr(sds s);

/* Export the allocator used by SDS to the program using SDS.
 * Sometimes the program SDS is linked to, may use a different set of
 * allocators, but may want to allocate or free things that SDS will
 * respectively free or allocate. */
 //开辟size大小的空间
void *sds_malloc(size_t size);
//如果size> ptr.length 重新开辟size大小的空间
void *sds_realloc(void *ptr, size_t size);
//释放指针空间
void sds_free(void *ptr);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值