Redis源码学习笔记

Redis源码学习基本数据结构之动态字符串sds

2019-04-02  本文已影响0人  lixin_karl
一、sds是什么

字符串是Redis中最为常见的数据存储类型,其底层实现是简单动态字符串sds(simple dynamic string),是可以修改的字符串。它的内存管理模式类似于c++中的vector,它采用预分配冗余空间的方式来减少内存的频繁分配。关联源码sds.c/sds.h

typedef char *sds 

sds实际上就是一个char指针。它来自于跟它相关的结构体的一部分,其中一共有5个结构体相关根据以下5个值判断属于哪个结构体

#define SDS_TYPE_5  0
#define SDS_TYPE_8  1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4

其中,SDS_TYPE_5 目前没有用,会用SDS_TYPE_8来代替。它是根据数据的长度来决定使用什么结构体的,对于SDS_TYPE_8 对应的结构体为

struct sdshdr8{
    uint8_t len; /*使用了多少 即数据长度 类似vector size()*/
    uint8_t alloc; /* 申请了多少内存 类似于vector capacity()*/
    unsigned char flags; /* 具体的sdshdr类型 可以节省内存*/
    char buf[];/* 实际数据也是sds开始的地址 */
}

二、sds特点

sds sdsnewlen(const void *init, size_t initlen);//申请内存申请内存的长度为(对应结构体的长度+1+initlen) 最后一个字节会赋值'\0',这点可以保证对普通字符串的兼容
sds sdsnew(const char *init);//根据一个普通字符串在创建sds
sds sdsempty(void);//创建一个空的sds
sds sdsdup(const sds s);//复制一个sds 重新申请内存

void sdsfree(sds s);//释放申请出来的内存

sds sdsgrowzero(sds s, size_t len);//sds动态空间增加到特定的长度,最多申请SDS_MAX_PREALLOC
sds sdscatlen(sds s, const void *t, size_t len);//字符串拼接
sds sdscat(sds s, const char *t);//字符串拼接
sds sdscatsds(sds s, const sds t);//sds拼接
sds sdscpylen(sds s, const char *t, size_t len);//sds复制
sds sdscpy(sds s, const char *t);//sds复制
sds sdscatvprintf(sds s, const char *fmt, va_list ap);//字符串拼接
sds sdscatfmt(sds s, char const *fmt, ...);//字符串拼接

sds sdstrim(sds s, const char *cset);//移除s中是 cset中的字符

void sdsrange(sds s, ssize_t start, ssize_t end);//sds子字符串

void sdsupdatelen(sds s);//字符串实际长度

void sdsclear(sds s);//字符串清理,相关数据赋值为0

int sdscmp(const sds s1, const sds s2);//字符串比较
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count);//s中以sep为分隔标志,返回分隔后的sds数组

void sdsfreesplitres(sds *tokens, int count);//将分隔出来的字符串数组释放掉内存

void sdstolower(sds s);//都变成小写字符
void sdstoupper(sds s);//都变成大写字符

sds sdsfromlonglong(long long value);//longlong变成sds

sds sdscatrepr(sds s, const char *p, size_t len);//一些特殊字符的拼接
sds *sdssplitargs(const char *line, int *argc);//将line分割argc个sds数组

sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);//把sds中出现在from中的字符替换为to中的对应位置的字符
sds sdsjoin(char **argv, int argc, char *sep);//字符串连接
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);//字符串连接

/* 底层用户调用api */
sds sdsMakeRoomFor(sds s, size_t addlen);//重新申请内存
void sdsIncrLen(sds s, ssize_t incr);
sds sdsRemoveFreeSpace(sds s);//移除冗余的空间,增加内存的效率
size_t sdsAllocSize(sds s);//返回总的申请的内存
void *sdsAllocPtr(sds s);//返回最初申请的一段内存的起始位置


void *sds_malloc(size_t size);///申请内存
void *sds_realloc(void *ptr, size_t size);//重新申请内存
void sds_free(void *ptr);//释放内存
上一篇下一篇

猜你喜欢

热点阅读