字符串
typedef char *sds;
struct sdshdr {
unsigned int len; //記錄已經使用字節數
unsigned int free; //記錄未使用字節數
char buf[]; //字節數組
};
sds組織如下:
下面基於sdshdr 結構,分析下一些sds api 調用:
//新分配一個sds結構,同時buf指向的地址是連續的
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); //cpy
sh->buf[initlen] = '\0'; //設置最後一個字節爲’\0’
return (char*)sh->buf;
}
sdsempty、sdsnew、sdsdup都是基於sdsnewlen
//更新長度
void sdsupdatelen(sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); //獲取頭部
int reallen = strlen(s); //獲取長度
sh->free += (sh->len-reallen); //更新free
sh->len = reallen; //更新len
}
//申請空間,如果free 還足夠,直接返回,如果不夠,新申請
sds sdsMakeRoomFor(sds s, size_t addlen) {
struct sdshdr *sh, *newsh;
size_t free = sdsavail(s);
size_t len, newlen;
if (free >= addlen) return s;
len = sdslen(s);
sh = (void*) (s-(sizeof(struct sdshdr)));
newlen = (len+addlen);
//新申請空間小於1M,以新長度的2倍爲增長,超過1M,每次增長1M
if (newlen < SDS_MAX_PREALLOC)
newlen *= 2;
else
newlen += SDS_MAX_PREALLOC;
newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
if (newsh == NULL) return NULL;
newsh->free = newlen - len;
return newsh->buf;
}
//刪除free空間
sds sdsRemoveFreeSpace(sds s) {
struct sdshdr *sh;
sh = (void*) (s-(sizeof(struct sdshdr)));
sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);
sh->free = 0;
return sh->buf;
}