深入redis内部--实现字符串
redis字符串的定義和實(shí)現(xiàn)在Ssd.h和Ssd.c中。
1.定義
typedef char *sds; //本質(zhì)是字符char的指針
2.字符串的操作
sds sdsnew(const char *init) {
??? size_t initlen = (init == NULL) ? 0 : strlen(init);
??? return sdsnewlen(init, initlen);
}
調(diào)用sdsnewlen,看一下該函數(shù)的實(shí)現(xiàn)
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] = '\0';
??? return (char*)sh->buf;
}
該函數(shù)使用redis自定義函數(shù)的zmalloc或者zcalloc分配內(nèi)存(以后章節(jié)會(huì)專門深入這些函數(shù))。
3.創(chuàng)建字符串使用了另一個(gè)結(jié)構(gòu)(紅色標(biāo)注)
struct sdshdr {
??? int len;
??? int free;
??? char buf[];
};
從上面的函數(shù)可以得出創(chuàng)建字符串時(shí),返回的是一個(gè)字符數(shù)組的指針。
該結(jié)構(gòu)和字符串的關(guān)系如下:
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);????? //實(shí)際真正創(chuàng)建字符串的函數(shù),使用sdsnew創(chuàng)建字符串時(shí)該函數(shù)被調(diào)用。
sds sdsnew(const char *init);???????????????????????????? //創(chuàng)建字符串函數(shù)
sds sdsempty(void);? ? ? ? ? ? ? ? ? ? ? ? ? ????????????? //創(chuàng)建一個(gè)長(zhǎng)度為0的空字符串
size_t sdslen(const sds s);????????????????????????????? //計(jì)算字符串的長(zhǎng)度
?
sds sdsdup(const sds s);??????????????????????????????? //復(fù)制字符串
void sdsfree(sds s);??????????????????????????????????????? //從內(nèi)存中釋放字符串,調(diào)用zfree方法
size_t sdsavail(const sds s); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //計(jì)算字符串的可用長(zhǎng)度(字符數(shù)組中還沒(méi)有使用的長(zhǎng)度)
sds sdsgrowzero(sds s, size_t len); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//增加字符串的內(nèi)存,并使用'\0'填充
sds sdscatlen(sds s, const void *t, size_t len); ? ? ? ? ? ? ?//字符串拼接常量實(shí)現(xiàn)函數(shù),使用sdscat時(shí)調(diào)用該函數(shù)
sds sdscat(sds s, const char *t); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//字符串拼接常量函數(shù)
????????????????
sds sdscatsds(sds s, const sds t); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//字符串拼接字符串函數(shù)
sds sdscpylen(sds s, const char *t, size_t len); ? ? ? ? ? ? ?//字符串復(fù)制的執(zhí)行函數(shù)
sds sdscpy(sds s, const char *t); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //將字符串t復(fù)制到s中,若s空間不足,使用sdsgrowzero增加空間
sds sdscatvprintf(sds s, const char *fmt, va_list ap); ? ?//類似sdscatprintf,但參數(shù)不是變長(zhǎng)的,是固定的
#ifdef __GNUC__ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //如果是linux平臺(tái),使用GNU編譯器
sds sdscatprintf(sds s, const char *fmt, ...)
??? __attribute__((format(printf, 2, 3))); ? ? ? ? ? ? ? ? ? ? ?//format (archetype, string-index, first-to-check) 告訴編譯器,按照printf, scanf, strftime
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//或strfmon的參數(shù)表格式規(guī)則對(duì)該函數(shù)的參數(shù)進(jìn)行檢查?!癮rchetype”指定是哪種風(fēng)格;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//“string-index”指定傳 入函數(shù)的第幾個(gè)參數(shù)是格式化字符串;“first-to-check”
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //指定從函數(shù)的第幾個(gè)參數(shù)開始按上述規(guī)則進(jìn)行檢查。
#else
sds sdscatprintf(sds s, const char *fmt, ...); ? ? ? ? ? ?//向參數(shù)s添加字符串,實(shí)例: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\n", s);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * Output will be just "Hello World".
sds sdsrange(sds s, int start, int end);?????????? //從字符串s中截取制定索引位置的子字符串。
void sdsupdatelen(sds s);??????????????????????????? //更新字符串的長(zhǎng)度。應(yīng)用實(shí)例: 如果沒(méi)有sdsupdatelen,則結(jié)果為2,有則結(jié)果為6
?????????????????????????????????????????????????????????????????? * s = sdsnew("foobar");
?????????????????????????????????????????????????????????????????? * s[2] = '\0';
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? * sdsupdatelen(s);
????????????????????????????????????????????????????????????????? * printf("%d\n", sdslen(s));
void sdsclear(sds s);???????????????????????????????????? //將字符串的buf設(shè)置為'\0'
int sdscmp(const sds s1, const sds s2);??????? //使用memcpy()比較兩個(gè)字符串,如果s1>s2則結(jié)果為1,s1=s2則結(jié)果為0,s1<s2則為-1
sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);//使用sep分隔符分割s,返回字符串?dāng)?shù)組
void sdsfreesplitres(sds *tokens, int count); //tokens為null時(shí)不執(zhí)行任何操作,否則清空sdssplitlen()函數(shù)返回的結(jié)果。
void sdstolower(sds s); ? ? ? ? ? ? ? ? ? ? ? ? ? ? //將字符串的每個(gè)字符轉(zhuǎn)換為小寫形式
void sdstoupper(sds s); ? ? ? ? ? ? ? ? ? ? ? ? ? //將字符串的每個(gè)字符轉(zhuǎn)換為大寫形式
sds sdsfromlonglong(long long value); ? ? ? ? ? ? ? ? ?//當(dāng)數(shù)字太大的時(shí)候,直接將數(shù)字轉(zhuǎn)化為字符串.
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); ? ? ? ? ? ? ? ?//根據(jù)incr來(lái)在字符串的尾部增加字符串長(zhǎng)度或者減少剩余字符串空間
sds sdsRemoveFreeSpace(sds s); ? ? ? ? ? ?//當(dāng)字符串沒(méi)有剩余空間時(shí),重新分配字符串。
size_t sdsAllocSize(sds s); ? ? ? ? ? ? ? ? ? ? ?//
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/3479509.html
總結(jié)
以上是生活随笔為你收集整理的深入redis内部--实现字符串的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深入redis内部--实现双向链表
- 下一篇: 深入redis内部--字典实现