/* Create a new sds string with the content specified by the 'init' pointer * and 'initlen'. * If NULL is used for 'init' the string is initialized with zero bytes. * If SDS_NOINIT is used, the buffer is left uninitialized; * * The string is always null-termined (all the sds strings are, always) so * even if you create an sds string with: * * mystring = sdsnewlen("abc",3); * * You can print the string with printf() as there is an implicit \0 at the * end of the string. However the string is binary safe and can contain * \0 characters in the middle, as the length is stored in the sds header. */ sds sdsnewlen(constvoid *init, size_t initlen){ void *sh; sds s; //根据长度选择合适的数据结构sdshdr char type = sdsReqType(initlen); /* Empty strings are usually created in order to append. Use type 8 * since type 5 is not good at this. */ if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8; //对应数据结构体sdshdr的大小 int hdrlen = sdsHdrSize(type); unsignedchar *fp; /* flags pointer. */
/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the * end of the specified sds string 's'. * * After the call, the passed sds string is no longer valid and all the * references must be substituted with the new pointer returned by the call. */ sds sdscatlen(sds s, constvoid *t, size_t len){ size_t curlen = sdslen(s);
s = sdsMakeRoomFor(s,len); if (s == NULL) returnNULL; memcpy(s+curlen, t, len); sdssetlen(s, curlen+len); s[curlen+len] = '\0'; return s; }
/* 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 sdsMakeRoomFor(sds s, size_t addlen){ void *sh, *newsh; size_t avail = sdsavail(s); size_t len, newlen; //[-1]在c语言是允许的,c++尽量不要这么来,参考https://www.zhihu.com/question/34790951 //s[-1]是flag的地址 char type, oldtype = s[-1] & SDS_TYPE_MASK; int hdrlen;
/* Return ASAP if there is enough space left. */ if (avail >= addlen) return s;
//len是字符串的长度 len = sdslen(s); //sh结构体的地址 sh = (char*)s-sdsHdrSize(oldtype); newlen = (len+addlen); if (newlen < SDS_MAX_PREALLOC) newlen *= 2; else newlen += SDS_MAX_PREALLOC;
//重新计算新的长度需要的结构体类型 type = sdsReqType(newlen);
/* Don't use type 5: the user is appending to the string and type 5 is * not able to remember empty space, so sdsMakeRoomFor() must be called * at every appending operation. */ if (type == SDS_TYPE_5) type = SDS_TYPE_8;
hdrlen = sdsHdrSize(type); if (oldtype==type) { //结构体类型不变的,直接realloc newsh = s_realloc(sh, hdrlen+newlen+1); if (newsh == NULL) returnNULL; s = (char*)newsh+hdrlen; } else { /* Since the header size changes, need to move the string forward, * and can't use realloc */ //结构体类型变化的,申请新的空间,拷贝老的过来,释放来的空间 newsh = s_malloc(hdrlen+newlen+1); if (newsh == NULL) returnNULL; memcpy((char*)newsh+hdrlen, s, len+1); s_free(sh); s = (char*)newsh+hdrlen; s[-1] = type; sdssetlen(s, len); } sdssetalloc(s, newlen); return s; }