redis源码分析—字符串(sds)处理

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字符串数组

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vfdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值