• Redis自定义动态字符串(sds)模块(一)


    Redis开发者在开发过程中没有使用系统的原始字符串,而是使用了自定义的sds字符串,这个模块的编写是在文件:sds.h和sds.c文件中。Redis自定义的这个字符串好像也不是很复杂,远不像nginx自定义的一样复杂,但也存在一些问题。

    在.h文件中定义了一个新的类型和一个结构体分别是:

    typedef char *sds;//定义了sds的字符串类型,使用的仍是字符串指针,只是多了个头部,具体定义见sdshdr。
    
    //动态字符串,数组的长度是可变的。
    struct sdshdr {
        unsigned int len;//记录当前串的长度。
        unsigned int free;//记录剩余的有效长度。
        char buf[];//真正的字符串位置。
    };

    先说两个小的内联函数,这个俩函数:

     1 //在本系统内所有的字符串都必须sds类型,否则用这个函数求取长度将会出错,还有一个问题,在修改了字符串的内容之后如果长度变了,要刷新头部的了len和free。否则会造成实际长度和真是长度不一致问题。
     2 static inline size_t sdslen(const sds s) 
     3 {
     4     //求取长度时,参数为字符串的地址,按照SDS的约定,字符串前面是动态数组的头部,将给定的地址
     5     //按照头部的长度前移一定长度,就可按照结构体直接获取到长度
     6     struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
     7     return sh->len;
     8 }
     9 
    10 //检查字符串的空闲部分大小
    11 static inline size_t sdsavail(const sds s) {
    12     struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    13     return sh->free;
    14 }

    sds整体接口函数一览:

    //创建一个指定内容的sds字符串,参数为内容和长度
    sds sdsnewlen(const void *init, size_t initlen);
    //创建一个指定内容的字符串,会调用上一个函数
    sds sdsnew(const char *init);
    //返回一个长度为0的sds字符串
    sds sdsempty(void);
    //返回sds字符串的长度
    size_t sdslen(const sds s);
    //复制一个已经sds字符串,会调用sdsnewlen
    sds sdsdup(const sds s);
    //获取一个sds字符串的剩余空间
    void sdsfree(sds s);
    //sds字符串是否有效,如果字符串已经释放,再调用可能会出错。
    size_t sdsavail(const sds s);
    //增长字符串
    sds sdsgrowzero(sds s, size_t len);
    //扩展sds长度,新的部分用指定字符填充
    sds sdscatlen(sds s, const void *t, size_t len);
    //扩展sds长度,扩展的长度和填充的值的长度一样
    sds sdscat(sds s, const char *t);
    //字符串拼接,将第二个拼接到第一个后面
    sds sdscatsds(sds s, const sds t);
    //将string串拼接入某个sds的后面,后面参数为string的长度
    sds sdscpylen(sds s, const char *t, size_t len);
    //调用上面的函数
    sds sdscpy(sds s, const char *t);
    
    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 sdscatfmt(sds s, char const *fmt, ...);
    //字符串剪切函数,从串中去掉某些字符
    sds sdstrim(sds s, const char *cset);
    //字符串剪切函数
    void sdsrange(sds s, int start, int end);
    //刷新字符串的长度,字符串真实的长度和len可能不一致
    void sdsupdatelen(sds s);
    //清空字符串,只是清空了长度,没有释放内存,可以继续使用
    void sdsclear(sds s);
    //串比较函数
    int sdscmp(const sds s1, const sds s2);
    //
    sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);
    void sdsfreesplitres(sds *tokens, int count);
    //转换成小写
    void sdstolower(sds s);
    //转换成大写
    void sdstoupper(sds s);
    //将longlong类型转为sds字符串
    sds sdsfromlonglong(long long value);
    sds sdscatrepr(sds s, const char *p, size_t len);
    sds *sdssplitargs(const char *line, int *argc);
    sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
    sds sdsjoin(char **argv, int argc, char *sep);
    
    /* Low level functions exposed to the user API */
    sds sdsMakeRoomFor(sds s, size_t addlen);
    void sdsIncrLen(sds s, int incr);
    //清除free记录长度的串
    sds sdsRemoveFreeSpace(sds s);
    //返回sds的真是长度,包括头部,字符串内容,尾部的0
    size_t sdsAllocSize(sds s);

    具体的内容下一篇再介绍。

  • 相关阅读:
    接口(interface)的使用于注意事项
    构造方法
    MySQL数据库软件
    final与static的作用
    区分like和in
    list,set,map各有什么异同?
    简述 Overload 与 Override
    标识符的基础知识
    类的继承关系
    MySQL常见索引失效
  • 原文地址:https://www.cnblogs.com/likui360/p/5273954.html
Copyright © 2020-2023  润新知