1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
| ```
//创建新的字符串
sds sdsnewlen(const void *init, size_t initlen) {
void *sh;
sds s;
//根据长度获取sds的类型
char type = sdsReqType(initlen);
/* Empty strings are usually created in order to append. Use type 8
* since type 5 is not good at this. */
//sds_type_5这个类型是不会使用的啦.
if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
//根据类型得到头部的长度,还记得前面的类型声明吗?
int hdrlen = sdsHdrSize(type);
unsigned char *fp; /* flags pointer. */
//分配空间: 头部大小+数据大小+'\0'(空终止符,为了c语言字符串兼容)
sh = s_malloc(hdrlen+initlen+1);
//如果没有初始化数据之间全部清空
if (!init)
memset(sh, 0, hdrlen+initlen+1);
if (sh == NULL) return NULL;
//s指向buf, 返回的sds就是这个s
s = (char*)sh+hdrlen;
fp = ((unsigned char*)s)-1;
switch(type) {
case SDS_TYPE_5: {
//记得吗?对于SDS_TYPE_5类型,长度是放在flags字段里的
*fp = type | (initlen << SDS_TYPE_BITS);
break;
}
case SDS_TYPE_8: {
//这里是新定义了一个相对应类型的sh
SDS_HDR_VAR(8,s);
//设置长度
sh->len = initlen;
//设置分配的大小(排查头部跟空终止符)
sh->alloc = initlen;
//设置类型
*fp = type;
break;
}
case SDS_TYPE_16: {
SDS_HDR_VAR(16,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
case SDS_TYPE_32: {
SDS_HDR_VAR(32,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
case SDS_TYPE_64: {
SDS_HDR_VAR(64,s);
sh->len = initlen;
sh->alloc = initlen;
*fp = type;
break;
}
}
//如果有初始化值,则执行memcpy复制数据
if (initlen && init)
memcpy(s, init, initlen);
//设置终止符,这里并不会有两个'\0',因为前面只复制了initlen个字符
s[initlen] = '\0';
//返回sds,实际执行buf
return s;
}
void sdsfree(sds s) {
if (s == NULL) return;
//得到真正的头部指向,然后释放
s_free((char*)s-sdsHdrSize(s[-1]));
}
//字符串增长
sds sdsMakeRoomFor(sds s, size_t addlen) {
void *sh, *newsh;
//获取剩余的空间,其实就是alloc-len
size_t avail = sdsavail(s);
size_t len, newlen;
//保持老的类型,因为字符串空间加长后有可能类型变化
char type, oldtype = s[-1] & SDS_TYPE_MASK;
int hdrlen;
/* Return ASAP if there is enough space left. */
//如果空间足够直接返回
if (avail >= addlen) return s;
len = sdslen(s);
sh = (char*)s-sdsHdrSize(oldtype);
newlen = (len+addlen);
//如果小于1024*1024直接翻倍空间
if (newlen < SDS_MAX_PREALLOC)
newlen *= 2;
else
newlen += SDS_MAX_PREALLOC;
//根据长度获取sds的类型
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) {
//如果类型不变
newsh = s_realloc(sh, hdrlen+newlen+1);
if (newsh == NULL) return NULL;
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) return NULL;
//复制数据
memcpy((char*)newsh+hdrlen, s, len+1);
//释放老的数据
s_free(sh);
s = (char*)newsh+hdrlen;
//设置类型s[-1]实际执行flags
s[-1] = type;
//设置新字符串的长度
sdssetlen(s, len);
}
//设置新字符串分配空间大小
sdssetalloc(s, newlen);
return s;
}
```
|