sds.h

  1. /**
  2. * redis 动态字符串
  3. */
  4. #ifndef __SDS_H
  5. #define __SDS_H
  6. #define SDS_MAX_PREALLOC (1024*1024)
  7. extern const char *SDS_NOINIT;
  8. #include <sys/types.h>
  9. #include <stdarg.h>
  10. #include <stdint.h>
  11. /**
  12. * sds 类型是 char * 的别名
  13. */
  14. typedef char *sds;
  15. /* Note: sdshdr5 is never used, we just access the flags byte directly.
  16. * However is here to document the layout of type 5 SDS strings. */
  17. // 根据存储的内容选择不同数据结构,以节省内存
  18. // 这里的 '__attribute__ ((__packed__))' 要求编译器取消内存对齐优化,按照实际的占用字节数进行对齐
  19. // string_size < 32
  20. struct __attribute__ ((__packed__)) sdshdr5 {
  21. /**
  22. * 前 5 位保存字符串长度,后 3 位保存类型值
  23. */
  24. unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
  25. //实际保存字符串数据的地方以及末尾的一个 \0
  26. char buf[];
  27. };
  28. // 32 <= string_size < 256
  29. struct __attribute__ ((__packed__)) sdshdr8 {
  30. /* 记录当前 buf 的长度(不包含 '\0') */
  31. uint8_t len; /* used */
  32. /* 记录当前 buf 总共分配的内存大小(不包含 '\0') */
  33. uint8_t alloc; /* excluding the header and null terminator */
  34. /* 记录当前 buf 的属性,用来标识到底是 sdshdr8 还是 sdshdr16 等 */
  35. unsigned char flags;
  36. // 实际保存字符串数据的地方以及末尾的一个 \0
  37. char buf[];
  38. };
  39. // 256 <= string_size < 65536(64K)
  40. struct __attribute__ ((__packed__)) sdshdr16 {
  41. // 记录当前 buf 的长度(不包含 '\0')
  42. uint16_t len; /* used */
  43. // 记录当前 buf 总共分配的内存大小(不包含 '\0'
  44. uint16_t alloc; /* excluding the header and null terminator */
  45. //记录当前 buf 的属性,用来标识到底是 sdshdr8 还是 sdshdr16 等
  46. unsigned char flags; /* 3 lsb of type, 5 unused bits */
  47. // 实际保存字符串数据的地方以及末尾的一个 \0
  48. char buf[];
  49. };
  50. // 65536(64K) <= string_size < 4GB
  51. struct __attribute__ ((__packed__)) sdshdr32 {
  52. //记录当前 buf 的长度(不包含 '\0')
  53. uint32_t len; /* used */
  54. //记录当前 buf 总共分配的内存大小(不包含 '\0')
  55. uint32_t alloc; /* excluding the header and null terminator */
  56. //记录当前 buf 的属性等
  57. unsigned char flags; /* 3 lsb of type, 5 unused bits */
  58. // 实际保存字符串数据的地方以及末尾的一个 \0
  59. char buf[];
  60. };
  61. // 4G <= string_size
  62. struct __attribute__ ((__packed__)) sdshdr64 {
  63. //记录当前 buf 的长度(不包含 '\0')
  64. uint64_t len; /* used */
  65. //记录当前 buf 总共分配的内存大小(不包含 '\0')
  66. uint64_t alloc; /* excluding the header and null terminator */
  67. //记录当前 buf 的属性等
  68. unsigned char flags; /* 3 lsb of type, 5 unused bits */
  69. // 实际保存字符串数据的地方以及末尾的一个 \0
  70. char buf[];
  71. };
  72. // flags 值的定义
  73. #define SDS_TYPE_5 0
  74. #define SDS_TYPE_8 1
  75. #define SDS_TYPE_16 2
  76. #define SDS_TYPE_32 3
  77. #define SDS_TYPE_64 4
  78. // 掩码,flags & SDS_TYPE_MASK 即可获得具体的 flags 值
  79. #define SDS_TYPE_MASK 7
  80. #define SDS_TYPE_BITS 3
  81. // 这里的 s 是一个 sds
  82. // 可以通过 sds 的头指针进行寻址,拿到整个 struct 的指针
  83. // buf[-1]的值是flags的值 存的值再内存中是连续的 (len alloc flags buf)
  84. #define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));
  85. #define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
  86. #define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
  87. //判断字符串长度 inline内联
  88. static inline size_t sdslen(const sds s) {
  89. // 通过 buf 的 -1 下标获取 flags 的值
  90. unsigned char flags = s[-1];
  91. //SDS_TYPE_MASK = 7 flags&SDS_TYPE_MASK运算获取flags具体的值
  92. switch(flags&SDS_TYPE_MASK) {
  93. case SDS_TYPE_5:
  94. //flags的值 flags >> 3
  95. return SDS_TYPE_5_LEN(flags);
  96. case SDS_TYPE_8:
  97. //SDS_HDR(8,s) == ((struct sdshdr8 *)((s)-(sizeof(struct sdshdrT8)))->len sdshdr8的len方法
  98. return SDS_HDR(8,s)->len;
  99. case SDS_TYPE_16:
  100. return SDS_HDR(16,s)->len;
  101. case SDS_TYPE_32:
  102. return SDS_HDR(32,s)->len;
  103. case SDS_TYPE_64:
  104. return SDS_HDR(64,s)->len;
  105. }
  106. return 0;
  107. }
  108. //sds可用内存大小
  109. static inline size_t sdsavail(const sds s) {
  110. //s[-1]的值是flags的值, 要求编译器取消内存对齐优化,按照实际的占用字节数进行对齐,buf的前面是flags
  111. unsigned char flags = s[-1];
  112. //flags&SDS_TYPE_MASK运算获取flags具体的值
  113. switch(flags&SDS_TYPE_MASK) {
  114. case SDS_TYPE_5: {
  115. return 0;
  116. }
  117. //sh->alloc - sh->len; 分配内存大小减去字符串长度
  118. case SDS_TYPE_8: {
  119. SDS_HDR_VAR(8,s);
  120. return sh->alloc - sh->len;
  121. }
  122. case SDS_TYPE_16: {
  123. SDS_HDR_VAR(16,s);
  124. return sh->alloc - sh->len;
  125. }
  126. case SDS_TYPE_32: {
  127. SDS_HDR_VAR(32,s);
  128. return sh->alloc - sh->len;
  129. }
  130. case SDS_TYPE_64: {
  131. SDS_HDR_VAR(64,s);
  132. return sh->alloc - sh->len;
  133. }
  134. }
  135. return 0;
  136. }
  137. //给sds设置新的长度
  138. static inline void sdssetlen(sds s, size_t newlen) {
  139. //获取flags的值
  140. unsigned char flags = s[-1];
  141. switch(flags&SDS_TYPE_MASK) {
  142. case SDS_TYPE_5:
  143. {
  144. unsigned char *fp = ((unsigned char*)s)-1;
  145. /**
  146. * 位或| 二进制中只要有一个为1 就位1 10010 | 01100 = 11110
  147. * 左移 << newlen << 3 = newlen * 2^3 = newlen * 8
  148. */
  149. //0 | newlen * 8 = newlen * 8
  150. *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
  151. }
  152. break;
  153. case SDS_TYPE_8:
  154. SDS_HDR(8,s)->len = newlen;
  155. break;
  156. case SDS_TYPE_16:
  157. SDS_HDR(16,s)->len = newlen;
  158. break;
  159. case SDS_TYPE_32:
  160. SDS_HDR(32,s)->len = newlen;
  161. break;
  162. case SDS_TYPE_64:
  163. SDS_HDR(64,s)->len = newlen;
  164. break;
  165. }
  166. }
  167. /**
  168. * 增加sds字符串长度
  169. * @param s 字符串
  170. * @param inc 新的长度
  171. */
  172. static inline void sdsinclen(sds s, size_t inc) {
  173. unsigned char flags = s[-1];
  174. switch(flags&SDS_TYPE_MASK) {
  175. case SDS_TYPE_5:
  176. {
  177. unsigned char *fp = ((unsigned char*)s)-1;
  178. unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;
  179. *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
  180. }
  181. break;
  182. case SDS_TYPE_8:
  183. SDS_HDR(8,s)->len += inc;
  184. break;
  185. case SDS_TYPE_16:
  186. SDS_HDR(16,s)->len += inc;
  187. break;
  188. case SDS_TYPE_32:
  189. SDS_HDR(32,s)->len += inc;
  190. break;
  191. case SDS_TYPE_64:
  192. SDS_HDR(64,s)->len += inc;
  193. break;
  194. }
  195. }
  196. /**
  197. * sds 分配的大小 = sds可用大小 + sds长度
  198. * @param s 字符串
  199. * @return
  200. */
  201. /* sdsalloc() = sdsavail() + sdslen() */
  202. static inline size_t sdsalloc(const sds s) {
  203. unsigned char flags = s[-1];
  204. switch(flags&SDS_TYPE_MASK) {
  205. case SDS_TYPE_5:
  206. //flags >> 3 = flags / 8
  207. return SDS_TYPE_5_LEN(flags);
  208. case SDS_TYPE_8:
  209. return SDS_HDR(8,s)->alloc;
  210. case SDS_TYPE_16:
  211. return SDS_HDR(16,s)->alloc;
  212. case SDS_TYPE_32:
  213. return SDS_HDR(32,s)->alloc;
  214. case SDS_TYPE_64:
  215. return SDS_HDR(64,s)->alloc;
  216. }
  217. return 0;
  218. }
  219. /**
  220. * 设置字符串可用内存为新分配的内存
  221. * @param s 字符串
  222. * @param newlen 新的长度
  223. */
  224. static inline void sdssetalloc(sds s, size_t newlen) {
  225. unsigned char flags = s[-1];
  226. //选择那种字符串类型
  227. switch(flags&SDS_TYPE_MASK) {
  228. case SDS_TYPE_5:
  229. /* Nothing to do, this type has no total allocation info. */
  230. break;
  231. case SDS_TYPE_8:
  232. //设置字符串buf内存 sds->alloc = newlen
  233. SDS_HDR(8,s)->alloc = newlen;
  234. break;
  235. case SDS_TYPE_16:
  236. SDS_HDR(16,s)->alloc = newlen;
  237. break;
  238. case SDS_TYPE_32:
  239. SDS_HDR(32,s)->alloc = newlen;
  240. break;
  241. case SDS_TYPE_64:
  242. SDS_HDR(64,s)->alloc = newlen;
  243. break;
  244. }
  245. }
  246. //创建一个initlen长度的sds字符串,如果创建不成功会返回异常
  247. sds sdsnewlen(const void *init, size_t initlen);
  248. //尝试创建initlen长度的sds字符串,创建不成功返回NULL
  249. sds sdstrynewlen(const void *init, size_t initlen);
  250. //给字符串init创建一个sdh
  251. sds sdsnew(const char *init);
  252. //创建一个空字符串
  253. sds sdsempty(void);
  254. //复制字符串
  255. sds sdsdup(const sds s);
  256. //释放字符串
  257. void sdsfree(sds s);
  258. //扩展sds字符串长度
  259. sds sdsgrowzero(sds s, size_t len);
  260. //sds连接固定长度len的char字符串
  261. sds sdscatlen(sds s, const void *t, size_t len);
  262. //sds连接char字符串,模仿strcat
  263. sds sdscat(sds s, const char *t);
  264. //sds连接sds字符串,模仿strcat
  265. sds sdscatsds(sds s, const sds t);
  266. //sds拷贝固定长度len的char字符串
  267. sds sdscpylen(sds s, const char *t, size_t len);
  268. //sds拷贝char字符串
  269. sds sdscpy(sds s, const char *t);
  270. //sds连接格式化字符串,采用C实现格式功能
  271. sds sdscatvprintf(sds s, const char *fmt, va_list ap);
  272. #ifdef __GNUC__
  273. sds sdscatprintf(sds s, const char *fmt, ...)
  274. __attribute__((format(printf, 2, 3)));
  275. #else
  276. sds sdscatprintf(sds s, const char *fmt, ...);
  277. #endif
  278. //sds连接格式化字符串,自定义格式化功能
  279. sds sdscatfmt(sds s, char const *fmt, ...);
  280. // 前后去掉字符 cset
  281. sds sdstrim(sds s, const char *cset);
  282. void sdssubstr(sds s, size_t start, size_t len);
  283. //截断字符串
  284. void sdsrange(sds s, ssize_t start, ssize_t end);
  285. //更新字符串长度
  286. void sdsupdatelen(sds s);
  287. //清空sds字符串
  288. void sdsclear(sds s);
  289. //比较两个sds字符串
  290. int sdscmp(const sds s1, const sds s2);
  291. //sds分割函数 对于strsplit
  292. sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count);
  293. //释放分割出来的sds
  294. void sdsfreesplitres(sds *tokens, int count);
  295. //sds转小写
  296. void sdstolower(sds s);
  297. //sds转大写
  298. void sdstoupper(sds s);
  299. //longlong类型转化为sds字符串
  300. sds sdsfromlonglong(long long value);
  301. //sds添加转义字符字符串
  302. sds sdscatrepr(sds s, const char *p, size_t len);
  303. //sds根据转义字符分割,必须用sdsfreesplitres().
  304. sds *sdssplitargs(const char *line, int *argc);
  305. sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
  306. //字符串连接后,转化为sds
  307. sds sdsjoin(char **argv, int argc, char *sep);
  308. //sds 连接sds
  309. sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
  310. /* Callback for sdstemplate. The function gets called by sdstemplate
  311. * every time a variable needs to be expanded. The variable name is
  312. * provided as variable, and the callback is expected to return a
  313. * substitution value. Returning a NULL indicates an error.
  314. */
  315. typedef sds (*sdstemplate_callback_t)(const sds variable, void *arg);
  316. //sds回调模板函数
  317. sds sdstemplate(const char *template, sdstemplate_callback_t cb_func, void *cb_arg);
  318. // sds扩展函数 sds的扩容
  319. /* Low level functions exposed to the user API */
  320. sds sdsMakeRoomFor(sds s, size_t addlen);
  321. //配合sdsMakeRoomFor使用,重置sds长度
  322. void sdsIncrLen(sds s, ssize_t incr);
  323. //sds释放空闲空间
  324. sds sdsRemoveFreeSpace(sds s);
  325. //计算sds开辟空间的大小
  326. size_t sdsAllocSize(sds s);
  327. //返回buf缓冲指针
  328. void *sdsAllocPtr(sds s);
  329. /* Export the allocator used by SDS to the program using SDS.
  330. * Sometimes the program SDS is linked to, may use a different set of
  331. * allocators, but may want to allocate or free things that SDS will
  332. * respectively free or allocate. */
  333. //开辟size大小的空间
  334. void *sds_malloc(size_t size);
  335. //如果size> ptr.length 重新开辟size大小的空间
  336. void *sds_realloc(void *ptr, size_t size);
  337. //释放指针空间
  338. void sds_free(void *ptr);
  339. #ifdef REDIS_TEST
  340. int sdsTest(int argc, char *argv[], int accurate);
  341. #endif
  342. #endif

sds.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <assert.h>
  6. #include <limits.h>
  7. #include "sds.h"
  8. #include "sdsalloc.h"
  9. /**
  10. * 常量
  11. */
  12. const char *SDS_NOINIT = "SDS_NOINIT";
  13. /**
  14. * 获取sds类型结构占用的内存大小
  15. * @param type sds的类型
  16. * @return 内存大小
  17. */
  18. static inline int sdsHdrSize(char type) {
  19. switch(type&SDS_TYPE_MASK) {
  20. case SDS_TYPE_5:
  21. return sizeof(struct sdshdr5);
  22. case SDS_TYPE_8:
  23. return sizeof(struct sdshdr8);
  24. case SDS_TYPE_16:
  25. return sizeof(struct sdshdr16);
  26. case SDS_TYPE_32:
  27. return sizeof(struct sdshdr32);
  28. case SDS_TYPE_64:
  29. return sizeof(struct sdshdr64);
  30. }
  31. return 0;
  32. }
  33. /**
  34. * 通过sds字符串长度获取所需要的sds类型
  35. * @param string_size 字符串长度
  36. * @return 字符串类型
  37. */
  38. static inline char sdsReqType(size_t string_size) {
  39. //string_size < 2^5 = string_size < 32
  40. if (string_size < 1<<5)
  41. return SDS_TYPE_5;
  42. // 32 <= string_size < 256
  43. if (string_size < 1<<8)
  44. return SDS_TYPE_8;
  45. // 256 <= string_size < 65536(64K)
  46. if (string_size < 1<<16)
  47. return SDS_TYPE_16;
  48. // LONG_MAX == LLONG_MAX = 8 代表64位系统
  49. #if (LONG_MAX == LLONG_MAX)
  50. // 65536(64K) <= string_size < 4GB
  51. if (string_size < 1ll<<32)
  52. return SDS_TYPE_32;
  53. // 4G <= string_size
  54. return SDS_TYPE_64;
  55. #else
  56. //32位系统
  57. return SDS_TYPE_32;
  58. #endif
  59. }
  60. /**
  61. * 获取sds字符串在该类型中的允许的最大长度
  62. * @param type 类型
  63. * @return 长度
  64. */
  65. static inline size_t sdsTypeMaxSize(char type) {
  66. if (type == SDS_TYPE_5)
  67. return (1<<5) - 1;
  68. if (type == SDS_TYPE_8)
  69. return (1<<8) - 1;
  70. if (type == SDS_TYPE_16)
  71. return (1<<16) - 1;
  72. #if (LONG_MAX == LLONG_MAX)
  73. //预编译命令 代表64位系统
  74. if (type == SDS_TYPE_32)
  75. return (1ll<<32) - 1;
  76. #endif
  77. //-1 相当于最大的 SDS_TYPE_64 或者 SDS_TYPE_32
  78. return -1; /* this is equivalent to the max SDS_TYPE_64 or SDS_TYPE_32 */
  79. }
  80. /* Create a new sds string with the content specified by the 'init' pointer
  81. * and 'initlen'.
  82. * If NULL is used for 'init' the string is initialized with zero bytes.
  83. * If SDS_NOINIT is used, the buffer is left uninitialized;
  84. *
  85. * The string is always null-termined (all the sds strings are, always) so
  86. * even if you create an sds string with:
  87. *
  88. * mystring = sdsnewlen("abc",3);
  89. *
  90. * You can print the string with printf() as there is an implicit \0 at the
  91. * end of the string. However the string is binary safe and can contain
  92. * \0 characters in the middle, as the length is stored in the sds header. */
  93. /**
  94. * 用于创建sds字符串
  95. * const void *init 代表任何类型的值
  96. * @param init init指针 init 代表任何类型的值,值为常量,无法修改其值,但是可以其使指针指向其他对象
  97. * @param initlen 字符串长度
  98. * @param trymalloc 分配的buf大小
  99. * @return sds字符串
  100. */
  101. sds _sdsnewlen(const void *init, size_t initlen, int trymalloc) {
  102. void *sh;
  103. sds s;
  104. //通过sds字符串长度获取sds类型
  105. char type = sdsReqType(initlen);
  106. /* Empty strings are usually created in order to append. Use type 8
  107. * since type 5 is not good at this. */
  108. // 如果类型SDS_TYPE_5 并且长度位0 则类型设置为 SDS_TYPE_8 ,空的字符串通常使用类型SDS_TYPE_8,以便于追加字符,
  109. if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
  110. //sds 的类型占用的内存的大小
  111. int hdrlen = sdsHdrSize(type);
  112. //定义flags标识 标识sds的buf属性
  113. unsigned char *fp; /* flags pointer. */
  114. size_t usable;
  115. //断言 字符串长度 + 类型占用的长度 + 1 > 字符串长度
  116. assert(initlen + hdrlen + 1 > initlen); /* Catch size_t overflow */
  117. // 分配内存的大小 sh如果为NULL则分配失败 否则usable为分配的可用内存大小
  118. sh = trymalloc?
  119. s_trymalloc_usable(hdrlen+initlen+1, &usable) :
  120. s_malloc_usable(hdrlen+initlen+1, &usable);
  121. //如果分配内存失败则返回 NULL
  122. if (sh == NULL) return NULL;
  123. // 如果init==SDS_NOINIT(这里判断地址是否相同),设置init为NULL
  124. if (init==SDS_NOINIT)
  125. init = NULL;
  126. else if (!init)
  127. // 清空内存内容
  128. memset(sh, 0, hdrlen+initlen+1);
  129. // c字符串
  130. s = (char*)sh+hdrlen;
  131. // 标志位(sdshdr_xx中flags)
  132. fp = ((unsigned char*)s)-1;
  133. //字符串可用内存大小 = 分配的内存大小-sds结构大小-1
  134. usable = usable-hdrlen-1;
  135. //判断可用内存大小 是否大于该类型最大可用大小
  136. if (usable > sdsTypeMaxSize(type))
  137. //是的话分配该类型最大可用内存大小
  138. usable = sdsTypeMaxSize(type);
  139. // 根据得到的sds类型设置头部信息
  140. switch(type) {
  141. case SDS_TYPE_5: {
  142. *fp = type | (initlen << SDS_TYPE_BITS);
  143. break;
  144. }
  145. case SDS_TYPE_8: {
  146. SDS_HDR_VAR(8,s);
  147. sh->len = initlen;
  148. sh->alloc = usable;
  149. *fp = type;
  150. break;
  151. }
  152. case SDS_TYPE_16: {
  153. SDS_HDR_VAR(16,s);
  154. sh->len = initlen;
  155. sh->alloc = usable;
  156. *fp = type;
  157. break;
  158. }
  159. case SDS_TYPE_32: {
  160. SDS_HDR_VAR(32,s);
  161. sh->len = initlen;
  162. sh->alloc = usable;
  163. *fp = type;
  164. break;
  165. }
  166. case SDS_TYPE_64: {
  167. SDS_HDR_VAR(64,s);
  168. sh->len = initlen;
  169. sh->alloc = usable;
  170. *fp = type;
  171. break;
  172. }
  173. }
  174. // 拷贝字符串到sds字符串中
  175. if (initlen && init)
  176. memcpy(s, init, initlen);
  177. // 设置标准结束符
  178. s[initlen] = '\0';
  179. return s;
  180. }
  181. /**
  182. * 创建sds字符串 使用s_malloc_usable创建内存空间
  183. * @param init 任意类型的值 常量 值不可更改 但指针可以更改指向的对象
  184. * @param initlen
  185. * @return 字符串
  186. */
  187. sds sdsnewlen(const void *init, size_t initlen) {
  188. return _sdsnewlen(init, initlen, 0);
  189. }
  190. /**
  191. * 尝试创建sds,使用s_trymalloc_usable创建内存空间
  192. * @param init 任意类型的值
  193. * @param initlen
  194. * @return
  195. */
  196. sds sdstrynewlen(const void *init, size_t initlen) {
  197. return _sdsnewlen(init, initlen, 1);
  198. }
  199. /**
  200. * 创建0长度的字符串
  201. * @return sds字符串
  202. */
  203. /* Create an empty (zero length) sds string. Even in this case the string
  204. * always has an implicit null term. */
  205. sds sdsempty(void) {
  206. return sdsnewlen("",0);
  207. }
  208. /**
  209. * 从一个以null结尾的 C字符串 创建一个新的sds字符串
  210. * @param init
  211. * @return
  212. */
  213. /* Create a new sds string starting from a null terminated C string. */
  214. sds sdsnew(const char *init) {
  215. // 判断传入的字符串是否为NULL 如果为NULL为创建一个空的sds字符串,否则创建strlen(init)长度的sds字符串
  216. size_t initlen = (init == NULL) ? 0 : strlen(init);
  217. return sdsnewlen(init, initlen);
  218. }
  219. /**
  220. * 复制一个sds
  221. * @param s
  222. * @return
  223. */
  224. /* Duplicate an sds string. */
  225. sds sdsdup(const sds s) {
  226. return sdsnewlen(s, sdslen(s));
  227. }
  228. /**
  229. * 释放sds字符串
  230. * @param s sds字符串
  231. */
  232. /* Free an sds string. No operation is performed if 's' is NULL. */
  233. void sdsfree(sds s) {
  234. //如果sds字符串为NULL为不作操作
  235. if (s == NULL) return;
  236. //释放内存空间
  237. s_free((char*)s-sdsHdrSize(s[-1]));
  238. }
  239. /* Set the sds string length to the length as obtained with strlen(), so
  240. * considering as content only up to the first null term character.
  241. *
  242. * This function is useful when the sds string is hacked manually in some
  243. * way, like in the following example:
  244. *
  245. * s = sdsnew("foobar");
  246. * s[2] = '\0';
  247. * sdsupdatelen(s);
  248. * printf("%d\n", sdslen(s));
  249. *
  250. * The output will be "2", but if we comment out the call to sdsupdatelen()
  251. * the output will be "6" as the string was modified but the logical length
  252. * remains 6 bytes. */
  253. /**
  254. * 将sds的已经使用的长度修改成第一个'\0'结尾的字符串的长度,相当于从第一个\0截断
  255. *
  256. * 当修改给sds字符串中某一个字符为'\0' ,
  257. * 此时需要执行该方法去更新sds字符串长度,因为sds长度记录在sds头len中,如果不去更新,则sds长度不变,
  258. * 例子:
  259. * s = sdsnew("foobar");
  260. * s[2] = '\0';
  261. * dsupdatelen(s);
  262. * rintf("%d\n", sdslen(s));
  263. * 此时输出长度为2
  264. * 如果没有dsupdatelen(s); 则sds长度还是原来的6
  265. * @param s
  266. */
  267. void sdsupdatelen(sds s) {
  268. //获取sds长度即 到第一个'\0'的长度
  269. size_t reallen = strlen(s);
  270. // 给sds设置新的长度
  271. sdssetlen(s, reallen);
  272. }
  273. /* Modify an sds string in-place to make it empty (zero length).
  274. * However all the existing buffer is not discarded but set as free space
  275. * so that next append operations will not require allocations up to the
  276. * number of bytes previously available. */
  277. /**
  278. * 将sds的内存清零但不释放
  279. * 设置sds长度为0,并将第一个字符位置设置为结束符 '\0'
  280. * @param s
  281. */
  282. void sdsclear(sds s) {
  283. sdssetlen(s, 0);
  284. s[0] = '\0';
  285. }
  286. /* Enlarge the free space at the end of the sds string so that the caller
  287. * is sure that after calling this function can overwrite up to addlen
  288. * bytes after the end of the string, plus one more byte for nul term.
  289. *
  290. * Note: this does not change the *length* of the sds string as returned
  291. * by sdslen(), but only the free buffer space we have. */
  292. /**
  293. * 给一个sds扩充空间以供以后使用
  294. * 该方法用于添加sds字符串sds的alloc的小 即可用空间大小,不会改变字符串长度
  295. * @param s sds字符串
  296. * @param addlen 需要新增的大小
  297. * @return sds字符串
  298. */
  299. sds sdsMakeRoomFor(sds s, size_t addlen) {
  300. void *sh, *newsh;
  301. //获取sds当前可用空间
  302. size_t avail = sdsavail(s);
  303. size_t len, newlen, reqlen;
  304. //获取sds的类型 s[-1]= flags oldtype = flags & SDS_TYPE_MASK;
  305. char type, oldtype = s[-1] & SDS_TYPE_MASK;
  306. int hdrlen;
  307. size_t usable;
  308. //如果可用空间大于扩容大小 则无须扩容直接返回
  309. /* Return ASAP if there is enough space left. */
  310. if (avail >= addlen) return s;
  311. //判断字符串长度
  312. len = sdslen(s);
  313. //获取sds类型结构占用的内存大小
  314. sh = (char*)s-sdsHdrSize(oldtype);
  315. //新的内存大小等于 sds字符串长度+新增长度
  316. reqlen = newlen = (len+addlen);
  317. //断言 新增后的长度要大于 sds字符串长度
  318. assert(newlen > len); /* Catch size_t overflow */
  319. //如果新的长度小于 1M,则扩容为其2倍
  320. if (newlen < SDS_MAX_PREALLOC)
  321. newlen *= 2;
  322. //否则+1M
  323. else
  324. newlen += SDS_MAX_PREALLOC;
  325. //修改要扩容sds字符串的类型
  326. type = sdsReqType(newlen);
  327. /* Don't use type 5: the user is appending to the string and type 5 is
  328. * not able to remember empty space, so sdsMakeRoomFor() must be called
  329. * at every appending operation. */
  330. //如果类型是SDS_TYPE_5 的话将类型设置为 SDS_TYPE_8
  331. if (type == SDS_TYPE_5) type = SDS_TYPE_8;
  332. //获取新的类型的结构占用的空间大小
  333. hdrlen = sdsHdrSize(type);
  334. //断言 新的类型结构占用的空间 + 扩容后的长度+1 要大于 扩容前sds字符串长度+addlen新增长度
  335. assert(hdrlen + newlen + 1 > reqlen); /* Catch size_t overflow */
  336. if (oldtype==type) {
  337. //如果旧的类型和新的类型一致,则重新分配内存
  338. newsh = s_realloc_usable(sh, hdrlen+newlen+1, &usable);
  339. if (newsh == NULL) return NULL;
  340. s = (char*)newsh+hdrlen;
  341. } else {
  342. /* Since the header size changes, need to move the string forward,
  343. * and can't use realloc */
  344. //如果新类型和旧内存不一致则重新创建一个新的内存空间
  345. //分配内存 如果为NULL则内存分配失败 否则usable为可用内存大小
  346. newsh = s_malloc_usable(hdrlen+newlen+1, &usable);
  347. if (newsh == NULL) return NULL;
  348. //复制字符串
  349. memcpy((char*)newsh+hdrlen, s, len+1);
  350. //释放之前的sds字符串
  351. s_free(sh);
  352. s = (char*)newsh+hdrlen;
  353. //设置新标识
  354. s[-1] = type;
  355. //给sds设置新的长度
  356. sdssetlen(s, len);
  357. }
  358. //可用内存 = 分配的可用内存-sds类型结构内存-1
  359. usable = usable-hdrlen-1;
  360. //如果可用内存 > 类型最大的内存则重新设置sds类型
  361. if (usable > sdsTypeMaxSize(type))
  362. usable = sdsTypeMaxSize(type);
  363. //设置字符串可用内存为新分配的内存
  364. sdssetalloc(s, usable);
  365. return s;
  366. }
  367. /* Reallocate the sds string so that it has no free space at the end. The
  368. * contained string remains not altered, but next concatenation operations
  369. * will require a reallocation.
  370. *
  371. * After the call, the passed sds string is no longer valid and all the
  372. * references must be substituted with the new pointer returned by the call. */
  373. /**
  374. * 根据实际使用长度减少sds的分配内存 设置sds可用空间为0
  375. * 重新分配sds字符串内存空间,传入的s字符串将不可以,指针将指向新创建的sds字符串
  376. * @param s sds字符串
  377. * @return
  378. */
  379. sds sdsRemoveFreeSpace(sds s) {
  380. void *sh, *newsh;
  381. //s[-1] = flags sds类型
  382. char type, oldtype = s[-1] & SDS_TYPE_MASK;
  383. int hdrlen, oldhdrlen = sdsHdrSize(oldtype);
  384. //获取sds字符串长度
  385. size_t len = sdslen(s);
  386. //获取s的可用内存
  387. size_t avail = sdsavail(s);
  388. //sda的buf长度 = sds长度 - sds类型结构占用的内存空间大小
  389. sh = (char*)s-oldhdrlen;
  390. //如果可用空间已经为0,那么无须调整
  391. /* Return ASAP if there is no space left. */
  392. if (avail == 0) return s;
  393. /* Check what would be the minimum SDS header that is just good enough to
  394. * fit this string. */
  395. //获取该长度所需要的的sds类型
  396. type = sdsReqType(len);
  397. //获取sds类型结构占用的内存大小
  398. hdrlen = sdsHdrSize(type);
  399. /* If the type is the same, or at least a large enough type is still
  400. * required, we just realloc(), letting the allocator to do the copy
  401. * only if really needed. Otherwise if the change is huge, we manually
  402. * reallocate the string to use the different header type. */
  403. if (oldtype==type || type > SDS_TYPE_8) {
  404. //如果旧sds类型和 sds字符串最少需要的sds类型一致,重新分配内存并将之前sds内存释放
  405. newsh = s_realloc(sh, oldhdrlen+len+1);
  406. //如果分配失败则返回NULL
  407. if (newsh == NULL) return NULL;
  408. //c 字符串
  409. s = (char*)newsh+oldhdrlen;
  410. } else {
  411. //sds字符串最少需要空间的sds类型 和 原sds类型不一致 分配内存
  412. newsh = s_malloc(hdrlen+len+1);
  413. //如果为NULL则分配失败
  414. if (newsh == NULL) return NULL;
  415. //复制
  416. memcpy((char*)newsh+hdrlen, s, len+1);
  417. //释放原sds串内存
  418. s_free(sh);
  419. // c串
  420. s = (char*)newsh+hdrlen;
  421. //设置新的类型
  422. s[-1] = type;
  423. //设置新的sds长度
  424. sdssetlen(s, len);
  425. }
  426. //设置sds可用内存为0的内存
  427. sdssetalloc(s, len);
  428. return s;
  429. }
  430. /* Return the total size of the allocation of the specified sds string,
  431. * including:
  432. * 1) The sds header before the pointer.
  433. * 2) The string.
  434. * 3) The free buffer at the end if any.
  435. * 4) The implicit null term.
  436. */
  437. // 返回一个sds的总长度,包括头,二进制字符串分配的内存长度和'\0'
  438. size_t sdsAllocSize(sds s) {
  439. //sds分配的内存大小
  440. size_t alloc = sdsalloc(s);
  441. // sds类型结构占用的内存大小 + 可用内存空间 + 1
  442. return sdsHdrSize(s[-1])+alloc+1;
  443. }
  444. /* Return the pointer of the actual SDS allocation (normally SDS strings
  445. * are referenced by the start of the string buffer). */
  446. /**
  447. * 返回一个sds的控制结构的起始地址
  448. * @param s sds字符串
  449. * @return 返回buf缓冲指针
  450. */
  451. void *sdsAllocPtr(sds s) {
  452. return (void*) (s-sdsHdrSize(s[-1]));
  453. }
  454. /* Increment the sds length and decrements the left free space at the
  455. * end of the string according to 'incr'. Also set the null term
  456. * in the new end of the string.
  457. *
  458. * This function is used in order to fix the string length after the
  459. * user calls sdsMakeRoomFor(), writes something after the end of
  460. * the current string, and finally needs to set the new length.
  461. *
  462. * Note: it is possible to use a negative increment in order to
  463. * right-trim the string.
  464. *
  465. * Usage example:
  466. *
  467. * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the
  468. * following schema, to cat bytes coming from the kernel to the end of an
  469. * sds string without copying into an intermediate buffer:
  470. *
  471. * oldlen = sdslen(s);
  472. * s = sdsMakeRoomFor(s, BUFFER_SIZE);
  473. * nread = read(fd, s+oldlen, BUFFER_SIZE);
  474. * ... check for nread <= 0 and handle it ...
  475. * sdsIncrLen(s, nread);
  476. */
  477. /**
  478. * 增加一个sds的已经使用的长度,要求加完之后不能超过分配的内存长度
  479. * @param s
  480. * @param incr
  481. */
  482. void sdsIncrLen(sds s, ssize_t incr) {
  483. unsigned char flags = s[-1];
  484. size_t len;
  485. //判断类型
  486. switch(flags&SDS_TYPE_MASK) {
  487. case SDS_TYPE_5: {
  488. //标志位flags
  489. unsigned char *fp = ((unsigned char*)s)-1;
  490. unsigned char oldlen = SDS_TYPE_5_LEN(flags);
  491. assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr)));
  492. *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS);
  493. len = oldlen+incr;
  494. break;
  495. }
  496. case SDS_TYPE_8: {
  497. SDS_HDR_VAR(8,s);
  498. assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));
  499. len = (sh->len += incr);
  500. break;
  501. }
  502. case SDS_TYPE_16: {
  503. SDS_HDR_VAR(16,s);
  504. assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));
  505. len = (sh->len += incr);
  506. break;
  507. }
  508. case SDS_TYPE_32: {
  509. SDS_HDR_VAR(32,s);
  510. assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));
  511. len = (sh->len += incr);
  512. break;
  513. }
  514. case SDS_TYPE_64: {
  515. SDS_HDR_VAR(64,s);
  516. assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr)));
  517. len = (sh->len += incr);
  518. break;
  519. }
  520. default: len = 0; /* Just to avoid compilation warnings. */
  521. }
  522. s[len] = '\0';
  523. }
  524. /* Grow the sds to have the specified length. Bytes that were not part of
  525. * the original length of the sds will be set to zero.
  526. *
  527. * if the specified length is smaller than the current length, no operation
  528. * is performed. */
  529. /**
  530. * 给一个sds的已经使用长度增加到指定长度,并将增加部分内存清零
  531. * @param s
  532. * @param len
  533. * @return
  534. */
  535. sds sdsgrowzero(sds s, size_t len) {
  536. //获取sds字符串长度
  537. size_t curlen = sdslen(s);
  538. //指定的长度如果下雨当前sds字符串长度 则不做处理
  539. if (len <= curlen) return s;
  540. //sds扩容
  541. s = sdsMakeRoomFor(s,len-curlen);
  542. //如果为NULL 则内存分配失败
  543. if (s == NULL) return NULL;
  544. // s+curlen ~ len-curlen+1 区间为0
  545. /* Make sure added region doesn't contain garbage */
  546. memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
  547. //设置sds长度
  548. sdssetlen(s, len);
  549. return s;
  550. }
  551. /* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
  552. * end of the specified sds string 's'.
  553. *
  554. * After the call, the passed sds string is no longer valid and all the
  555. * references must be substituted with the new pointer returned by the call. */
  556. /**
  557. * 在一个sds后面连接给定长度的二进制字符串
  558. * @param s sds字符串
  559. * @param t 任意类型的值
  560. * @param len 长度
  561. * @return sds字符串
  562. */
  563. sds sdscatlen(sds s, const void *t, size_t len) {
  564. //获取sds字符串长度
  565. size_t curlen = sdslen(s);
  566. //sds扩容
  567. s = sdsMakeRoomFor(s,len);
  568. if (s == NULL) return NULL;
  569. //复制字符串
  570. memcpy(s+curlen, t, len);
  571. //重新设置字符串
  572. sdssetlen(s, curlen+len);
  573. //sds末尾置'\0'
  574. s[curlen+len] = '\0';
  575. return s;
  576. }
  577. /* Append the specified null terminated C string to the sds string 's'.
  578. *
  579. * After the call, the passed sds string is no longer valid and all the
  580. * references must be substituted with the new pointer returned by the call. */
  581. /**
  582. * 在一个sds后面连接一个C字符串
  583. * @param s
  584. * @param t
  585. * @return
  586. */
  587. sds sdscat(sds s, const char *t) {
  588. return sdscatlen(s, t, strlen(t));
  589. }
  590. /* Append the specified sds 't' to the existing sds 's'.
  591. *
  592. * After the call, the modified sds string is no longer valid and all the
  593. * references must be substituted with the new pointer returned by the call. */
  594. /**
  595. * 将一个sds的已经使用的内存连接到另一个sds中
  596. * @param s
  597. * @param t
  598. * @return
  599. */
  600. sds sdscatsds(sds s, const sds t) {
  601. return sdscatlen(s, t, sdslen(t));
  602. }
  603. /* Destructively modify the sds string 's' to hold the specified binary
  604. * safe string pointed by 't' of length 'len' bytes. */
  605. /**
  606. * 将一个给定长度的二进制字符串复制到sds,并更新已经使用的长度
  607. * @param s
  608. * @param t
  609. * @param len
  610. * @return
  611. */
  612. sds sdscpylen(sds s, const char *t, size_t len) {
  613. //如果长度len大于sds分配的内存大小
  614. if (sdsalloc(s) < len) {
  615. //sds扩容
  616. s = sdsMakeRoomFor(s,len-sdslen(s));
  617. if (s == NULL) return NULL;
  618. }
  619. //复制字符串
  620. memcpy(s, t, len);
  621. s[len] = '\0';
  622. //设置长度
  623. sdssetlen(s, len);
  624. return s;
  625. }
  626. /* Like sdscpylen() but 't' must be a null-termined string so that the length
  627. * of the string is obtained with strlen(). */
  628. /**
  629. * 将一个C字符串复制到sds
  630. * @param s
  631. * @param t
  632. * @return
  633. */
  634. sds sdscpy(sds s, const char *t) {
  635. return sdscpylen(s, t, strlen(t));
  636. }
  637. /* Helper for sdscatlonglong() doing the actual number -> string
  638. * conversion. 's' must point to a string with room for at least
  639. * SDS_LLSTR_SIZE bytes.
  640. *
  641. * The function returns the length of the null-terminated string
  642. * representation stored at 's'. */
  643. #define SDS_LLSTR_SIZE 21
  644. /**
  645. * 将一个long long转换成C字符串格式
  646. * @param s
  647. * @param value
  648. * @return
  649. */
  650. int sdsll2str(char *s, long long value) {
  651. char *p, aux;
  652. unsigned long long v;
  653. size_t l;
  654. /* Generate the string representation, this method produces
  655. * a reversed string. */
  656. v = (value < 0) ? -value : value;
  657. p = s;
  658. do {
  659. *p++ = '0'+(v%10);
  660. v /= 10;
  661. } while(v);
  662. if (value < 0) *p++ = '-';
  663. /* Compute length and add null term. */
  664. l = p-s;
  665. *p = '\0';
  666. /* Reverse the string. */
  667. p--;
  668. while(s < p) {
  669. aux = *s;
  670. *s = *p;
  671. *p = aux;
  672. s++;
  673. p--;
  674. }
  675. return l;
  676. }
  677. /**
  678. * 将一个unsigned long long 转换成C字符串格式
  679. * @param s
  680. * @param v
  681. * @return
  682. */
  683. /* Identical sdsll2str(), but for unsigned long long type. */
  684. int sdsull2str(char *s, unsigned long long v) {
  685. char *p, aux;
  686. size_t l;
  687. /* Generate the string representation, this method produces
  688. * a reversed string. */
  689. p = s;
  690. do {
  691. *p++ = '0'+(v%10);
  692. v /= 10;
  693. } while(v);
  694. /* Compute length and add null term. */
  695. l = p-s;
  696. *p = '\0';
  697. /* Reverse the string. */
  698. p--;
  699. while(s < p) {
  700. aux = *s;
  701. *s = *p;
  702. *p = aux;
  703. s++;
  704. p--;
  705. }
  706. return l;
  707. }
  708. /* Create an sds string from a long long value. It is much faster than:
  709. *
  710. * sdscatprintf(sdsempty(),"%lld\n", value);
  711. */
  712. /**
  713. * 使用long long制造一个sds
  714. * @param value
  715. * @return
  716. */
  717. sds sdsfromlonglong(long long value) {
  718. char buf[SDS_LLSTR_SIZE];
  719. //转换成C串
  720. int len = sdsll2str(buf,value);
  721. //创建sds字符串 使用s_malloc_usable创建内存空
  722. return sdsnewlen(buf,len);
  723. }
  724. /**
  725. * 将可变长格式化字符串连接到sds后面
  726. * @param s
  727. * @param fmt
  728. * @param ap
  729. * @return
  730. */
  731. /* Like sdscatprintf() but gets va_list instead of being variadic. */
  732. sds sdscatvprintf(sds s, const char *fmt, va_list ap) {
  733. va_list cpy;
  734. char staticbuf[1024], *buf = staticbuf, *t;
  735. //获取fmt字符串长度 * 2
  736. size_t buflen = strlen(fmt)*2;
  737. int bufstrlen;
  738. /* We try to start using a static buffer for speed.
  739. * If not possible we revert to heap allocation. */
  740. if (buflen > sizeof(staticbuf)) {
  741. // 如果格式化字符串长度*2 大于 缓冲区长度,则分配内存
  742. buf = s_malloc(buflen);
  743. if (buf == NULL) return NULL;
  744. } else {
  745. //如果格式化字符串长度*2 小于等于缓冲区大小 则设置为缓冲区大小
  746. buflen = sizeof(staticbuf);
  747. }
  748. /* Alloc enough space for buffer and \0 after failing to
  749. * fit the string in the current buffer size. */
  750. while(1) {
  751. //将ap复制到cpy
  752. va_copy(cpy,ap);
  753. //将可变参数格式化输出到一个字符数组。
  754. bufstrlen = vsnprintf(buf, buflen, fmt, cpy);
  755. //将cpy置为NULL
  756. va_end(cpy);
  757. if (bufstrlen < 0) {
  758. //如果bufstrlen小于0 且 buf 不等于 staticbuf释放buf 并返回NULL
  759. if (buf != staticbuf) s_free(buf);
  760. return NULL;
  761. }
  762. if (((size_t)bufstrlen) >= buflen) {
  763. if (buf != staticbuf) s_free(buf);
  764. buflen = ((size_t)bufstrlen) + 1;
  765. buf = s_malloc(buflen);
  766. if (buf == NULL) return NULL;
  767. continue;
  768. }
  769. break;
  770. }
  771. /* Finally concat the obtained string to the SDS string and return it. */
  772. //将字符串拼接到sds后面
  773. t = sdscatlen(s, buf, bufstrlen);
  774. if (buf != staticbuf) s_free(buf); //释放buf缓冲区内存
  775. return t;
  776. }
  777. /* Append to the sds string 's' a string obtained using printf-alike format
  778. * specifier.
  779. *
  780. * After the call, the modified sds string is no longer valid and all the
  781. * references must be substituted with the new pointer returned by the call.
  782. *
  783. * Example:
  784. *
  785. * s = sdsnew("Sum is: ");
  786. * s = sdscatprintf(s,"%d+%d = %d",a,b,a+b).
  787. *
  788. * Often you need to create a string from scratch with the printf-alike
  789. * format. When this is the need, just use sdsempty() as the target string:
  790. *
  791. * s = sdscatprintf(sdsempty(), "... your format ...", args);
  792. */
  793. /**
  794. * 是sdscatvprintf的包装, 将可变长格式化字符串连接到sds后面
  795. * @param s
  796. * @param fmt
  797. * @param ...
  798. * @return
  799. */
  800. sds sdscatprintf(sds s, const char *fmt, ...) {
  801. va_list ap;
  802. char *t;
  803. va_start(ap, fmt);
  804. t = sdscatvprintf(s,fmt,ap);
  805. va_end(ap);
  806. return t;
  807. }
  808. /* This function is similar to sdscatprintf, but much faster as it does
  809. * not rely on sprintf() family functions implemented by the libc that
  810. * are often very slow. Moreover directly handling the sds string as
  811. * new data is concatenated provides a performance improvement.
  812. *
  813. * However this function only handles an incompatible subset of printf-alike
  814. * format specifiers:
  815. *
  816. * %s - C String
  817. * %S - SDS string
  818. * %i - signed int
  819. * %I - 64 bit signed integer (long long, int64_t)
  820. * %u - unsigned int
  821. * %U - 64 bit unsigned integer (unsigned long long, uint64_t)
  822. * %% - Verbatim "%" character.
  823. */
  824. /**
  825. * 和sdscatvprintf功能一样,区别是不使用sprintf族函数,性能高
  826. * @param s
  827. * @param fmt
  828. * @param ...
  829. * @return
  830. */
  831. sds sdscatfmt(sds s, char const *fmt, ...) {
  832. //initlen= s长度
  833. size_t initlen = sdslen(s);
  834. const char *f = fmt;
  835. long i;
  836. va_list ap;
  837. /* To avoid continuous reallocations, let's start with a buffer that
  838. * can hold at least two times the format string itself. It's not the
  839. * best heuristic but seems to work in practice. */
  840. //sds扩容
  841. s = sdsMakeRoomFor(s, strlen(fmt)*2);
  842. //宏 ap储存fmt参数
  843. va_start(ap,fmt);
  844. f = fmt; /* Next format specifier byte to process. */
  845. i = initlen; /* Position of the next byte to write to dest str. */
  846. while(*f) {
  847. char next, *str;
  848. size_t l;
  849. long long num;
  850. unsigned long long unum;
  851. /* Make sure there is always space for at least 1 char. */
  852. if (sdsavail(s)==0) {
  853. //如果可用空间为0,则扩容,内存大小+1
  854. s = sdsMakeRoomFor(s,1);
  855. }
  856. switch(*f) {
  857. case '%':
  858. next = *(f+1);
  859. f++;
  860. switch(next) {
  861. case 's':
  862. case 'S':
  863. str = va_arg(ap,char*);
  864. //next如果是s则使用strlen获取长度,否则使用sds的sdslen根据sds的len值去获取长度
  865. l = (next == 's') ? strlen(str) : sdslen(str);
  866. if (sdsavail(s) < l) {
  867. //如果可以长度小于l长度则扩容
  868. s = sdsMakeRoomFor(s,l);
  869. }
  870. //复制
  871. memcpy(s+i,str,l);
  872. //增加sds字符串长度
  873. sdsinclen(s,l);
  874. i += l;
  875. break;
  876. case 'i':
  877. case 'I':
  878. if (next == 'i')
  879. num = va_arg(ap,int);
  880. else
  881. num = va_arg(ap,long long);
  882. {
  883. //SDS_LLSTR_SIZE = 21 char buf[21]
  884. char buf[SDS_LLSTR_SIZE];
  885. //将long long转成C串
  886. l = sdsll2str(buf,num);
  887. if (sdsavail(s) < l) {
  888. //可用空间小于l则扩容
  889. s = sdsMakeRoomFor(s,l);
  890. }
  891. //复制
  892. memcpy(s+i,buf,l);
  893. //增加sds字符串长度
  894. sdsinclen(s,l);
  895. i += l;
  896. }
  897. break;
  898. case 'u':
  899. case 'U':
  900. if (next == 'u')
  901. unum = va_arg(ap,unsigned int);
  902. else
  903. unum = va_arg(ap,unsigned long long);
  904. {
  905. char buf[SDS_LLSTR_SIZE];
  906. //将一个unsigned long long 转换成C字符串格式
  907. l = sdsull2str(buf,unum);
  908. if (sdsavail(s) < l) {
  909. //扩容
  910. s = sdsMakeRoomFor(s,l);
  911. }
  912. memcpy(s+i,buf,l);
  913. sdsinclen(s,l);
  914. i += l;
  915. }
  916. break;
  917. default: /* Handle %% and generally %<unknown>. */
  918. //处理%%的情况
  919. s[i++] = next;
  920. //增加sds字符串长
  921. sdsinclen(s,1);
  922. break;
  923. }
  924. break;
  925. default:
  926. s[i++] = *f;
  927. sdsinclen(s,1);
  928. break;
  929. }
  930. f++;
  931. }
  932. //设置ap 为NULL
  933. va_end(ap);
  934. //sds串末尾置为'\0'
  935. /* Add null-term */
  936. s[i] = '\0';
  937. return s;
  938. }
  939. /* Remove the part of the string from left and from right composed just of
  940. * contiguous characters found in 'cset', that is a null terminted C string.
  941. *
  942. * After the call, the modified sds string is no longer valid and all the
  943. * references must be substituted with the new pointer returned by the call.
  944. *
  945. * Example:
  946. *
  947. * s = sdsnew("AA...AA.a.aa.aHelloWorld :::");
  948. * s = sdstrim(s,"Aa. :");
  949. * printf("%s\n", s);
  950. *
  951. * Output will be just "HelloWorld".
  952. */
  953. /**
  954. * 从sds的头和尾去掉所有和给定字符一致的内容,保留剩下的部分
  955. * @param s
  956. * @param cset
  957. * @return sds
  958. */
  959. sds sdstrim(sds s, const char *cset) {
  960. char *start, *end, *sp, *ep;
  961. size_t len;
  962. //sp 指向头 ep指向尾
  963. sp = start = s;
  964. ep = end = s+sdslen(s)-1;
  965. // 用于去掉sp头部有参数cset的部分
  966. while(sp <= end && strchr(cset, *sp)) sp++;
  967. while(ep > sp && strchr(cset, *ep)) ep--;
  968. //新的长度
  969. len = (sp > ep) ? 0 : ((ep-sp)+1);
  970. //sds拷贝 sp到s
  971. if (s != sp) memmove(s, sp, len);
  972. s[len] = '\0';
  973. //设置sds
  974. sdssetlen(s,len);
  975. return s;
  976. }
  977. /* Changes the input string to be a subset of the original.
  978. * It does not release the free space in the string, so a call to
  979. * sdsRemoveFreeSpace may be wise after. */
  980. /**
  981. *
  982. * @param s
  983. * @param start
  984. * @param len
  985. */
  986. void sdssubstr(sds s, size_t start, size_t len) {
  987. /* Clamp out of range input */
  988. //获取sds长度
  989. size_t oldlen = sdslen(s);
  990. //如果起始点大于sds长度 则设置start = len = 0
  991. if (start >= oldlen) start = len = 0;
  992. //长度如果大于 sds长度-起始点 重新设置长度为 sds长度-起始点
  993. if (len > oldlen-start) len = oldlen-start;
  994. //将 s 的 N 个字节复制到 DEST,保证重叠字符串的正确行为。
  995. /* Move the data */
  996. if (len) memmove(s, s+start, len);
  997. s[len] = 0;
  998. //给sds设置新的长度
  999. sdssetlen(s,len);
  1000. }
  1001. /* Turn the string into a smaller (or equal) string containing only the
  1002. * substring specified by the 'start' and 'end' indexes.
  1003. *
  1004. * start and end can be negative, where -1 means the last character of the
  1005. * string, -2 the penultimate character, and so forth.
  1006. *
  1007. * The interval is inclusive, so the start and end characters will be part
  1008. * of the resulting string.
  1009. *
  1010. * The string is modified in-place.
  1011. *
  1012. * NOTE: this function can be misleading and can have unexpected behaviour,
  1013. * specifically when you want the length of the new string to be 0.
  1014. * Having start==end will result in a string with one character.
  1015. * please consider using sdssubstr instead.
  1016. *
  1017. * Example:
  1018. *
  1019. * s = sdsnew("Hello World");
  1020. * sdsrange(s,1,-1); => "ello World"
  1021. */
  1022. /**
  1023. * 将sds切片,提供起始和终止位置,可以是负数表示从结尾开始
  1024. * @param s sds字符串
  1025. * @param start 开始
  1026. * @param end 结束
  1027. */
  1028. void sdsrange(sds s, ssize_t start, ssize_t end) {
  1029. size_t newlen, len = sdslen(s);
  1030. if (len == 0) return;
  1031. if (start < 0)
  1032. start = len + start;
  1033. if (end < 0)
  1034. end = len + end;
  1035. newlen = (start > end) ? 0 : (end-start)+1;
  1036. sdssubstr(s, start, newlen);
  1037. }
  1038. /**
  1039. * 将sds的所有字母变成小写,内部是tolower
  1040. * @param s sds
  1041. */
  1042. /* Apply tolower() to every character of the sds string 's'. */
  1043. void sdstolower(sds s) {
  1044. size_t len = sdslen(s), j;
  1045. for (j = 0; j < len; j++) s[j] = tolower(s[j]);
  1046. }
  1047. /**
  1048. * 将sds的所有字母变成大写,内部是toupper
  1049. * @param s sds
  1050. */
  1051. /* Apply toupper() to every character of the sds string 's'. */
  1052. void sdstoupper(sds s) {
  1053. size_t len = sdslen(s), j;
  1054. for (j = 0; j < len; j++) s[j] = toupper(s[j]);
  1055. }
  1056. /* Compare two sds strings s1 and s2 with memcmp().
  1057. *
  1058. * Return value:
  1059. *
  1060. * positive if s1 > s2.
  1061. * negative if s1 < s2.
  1062. * 0 if s1 and s2 are exactly the same binary string.
  1063. *
  1064. * If two strings share exactly the same prefix, but one of the two has
  1065. * additional characters, the longer string is considered to be greater than
  1066. * the smaller one. */
  1067. /**
  1068. * 比较两个sds,内部是memcmp
  1069. * @param s1 sds1
  1070. * @param s2 sds2
  1071. * @return
  1072. */
  1073. int sdscmp(const sds s1, const sds s2) {
  1074. size_t l1, l2, minlen;
  1075. int cmp;
  1076. //获取sds字符串长度
  1077. l1 = sdslen(s1);
  1078. l2 = sdslen(s2);
  1079. minlen = (l1 < l2) ? l1 : l2;
  1080. /**
  1081. * memcmp
  1082. * s1 < s2 cmp <0
  1083. * s1==s2 cmp =0
  1084. * s1>s2 cmp > 0
  1085. */
  1086. cmp = memcmp(s1,s2,minlen);
  1087. //如果cmp = 0的话 就比较长度
  1088. if (cmp == 0) return l1>l2? 1: (l1<l2? -1: 0);
  1089. return cmp;
  1090. }
  1091. /* Split 's' with separator in 'sep'. An array
  1092. * of sds strings is returned. *count will be set
  1093. * by reference to the number of tokens returned.
  1094. *
  1095. * On out of memory, zero length string, zero length
  1096. * separator, NULL is returned.
  1097. *
  1098. * Note that 'sep' is able to split a string using
  1099. * a multi-character separator. For example
  1100. * sdssplit("foo_-_bar","_-_"); will return two
  1101. * elements "foo" and "bar".
  1102. *
  1103. * This version of the function is binary-safe but
  1104. * requires length arguments. sdssplit() is just the
  1105. * same function but for zero-terminated strings.
  1106. */
  1107. /**
  1108. *
  1109. * 将字符串用指定的分割器分割成若干部分,存入sds指针数组,并返回这个指针数组,是简单的字符串匹配,可以使用KMP优化
  1110. * 输入长度为@len的字符串@s,以及长度为@seplen的字符串@sep。使用@sep对@s进行切分。
  1111. * 切分好的字符串通过返回值@tokens传出,切分得到的个数通过参数@count传出。
  1112. *
  1113. * @param s s字符串
  1114. * @param len 长度
  1115. * @param sep 分隔字符串
  1116. * @param seplen 分隔字符串的长度
  1117. * @param count 分隔后的数组个数
  1118. * @return 返回@tokens
  1119. */
  1120. sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) {
  1121. int elements = 0, slots = 5;
  1122. long start = 0, j;
  1123. sds *tokens;
  1124. //如果分隔字符串长度小于0 或者要被分割的字符串长度小于0 那么直接返回NULL
  1125. if (seplen < 1 || len < 0) return NULL;
  1126. //分配内存空间
  1127. tokens = s_malloc(sizeof(sds)*slots);
  1128. //如果tokens为NULL 分配内存失败
  1129. if (tokens == NULL) return NULL;
  1130. if (len == 0) {
  1131. *count = 0;
  1132. return tokens;
  1133. }
  1134. for (j = 0; j < (len-(seplen-1)); j++) {
  1135. /* make sure there is room for the next element and the final one */
  1136. //确保预留空间
  1137. if (slots < elements+2) {
  1138. sds *newtokens;
  1139. slots *= 2;
  1140. //分配内存
  1141. newtokens = s_realloc(tokens,sizeof(sds)*slots);
  1142. if (newtokens == NULL) goto cleanup;
  1143. tokens = newtokens;
  1144. }
  1145. /* search the separator */
  1146. /*
  1147. * 两种情况:
  1148. * 1、sep只有一个字符,一个字符一个字符比较,如果相等则进行分割
  1149. * 2、sep是字符串有多个字符,直接用memcmp进行比较,等于0代表相等,每次比较的长度为seplen
  1150. */
  1151. if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {
  1152. //分割字符串
  1153. tokens[elements] = sdsnewlen(s+start,j-start);
  1154. //判断是否分配内存失败,如果失败则goto到cleanup去释放tokens空间
  1155. if (tokens[elements] == NULL) goto cleanup;
  1156. elements++;
  1157. start = j+seplen;
  1158. //跳过分割符
  1159. j = j+seplen-1; /* skip the separator */
  1160. }
  1161. }
  1162. /* Add the final element. We are sure there is room in the tokens array. */
  1163. //最后添加一个元素,确保tokens长度不为0
  1164. tokens[elements] = sdsnewlen(s+start,len-start);
  1165. //判断内存分配是否成功
  1166. if (tokens[elements] == NULL) goto cleanup;
  1167. elements++;
  1168. *count = elements;
  1169. return tokens;
  1170. cleanup:
  1171. {
  1172. //释放tokens数组中的元素
  1173. int i;
  1174. for (i = 0; i < elements; i++) sdsfree(tokens[i]);
  1175. s_free(tokens);
  1176. *count = 0;
  1177. return NULL;
  1178. }
  1179. }
  1180. /**
  1181. * 释放sdssplitlen产生的指针数组和其中的sds的内存
  1182. * @param tokens 分割后得到的数组
  1183. * @param count 数组中元素个数
  1184. */
  1185. /* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */
  1186. void sdsfreesplitres(sds *tokens, int count) {
  1187. if (!tokens) return;
  1188. while(count--)
  1189. sdsfree(tokens[count]);
  1190. s_free(tokens);
  1191. }
  1192. /* Append to the sds string "s" an escaped string representation where
  1193. * all the non-printable characters (tested with isprint()) are turned into
  1194. * escapes in the form "\n\r\a...." or "\x<hex-number>".
  1195. *
  1196. * After the call, the modified sds string is no longer valid and all the
  1197. * references must be substituted with the new pointer returned by the call. */
  1198. /**
  1199. * 处理包含转义字符的二进制字符串
  1200. * @param s
  1201. * @param p
  1202. * @param len
  1203. * @return
  1204. */
  1205. sds sdscatrepr(sds s, const char *p, size_t len) {
  1206. //给s字符串后拼接 "\""
  1207. s = sdscatlen(s,"\"",1);
  1208. while(len--) {
  1209. switch(*p) {
  1210. case '\\':
  1211. case '"':
  1212. //将可变长格式化字符串连接到sds后面
  1213. s = sdscatprintf(s,"\\%c",*p);
  1214. break;
  1215. case '\n': s = sdscatlen(s,"\\n",2); break;
  1216. case '\r': s = sdscatlen(s,"\\r",2); break;
  1217. case '\t': s = sdscatlen(s,"\\t",2); break;
  1218. case '\a': s = sdscatlen(s,"\\a",2); break;
  1219. case '\b': s = sdscatlen(s,"\\b",2); break;
  1220. default:
  1221. //检查所传的字符是否是可打印的 可打印为true 否则为false
  1222. if (isprint(*p))
  1223. //将可变长格式化字符串连接到sds后面
  1224. s = sdscatprintf(s,"%c",*p);
  1225. else
  1226. s = sdscatprintf(s,"\\x%02x",(unsigned char)*p);
  1227. break;
  1228. }
  1229. p++;
  1230. }
  1231. //给s字符串后拼接 "\""
  1232. return sdscatlen(s,"\"",1);
  1233. }
  1234. /**
  1235. * 判断char c是否是十六进制数,是根据ASCII码判断的
  1236. * @param c 字符
  1237. * @return
  1238. */
  1239. /* Helper function for sdssplitargs() that returns non zero if 'c'
  1240. * is a valid hex digit. */
  1241. int is_hex_digit(char c) {
  1242. return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  1243. (c >= 'A' && c <= 'F');
  1244. }
  1245. /**
  1246. * 将一个十六进制字符转换成十进制
  1247. * @param c 字符
  1248. * @return
  1249. */
  1250. /* Helper function for sdssplitargs() that converts a hex digit into an
  1251. * integer from 0 to 15 */
  1252. int hex_digit_to_int(char c) {
  1253. switch(c) {
  1254. case '0': return 0;
  1255. case '1': return 1;
  1256. case '2': return 2;
  1257. case '3': return 3;
  1258. case '4': return 4;
  1259. case '5': return 5;
  1260. case '6': return 6;
  1261. case '7': return 7;
  1262. case '8': return 8;
  1263. case '9': return 9;
  1264. case 'a': case 'A': return 10;
  1265. case 'b': case 'B': return 11;
  1266. case 'c': case 'C': return 12;
  1267. case 'd': case 'D': return 13;
  1268. case 'e': case 'E': return 14;
  1269. case 'f': case 'F': return 15;
  1270. default: return 0;
  1271. }
  1272. }
  1273. /* Split a line into arguments, where every argument can be in the
  1274. * following programming-language REPL-alike form:
  1275. *
  1276. * foo bar "newline are supported\n" and "\xff\x00otherstuff"
  1277. *
  1278. * The number of arguments is stored into *argc, and an array
  1279. * of sds is returned.
  1280. *
  1281. * The caller should free the resulting array of sds strings with
  1282. * sdsfreesplitres().
  1283. *
  1284. * Note that sdscatrepr() is able to convert back a string into
  1285. * a quoted string in the same format sdssplitargs() is able to parse.
  1286. *
  1287. * The function returns the allocated tokens on success, even when the
  1288. * input string is empty, or NULL if the input contains unbalanced
  1289. * quotes or closed quotes followed by non space characters
  1290. * as in: "foo"bar or "foo'
  1291. */
  1292. /**
  1293. * 字符串分割函数
  1294. * 将一行内容读取到sds指针数组,解析配置文件时使用,每个配置项保存在一个sds中,此函数返回一个sds指针数组和其元素个数
  1295. * @param line
  1296. * @param argc
  1297. * @return
  1298. */
  1299. sds *sdssplitargs(const char *line, int *argc) {
  1300. const char *p = line;
  1301. char *current = NULL;
  1302. char **vector = NULL;
  1303. *argc = 0;
  1304. while(1) {
  1305. /* skip blanks */
  1306. // isspace 判断字符是否为空白字符 不是空白字符 返回0 ,是空白字符 返回非0
  1307. while(*p && isspace(*p)) p++;
  1308. if (*p) {
  1309. /* get a token */
  1310. int inq=0; /* set to 1 if we are in "quotes" */
  1311. int insq=0; /* set to 1 if we are in 'single quotes' */
  1312. int done=0;
  1313. //如果curent为NULL则创建一个空的sds字符串
  1314. if (current == NULL) current = sdsempty();
  1315. while(!done) {
  1316. // *p = '"' inq = 1
  1317. //处理单引号
  1318. if (inq) {
  1319. //处理16进制数字转换
  1320. // 如果满足 *p == '\\' *(p+1) == 'x' 和 *(p+2)、*(p+3)都是十六进制
  1321. if (*p == '\\' && *(p+1) == 'x' &&
  1322. is_hex_digit(*(p+2)) &&
  1323. is_hex_digit(*(p+3)))
  1324. {
  1325. unsigned char byte;
  1326. // 16进制转10进制
  1327. byte = (hex_digit_to_int(*(p+2))*16)+
  1328. hex_digit_to_int(*(p+3));
  1329. current = sdscatlen(current,(char*)&byte,1);
  1330. p += 3;
  1331. } else if (*p == '\\' && *(p+1)) {
  1332. //处理特殊字符
  1333. char c;
  1334. p++;
  1335. switch(*p) {
  1336. case 'n': c = '\n'; break;
  1337. case 'r': c = '\r'; break;
  1338. case 't': c = '\t'; break;
  1339. case 'b': c = '\b'; break;
  1340. case 'a': c = '\a'; break;
  1341. default: c = *p; break;
  1342. }
  1343. current = sdscatlen(current,&c,1);
  1344. } else if (*p == '"') {
  1345. /* closing quote must be followed by a space or
  1346. * nothing at all. */
  1347. if (*(p+1) && !isspace(*(p+1))) goto err;
  1348. done=1;
  1349. } else if (!*p) {
  1350. /* unterminated quotes */
  1351. goto err;
  1352. } else {
  1353. current = sdscatlen(current,p,1);
  1354. }
  1355. } else if (insq) {
  1356. //处理单引号
  1357. if (*p == '\\' && *(p+1) == '\'') {
  1358. p++;
  1359. current = sdscatlen(current,"'",1);
  1360. } else if (*p == '\'') {
  1361. /* closing quote must be followed by a space or
  1362. * nothing at all. */
  1363. if (*(p+1) && !isspace(*(p+1))) goto err;
  1364. done=1;
  1365. } else if (!*p) {
  1366. /* unterminated quotes */
  1367. goto err;
  1368. } else {
  1369. current = sdscatlen(current,p,1);
  1370. }
  1371. } else {
  1372. switch(*p) {
  1373. case ' ':
  1374. case '\n':
  1375. case '\r':
  1376. case '\t':
  1377. case '\0':
  1378. done=1;
  1379. break;
  1380. case '"':
  1381. inq=1;
  1382. break;
  1383. case '\'':
  1384. insq=1;
  1385. break;
  1386. default:
  1387. //拼接到curent后面
  1388. current = sdscatlen(current,p,1);
  1389. break;
  1390. }
  1391. }
  1392. if (*p) p++;
  1393. }
  1394. //分配内存空间
  1395. /* add the token to the vector */
  1396. vector = s_realloc(vector,((*argc)+1)*sizeof(char*));
  1397. vector[*argc] = current;
  1398. (*argc)++;
  1399. current = NULL;
  1400. } else {
  1401. /* Even on empty input string return something not NULL. */
  1402. //即使输入为空也返回不为空的内容
  1403. if (vector == NULL) vector = s_malloc(sizeof(void*));
  1404. return vector;
  1405. }
  1406. }
  1407. err:
  1408. while((*argc)--)
  1409. sdsfree(vector[*argc]);
  1410. s_free(vector);
  1411. if (current) sdsfree(current);
  1412. *argc = 0;
  1413. return NULL;
  1414. }
  1415. /* Modify the string substituting all the occurrences of the set of
  1416. * characters specified in the 'from' string to the corresponding character
  1417. * in the 'to' array.
  1418. *
  1419. * For instance: sdsmapchars(mystring, "ho", "01", 2)
  1420. * will have the effect of turning the string "hello" into "0ell1".
  1421. *
  1422. * The function returns the sds string pointer, that is always the same
  1423. * as the input pointer since no resize is needed. */
  1424. /**
  1425. * 将sds中出现在指定字符集中的字符用另一个字符集中的字符代替,要求两个字符集长度相等
  1426. * @param s sds字符串
  1427. * @param from 指定的字符
  1428. * @param to 替换成的字符
  1429. * @param setlen 长度
  1430. * @return sds
  1431. */
  1432. sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {
  1433. size_t j, i, l = sdslen(s);
  1434. for (j = 0; j < l; j++) {
  1435. for (i = 0; i < setlen; i++) {
  1436. if (s[j] == from[i]) {
  1437. s[j] = to[i];
  1438. break;
  1439. }
  1440. }
  1441. }
  1442. return s;
  1443. }
  1444. /* Join an array of C strings using the specified separator (also a C string).
  1445. * Returns the result as an sds string. */
  1446. /**
  1447. * 将若干C字符串用提供的分割器连接起来,产生一个sds
  1448. * @param argv C字符串
  1449. * @param argc 个数
  1450. * @param sep 分割符
  1451. * @return
  1452. */
  1453. sds sdsjoin(char **argv, int argc, char *sep) {
  1454. sds join = sdsempty();
  1455. int j;
  1456. for (j = 0; j < argc; j++) {
  1457. //字符串拼接到join后面
  1458. join = sdscat(join, argv[j]);
  1459. if (j != argc-1) join = sdscat(join,sep);
  1460. }
  1461. return join;
  1462. }
  1463. /**
  1464. * 和sdsjoin类似,连接的是若干sds
  1465. * @param argv 若干个sds字符串
  1466. * @param argc 个数
  1467. * @param sep 分隔符
  1468. * @param seplen 长度
  1469. * @return
  1470. */
  1471. /* Like sdsjoin, but joins an array of SDS strings. */
  1472. sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) {
  1473. sds join = sdsempty();
  1474. int j;
  1475. for (j = 0; j < argc; j++) {
  1476. join = sdscatsds(join, argv[j]);
  1477. if (j != argc-1) join = sdscatlen(join,sep,seplen);
  1478. }
  1479. return join;
  1480. }
  1481. /* Wrappers to the allocators used by SDS. Note that SDS will actually
  1482. * just use the macros defined into sdsalloc.h in order to avoid to pay
  1483. * the overhead of function calls. Here we define these wrappers only for
  1484. * the programs SDS is linked to, if they want to touch the SDS internals
  1485. * even if they use a different allocator. */
  1486. /**
  1487. * 分配内存
  1488. * @param size
  1489. * @return
  1490. */
  1491. void *sds_malloc(size_t size) { return s_malloc(size); }
  1492. /**
  1493. * 重新分配内存
  1494. * @param ptr
  1495. * @param size
  1496. * @return
  1497. */
  1498. void *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); }
  1499. /**
  1500. * 释放内存
  1501. * @param ptr
  1502. */
  1503. void sds_free(void *ptr) { s_free(ptr); }
  1504. /* Perform expansion of a template string and return the result as a newly
  1505. * allocated sds.
  1506. *
  1507. * Template variables are specified using curly brackets, e.g. {variable}.
  1508. * An opening bracket can be quoted by repeating it twice.
  1509. */
  1510. /**
  1511. * sds回调模板函数
  1512. * @param template
  1513. * @param cb_func
  1514. * @param cb_arg
  1515. * @return
  1516. */
  1517. sds sdstemplate(const char *template, sdstemplate_callback_t cb_func, void *cb_arg)
  1518. {
  1519. sds res = sdsempty();
  1520. const char *p = template;
  1521. while (*p) {
  1522. /* Find next variable, copy everything until there */
  1523. const char *sv = strchr(p, '{');
  1524. if (!sv) {
  1525. /* Not found: copy till rest of template and stop */
  1526. res = sdscat(res, p);
  1527. break;
  1528. } else if (sv > p) {
  1529. /* Found: copy anything up to the begining of the variable */
  1530. res = sdscatlen(res, p, sv - p);
  1531. }
  1532. /* Skip into variable name, handle premature end or quoting */
  1533. //跳过遍历名称
  1534. sv++;
  1535. if (!*sv) goto error; /* Premature end of template */
  1536. if (*sv == '{') {
  1537. /* Quoted '{' */
  1538. p = sv + 1;
  1539. res = sdscat(res, "{");
  1540. continue;
  1541. }
  1542. /* Find end of variable name, handle premature end of template */
  1543. const char *ev = strchr(sv, '}');
  1544. if (!ev) goto error;
  1545. /* Pass variable name to callback and obtain value. If callback failed,
  1546. * abort. */
  1547. // 通过变量名称去回调
  1548. sds varname = sdsnewlen(sv, ev - sv);
  1549. sds value = cb_func(varname, cb_arg);
  1550. //释放内存空间
  1551. sdsfree(varname);
  1552. if (!value) goto error;
  1553. //将值添加到结果
  1554. /* Append value to result and continue */
  1555. res = sdscat(res, value);
  1556. //释放值
  1557. sdsfree(value);
  1558. p = ev + 1;
  1559. }
  1560. return res;
  1561. error:
  1562. //释放res
  1563. sdsfree(res);
  1564. return NULL;
  1565. }
  1566. #ifdef REDIS_TEST
  1567. #include <stdio.h>
  1568. #include <limits.h>
  1569. #include "testhelp.h"
  1570. #define UNUSED(x) (void)(x)
  1571. static sds sdsTestTemplateCallback(sds varname, void *arg) {
  1572. UNUSED(arg);
  1573. static const char *_var1 = "variable1";
  1574. static const char *_var2 = "variable2";
  1575. if (!strcmp(varname, _var1)) return sdsnew("value1");
  1576. else if (!strcmp(varname, _var2)) return sdsnew("value2");
  1577. else return NULL;
  1578. }
  1579. int sdsTest(int argc, char **argv, int accurate) {
  1580. UNUSED(argc);
  1581. UNUSED(argv);
  1582. UNUSED(accurate);
  1583. {
  1584. sds x = sdsnew("foo"), y;
  1585. test_cond("Create a string and obtain the length",
  1586. sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0);
  1587. sdsfree(x);
  1588. x = sdsnewlen("foo",2);
  1589. test_cond("Create a string with specified length",
  1590. sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0);
  1591. x = sdscat(x,"bar");
  1592. test_cond("Strings concatenation",
  1593. sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0);
  1594. x = sdscpy(x,"a");
  1595. test_cond("sdscpy() against an originally longer string",
  1596. sdslen(x) == 1 && memcmp(x,"a\0",2) == 0);
  1597. x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk");
  1598. test_cond("sdscpy() against an originally shorter string",
  1599. sdslen(x) == 33 &&
  1600. memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0);
  1601. sdsfree(x);
  1602. x = sdscatprintf(sdsempty(),"%d",123);
  1603. test_cond("sdscatprintf() seems working in the base case",
  1604. sdslen(x) == 3 && memcmp(x,"123\0",4) == 0);
  1605. sdsfree(x);
  1606. x = sdscatprintf(sdsempty(),"a%cb",0);
  1607. test_cond("sdscatprintf() seems working with \\0 inside of result",
  1608. sdslen(x) == 3 && memcmp(x,"a\0""b\0",4) == 0);
  1609. {
  1610. sdsfree(x);
  1611. char etalon[1024*1024];
  1612. for (size_t i = 0; i < sizeof(etalon); i++) {
  1613. etalon[i] = '0';
  1614. }
  1615. x = sdscatprintf(sdsempty(),"%0*d",(int)sizeof(etalon),0);
  1616. test_cond("sdscatprintf() can print 1MB",
  1617. sdslen(x) == sizeof(etalon) && memcmp(x,etalon,sizeof(etalon)) == 0);
  1618. }
  1619. sdsfree(x);
  1620. x = sdsnew("--");
  1621. x = sdscatfmt(x, "Hello %s World %I,%I--", "Hi!", LLONG_MIN,LLONG_MAX);
  1622. test_cond("sdscatfmt() seems working in the base case",
  1623. sdslen(x) == 60 &&
  1624. memcmp(x,"--Hello Hi! World -9223372036854775808,"
  1625. "9223372036854775807--",60) == 0);
  1626. printf("[%s]\n",x);
  1627. sdsfree(x);
  1628. x = sdsnew("--");
  1629. x = sdscatfmt(x, "%u,%U--", UINT_MAX, ULLONG_MAX);
  1630. test_cond("sdscatfmt() seems working with unsigned numbers",
  1631. sdslen(x) == 35 &&
  1632. memcmp(x,"--4294967295,18446744073709551615--",35) == 0);
  1633. sdsfree(x);
  1634. x = sdsnew(" x ");
  1635. sdstrim(x," x");
  1636. test_cond("sdstrim() works when all chars match",
  1637. sdslen(x) == 0);
  1638. sdsfree(x);
  1639. x = sdsnew(" x ");
  1640. sdstrim(x," ");
  1641. test_cond("sdstrim() works when a single char remains",
  1642. sdslen(x) == 1 && x[0] == 'x');
  1643. sdsfree(x);
  1644. x = sdsnew("xxciaoyyy");
  1645. sdstrim(x,"xy");
  1646. test_cond("sdstrim() correctly trims characters",
  1647. sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0);
  1648. y = sdsdup(x);
  1649. sdsrange(y,1,1);
  1650. test_cond("sdsrange(...,1,1)",
  1651. sdslen(y) == 1 && memcmp(y,"i\0",2) == 0);
  1652. sdsfree(y);
  1653. y = sdsdup(x);
  1654. sdsrange(y,1,-1);
  1655. test_cond("sdsrange(...,1,-1)",
  1656. sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0);
  1657. sdsfree(y);
  1658. y = sdsdup(x);
  1659. sdsrange(y,-2,-1);
  1660. test_cond("sdsrange(...,-2,-1)",
  1661. sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0);
  1662. sdsfree(y);
  1663. y = sdsdup(x);
  1664. sdsrange(y,2,1);
  1665. test_cond("sdsrange(...,2,1)",
  1666. sdslen(y) == 0 && memcmp(y,"\0",1) == 0);
  1667. sdsfree(y);
  1668. y = sdsdup(x);
  1669. sdsrange(y,1,100);
  1670. test_cond("sdsrange(...,1,100)",
  1671. sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0);
  1672. sdsfree(y);
  1673. y = sdsdup(x);
  1674. sdsrange(y,100,100);
  1675. test_cond("sdsrange(...,100,100)",
  1676. sdslen(y) == 0 && memcmp(y,"\0",1) == 0);
  1677. sdsfree(y);
  1678. y = sdsdup(x);
  1679. sdsrange(y,4,6);
  1680. test_cond("sdsrange(...,4,6)",
  1681. sdslen(y) == 0 && memcmp(y,"\0",1) == 0);
  1682. sdsfree(y);
  1683. y = sdsdup(x);
  1684. sdsrange(y,3,6);
  1685. test_cond("sdsrange(...,3,6)",
  1686. sdslen(y) == 1 && memcmp(y,"o\0",2) == 0);
  1687. sdsfree(y);
  1688. sdsfree(x);
  1689. x = sdsnew("foo");
  1690. y = sdsnew("foa");
  1691. test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0);
  1692. sdsfree(y);
  1693. sdsfree(x);
  1694. x = sdsnew("bar");
  1695. y = sdsnew("bar");
  1696. test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0);
  1697. sdsfree(y);
  1698. sdsfree(x);
  1699. x = sdsnew("aar");
  1700. y = sdsnew("bar");
  1701. test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0);
  1702. sdsfree(y);
  1703. sdsfree(x);
  1704. x = sdsnewlen("\a\n\0foo\r",7);
  1705. y = sdscatrepr(sdsempty(),x,sdslen(x));
  1706. test_cond("sdscatrepr(...data...)",
  1707. memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0);
  1708. {
  1709. unsigned int oldfree;
  1710. char *p;
  1711. int i;
  1712. size_t step = 10, j;
  1713. sdsfree(x);
  1714. sdsfree(y);
  1715. x = sdsnew("0");
  1716. test_cond("sdsnew() free/len buffers", sdslen(x) == 1 && sdsavail(x) == 0);
  1717. /* Run the test a few times in order to hit the first two
  1718. * SDS header types. */
  1719. for (i = 0; i < 10; i++) {
  1720. size_t oldlen = sdslen(x);
  1721. x = sdsMakeRoomFor(x,step);
  1722. int type = x[-1]&SDS_TYPE_MASK;
  1723. test_cond("sdsMakeRoomFor() len", sdslen(x) == oldlen);
  1724. if (type != SDS_TYPE_5) {
  1725. test_cond("sdsMakeRoomFor() free", sdsavail(x) >= step);
  1726. oldfree = sdsavail(x);
  1727. UNUSED(oldfree);
  1728. }
  1729. p = x+oldlen;
  1730. for (j = 0; j < step; j++) {
  1731. p[j] = 'A'+j;
  1732. }
  1733. sdsIncrLen(x,step);
  1734. }
  1735. test_cond("sdsMakeRoomFor() content",
  1736. memcmp("0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ",x,101) == 0);
  1737. test_cond("sdsMakeRoomFor() final length",sdslen(x)==101);
  1738. sdsfree(x);
  1739. }
  1740. /* Simple template */
  1741. x = sdstemplate("v1={variable1} v2={variable2}", sdsTestTemplateCallback, NULL);
  1742. test_cond("sdstemplate() normal flow",
  1743. memcmp(x,"v1=value1 v2=value2",19) == 0);
  1744. sdsfree(x);
  1745. /* Template with callback error */
  1746. x = sdstemplate("v1={variable1} v3={doesnotexist}", sdsTestTemplateCallback, NULL);
  1747. test_cond("sdstemplate() with callback error", x == NULL);
  1748. /* Template with empty var name */
  1749. x = sdstemplate("v1={", sdsTestTemplateCallback, NULL);
  1750. test_cond("sdstemplate() with empty var name", x == NULL);
  1751. /* Template with truncated var name */
  1752. x = sdstemplate("v1={start", sdsTestTemplateCallback, NULL);
  1753. test_cond("sdstemplate() with truncated var name", x == NULL);
  1754. /* Template with quoting */
  1755. x = sdstemplate("v1={{{variable1}} {{} v2={variable2}", sdsTestTemplateCallback, NULL);
  1756. test_cond("sdstemplate() with quoting",
  1757. memcmp(x,"v1={value1} {} v2=value2",24) == 0);
  1758. sdsfree(x);
  1759. }
  1760. test_report();
  1761. return 0;
  1762. }
  1763. #endif