redis源码分析(2)字符串sds.c

 

sds是一个char*的类型别名


 

可以把这个结构体和对应操作函数类比为C++中STL的string类。


 

 

 因此可知,如果传入buf的地址s,该结构体的地址就是s-sizeof(struct sdshdr);

这两个函数比较好理解,当传入的sds类型而非普通字符数组时,求sds的现有长度和sds的可用长度。

有了len这个变量以后,获取字符串长度的时间复杂度为O(1),而C字符串获取字符串长度的时间复杂度为O(N)。


 

 

sdsnewlen 给定一个字符串init和字符串长度initlen,创建一个新的没有预留空间的sds。

如果init指针是有效值的话,就将init的内容复制到buf中去,如果没有的话,全部初始化为0.

可以看到,与字符数组一样,会预留1长度用来存放'\0'。

这样做的好处是在某些情况下可以重用C字符串函数库中的一些函数。比如,可以直接使用printf("%s",sds->buf);而无需重新位sdshdr编写打印函数。

注意,返回的是buf的地址。


 

 

 sdsempty调用sdsnewlen创建一个空字符串。

 

 

 

 但是我觉得return sdsnewlen(NULL,0)这种写法可能更好,从上面的图中可以看到,为“”字符串额外提供了空间,不过相差不大,可以看到相同的字符串常量地址是一样的。


 

 

 sdsnew()复制一个以'\0'结尾的C风格字符串

 

 sdsup与sdsnew类似,但是参数是一个sds类型。


 

 

 释放函数。


 

 在不释放sds的情况下重置,改变了len和free,相当于‘\0’后的数据全都无效了。


/* 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.
 * 
 * Note: this does not change the *length* of the sds string as returned
 * by sdslen(), but only the free buffer space we have. */
/*
 * 对 sds 中 buf 的长度进行扩展,确保在函数执行之后,
 * buf 至少会有 addlen + 1 长度的空余空间
 * (额外的 1 字节是为 \0 准备的)
 *
 * 返回值
 *  sds :扩展成功返回扩展后的 sds
 *        扩展失败返回 NULL
 *
 * 复杂度
 *  T = O(N)
 */
sds sdsMakeRoomFor(sds s, size_t addlen) {
    struct sdshdr *sh, *newsh;
    // 获取 s 目前的空余空间长度
    size_t free = sdsavail(s);
    size_t len, newlen;
    // s 目前的空余空间已经足够,无须再进行扩展,直接返回
    if (free >= addlen) return s;
    // 获取 s 目前已占用空间的长度
    len = sdslen(s);
    sh = (void*) (s-(sizeof(struct sdshdr)));

    // s 最少需要的长度
    newlen = (len+addlen);

    // 根据新长度,为 s 分配新空间所需的大小
    if (newlen < SDS_MAX_PREALLOC)
        // 如果新长度小于 SDS_MAX_PREALLOC 
        // 那么为它分配两倍于所需长度的空间
        newlen *= 2;
    else
        // 否则,分配长度为目前长度加上 SDS_MAX_PREALLOC
        newlen += SDS_MAX_PREALLOC;
    // T = O(N)
    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);

    // 内存不足,分配失败,返回
    if (newsh == NULL) return NULL;

    // 更新 sds 的空余长度
    newsh->free = newlen - len;

    // 返回 sds
    return newsh->buf;
}

 

posted on 2019-08-22 17:11  长岛的雪  阅读(282)  评论(0编辑  收藏  举报