• 深入redis内部--实现字符串


    redis字符串的定义和实现在Ssd.h和Ssd.c中。

    1.定义

    typedef char *sds; //本质是字符char的指针

    2.字符串的操作

    sds sdsnew(const char *init) {
        size_t initlen = (init == NULL) ? 0 : strlen(init);
        return sdsnewlen(init, initlen);
    }

    调用sdsnewlen,看一下该函数的实现

    sds sdsnewlen(const void *init, size_t initlen) {
        struct sdshdr *sh;

        if (init) {
            sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
        } else {
            sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
        }
        if (sh == NULL) return NULL;
        sh->len = initlen;
        sh->free = 0;
        if (initlen && init)
            memcpy(sh->buf, init, initlen);
        sh->buf[initlen] = '';
        return (char*)sh->buf;
    }

    该函数使用redis自定义函数的zmalloc或者zcalloc分配内存(以后章节会专门深入这些函数)。

    3.创建字符串使用了另一个结构(红色标注)

    struct sdshdr {
        int len;
        int free;
        char buf[];
    };

    从上面的函数可以得出创建字符串时,返回的是一个字符数组的指针。

    该结构和字符串的关系如下:

    static inline size_t sdslen(const sds s) {
        struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
        return sh->len;
    }

    static inline size_t sdsavail(const sds s) {
        struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
        return sh->free;
    }

    4. 操作字符串的方法

    sds sdsnewlen(const void *init, size_t initlen);      //实际真正创建字符串的函数,使用sdsnew创建字符串时该函数被调用。


    sds sdsnew(const char *init);                             //创建字符串函数


    sds sdsempty(void);                                        //创建一个长度为0的空字符串


    size_t sdslen(const sds s);                              //计算字符串的长度

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


    void sdsfree(sds s);                                        //从内存中释放字符串,调用zfree方法


    size_t sdsavail(const sds s);                                       //计算字符串的可用长度(字符数组中还没有使用的长度)


    sds sdsgrowzero(sds s, size_t len);                              //增加字符串的内存,并使用''填充


    sds sdscatlen(sds s, const void *t, size_t len);              //字符串拼接常量实现函数,使用sdscat时调用该函数


    sds sdscat(sds s, const char *t);                                  //字符串拼接常量函数

                    
    sds sdscatsds(sds s, const sds t);                                //字符串拼接字符串函数


    sds sdscpylen(sds s, const char *t, size_t len);              //字符串复制的执行函数


    sds sdscpy(sds s, const char *t);                                 //将字符串t复制到s中,若s空间不足,使用sdsgrowzero增加空间

    sds sdscatvprintf(sds s, const char *fmt, va_list ap);    //类似sdscatprintf,但参数不是变长的,是固定的
    #ifdef __GNUC__                                                       //如果是linux平台,使用GNU编译器
    sds sdscatprintf(sds s, const char *fmt, ...)
        __attribute__((format(printf, 2, 3)));                      //format (archetype, string-index, first-to-check) 告诉编译器,按照printf, scanf, strftime

                                                                                 //或strfmon的参数表格式规则对该函数的参数进行检查。“archetype”指定是哪种风格;

                                                                                 //“string-index”指定传 入函数的第几个参数是格式化字符串;“first-to-check”

                                                                                //指定从函数的第几个参数开始按上述规则进行检查。
    #else
    sds sdscatprintf(sds s, const char *fmt, ...);            //向参数s添加字符串,实例:s = sdscatprintf(s,"%d+%d = %d",a,b,a+b).
    #endif

    sds sdstrim(sds s, const char *cset);                     //从左边或者后边移除制定的字符串cset,

                                                                              * Example:
                                                                              * s = sdsnew("AA...AA.a.aa.aHelloWorld     :::");
                                                                              * s = sdstrim(s,"A. :");
                                                                              * printf("%s ", s);
                                                                              * Output will be just "Hello World".


    sds sdsrange(sds s, int start, int end);           //从字符串s中截取制定索引位置的子字符串。


    void sdsupdatelen(sds s);                            //更新字符串的长度。应用实例: 如果没有sdsupdatelen,则结果为2,有则结果为6

                                                                       * s = sdsnew("foobar");
                                                                       * s[2] = '';

                                                                       * sdsupdatelen(s);
                                                                      * printf("%d ", sdslen(s));


    void sdsclear(sds s);                                     //将字符串的buf设置为''


    int sdscmp(const sds s1, const sds s2);        //使用memcpy()比较两个字符串,如果s1>s2则结果为1,s1=s2则结果为0,s1<s2则为-1


    sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);//使用sep分隔符分割s,返回字符串数组


    void sdsfreesplitres(sds *tokens, int count); //tokens为null时不执行任何操作,否则清空sdssplitlen()函数返回的结果。


    void sdstolower(sds s);                             //将字符串的每个字符转换为小写形式


    void sdstoupper(sds s);                           //将字符串的每个字符转换为大写形式


    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); 

                            /* Modify the string substituting all the occurrences of the set of
                            * characters specified in the 'from' string to the corresponding character in the 'to' array.
                            * For instance: sdsmapchars(mystring, "ho", "01", 2)
                            * will have the effect of turning the string "hello" into "0ell1".


    sds sdsMakeRoomFor(sds s, size_t addlen);

                               * Enlarge the free space at the end of the sds string so that the caller

             * is sure that after calling this function can overwrite up to addlen
             * bytes after the end of the string, plus one more byte for nul term.


    void sdsIncrLen(sds s, int incr);                //根据incr来在字符串的尾部增加字符串长度或者减少剩余字符串空间
    sds sdsRemoveFreeSpace(sds s);            //当字符串没有剩余空间时,重新分配字符串。
    size_t sdsAllocSize(sds s);                      //

  • 相关阅读:
    html+css实现简易下拉菜单
    Win10 设置外网多用户远程桌面连接
    ubuntu 14.04 下svn + apache2 配置
    JavaScript 学习笔记(一)
    生成Log文件的写法
    运行执行sql文件脚本的例子
    css实现文本框和下拉框结合的案例
    angularjs 1 开发简单案例(包含common.js,service.js,controller.js,page)
    将字符串转成只有首字母是大写
    java之springboot的spring-boot-starter-aop的切面编程的使用(四)
  • 原文地址:https://www.cnblogs.com/davidwang456/p/3479509.html
Copyright © 2020-2023  润新知