redis中对字符串进行了一些特殊的处理,在每个字符串前面增加了一个头结构,头结构保存了字符串的长度、内存大小和类型,redis根据字符串长短定义了5种字符串头结构类型:sdshdr5(没使用)、sdshdr8、sdshdr16、sdshdr32、sdshdr64
len表示字符串长度
alloc表示除头部和结束标志后内存大小
flags表示字符串头部的类型(SDS_TYPE_8等)
buf可变长数组,存放字符串数据,可以使头部和字符串内存空间是连续的,减少内存碎片
/* 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 lsb of type, and 5 msb of string length */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* used */
uint8_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
uint16_t len; /* used */
uint16_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len; /* used */
uint32_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
uint64_t len; /* used */
uint64_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
sdsnewlen :根据字符串和长度创建一个新的sds字符串
sds sdsnewlen(const void *init, size_t initlen) {
void *sh;
sds s;
//根据字符串大小判断应该用哪个sds type
char type = sdsReqType(initlen);
/* Empty strings are usually created in order to append. Use type 8
* since type 5 is not good at this. */
//创建空字符串主要是为了后面追加内容,type 5不适用,用type 8代替
if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
//获取sds头部长度
int hdrlen = sdsHdrSize(type);
unsigned char *fp; /* flags pointer. */
// 申请内存大小 = sds头部长度 + 初始字符串长度 + 1个结束标志符
sh = s_malloc(hdrlen+initlen+1);
if (init==SDS_NOINIT) // 如果init==SDS_NOINIT(这里判断地址是否相同),设置init为NULL
init = NULL;
else if (!init) // 清空内存内容
memset(sh, 0, hdrlen+initlen+1);
if (sh == NULL) return NULL;
s = (char*)sh+hdrlen; // c字符串
fp = ((unsigned char*)s)-1; // 标志位(sdshdr_xx中flags)
switch(type) { // 根据得到的sds类型设置头部信息
case SDS_TYPE_5: {
*fp = type | (initlen << SDS_TYPE_BITS);
break;
}
case SDS_TYPE_8: {
SDS_HDR_VAR(8,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
case SDS_TYPE_16: {
SDS_HDR_VAR(16,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
case SDS_TYPE_32: {
SDS_HDR_VAR(32,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
case SDS_TYPE_64: {
SDS_HDR_VAR(64,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
}
if (initlen && init) // 拷贝字符串到sds字符串中
memcpy(s, init, initlen);
s[initlen] = '\0'; // 设置标准结束符
return s;
}
sdsempty:创建一个空的sds字符串
sds sdsnew(const char *init):根据c字符串init创建一个sds字符串
sds sdsdup(const sds s):和sdsnew类似,根据sds字符串创建一个新的sds字符串
void sdsfree(sds s):释放sds字符串内存
void sdsupdatelen(sds s):更新sds字符串头部记录的长度,一般通过s[i] = '\0'修改过字符串后使用
void sdsclear(sds s):清空s内容
sds sdsMakeRoomFor(sds s, size_t addlen):对s扩充addlen个字节,新字符串长度newlen,根据newlen *2判断调整后的sds头部类型,如果newlen大于等于1024*1024,根据newlen+1024*1024判断头部类型
sds sdsRemoveFreeSpace(sds s):和sdsMakeRoomFor对应,去除s中多余的部分
size_t sdsAllocSize(sds s):获取字符串s占用内存大小(包括头部和结束符)
void *sdsAllocPtr(sds s):获取字符串s内存的起始地址,也就是头部地址
void sdsIncrLen(sds s, ssize_t incr):字符串s增加长度incr,并设置结束符
sds sdsgrowzero(sds s, size_t len):对s设置为指定长度len,空余部分填充0,len比s长度小的时候不做操作
sds sdscatlen(sds s, const void *t, size_t len):在s后面拼接t中长度为len的内容,并设置结束符
sds sdscat(sds s, const char *t):同sdscatlen,长度通过strlen(t)获取
sds sdscatsds(sds s, const sds t):同sdscatlen,长度通过sdslen(t)获取
sds sdscpylen(sds s, const char *t, size_t len):拷贝t中len长度内容到s,根据len调整s内存大小
sds sdscpy(sds s, const char *t):同sdscpylen,长度通过strlen(t)获取
int sdsll2str(char *s, long long value):long long类型转c字符串
int sdsull2str(char *s, unsigned long long v):unsigned long long类型转c字符串
sds sdsfromlonglong(long long value):value转sds字符串
sds sdscatvprintf(sds s, const char *fmt, va_list ap):在s后面格式化拼接字符串,fmt格式化字符串,ap可变参数
sds sdscatprintf(sds s, const char *fmt, ...):同sdscatvprintf,内部调用sdscatvprintf,可变参数不太一样
sds sdscatfmt(sds s, char const *fmt, ...):类似sdscatprintf,内部不调用c标准函数sprintf,自定义了几种格式化标记
%s - C String c字符串
%S - SDS string sds字符串
%i - signed int 有符号整型
%I - 64 bit signed integer (long long, int64_t) 64位有符号整型
%u - unsigned int 无符号整型
%U - 64 bit unsigned integer (unsigned long long, uint64_t) 64位无符号整型
%% - Verbatim "%" character 转义为%
sds sdstrim(sds s, const char *cset):把同时在s和cset中的字符从s中删除
void sdsrange(sds s, ssize_t start, ssize_t end):截取start和end之间的字符串,start和end支持负数,-1表示从末尾数1
void sdstolower(sds s):转换为小写
void sdstoupper(sds s):转换为大写
int sdscmp(const sds s1, const sds s2):对比字符串,s1>s2返回正数,s1<s2返回负数,内容相同返回0
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) :以sep拆分s,返回拆分后的sds字符串数 组,count传出数组的长度
void sdsfreesplitres(sds *tokens, int count):释放sdssplitlen返回的数组
sds *sdssplitargs(const char *line, int *argc):以单引号或双引号分解字符串,并且翻译转义字符\x、\n、\t等
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen):例如sdsmapchars("hello", "ho", "01", 2)返回"0ell1",h对应0,0对应1替换
sds sdsjoin(char **argv, int argc, char *sep):字符串数组argv,数组有argc个元素,以sep作为分割符,拼接成一个sds字符串
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen):同sdsjoin,该函数拼接对象是sds字符串数组