主要是区别

  1. sdshdr

    不是单一的sdshdr结构,而是分了sdshdr5,sdshdr8,sdshdr16,sdshdr32,sdshdr64几种.鉴于对__attribute__的浅陋理解,是对某种结构属性的定义,也就是说可以当作同一个结构,然后在不同的场景,赋予了不同的结构属性.然后主要用flags的前三位(5种类型)来判断使用的是那种属性结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 这个不存在使用场景,只是给出理论上的属性结构
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};

// 其他几种字段相同,但是len和alloc的类型结构跟着名称变
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* used */
// 这里是总分配,书中是`free`,这里`free`用`sdsavail`计算得到
uint8_t alloc; /* excluding the header and null terminator */
// 多出来的类型标志
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
  1. #define SDS_MAX_PREALLOC (1024*1024)

    这是重分配的1M空间临界定义字段

  2. sdsReqType

    这个函数没什么特殊的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
tatic inline char sdsReqType(size_t string_size) {
if (string_size < 1<<5)
return SDS_TYPE_5;
if (string_size < 1<<8)
return SDS_TYPE_8;
if (string_size < 1<<16)
return SDS_TYPE_16;
// LONG_MAX大概是系统位数决定的最大数
// LLONG_MAX大概是固定的64位最大数
// 所以就是判断是32位还是64位的意思
#if (LONG_MAX == LLONG_MAX)
if (string_size < 1ll<<32)
return SDS_TYPE_32;
return SDS_TYPE_64;
#else // 所以如果是32位系统就没有使用sdshdr64一说了
return SDS_TYPE_32;
#endif
}
  1. sdsnewlen

    这个函数是主要功能,其他的很多函数都是调用它实现的

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
sds sdsnewlen(const void *init, size_t initlen) {
void *sh;
sds s;
char type = sdsReqType(initlen);
/* Empty strings are usually created in order to append. Use type 8
* since type 5 is not good at this. */
// sdshdr5没有被使用的原因所在
if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
int hdrlen = sdsHdrSize(type);
unsigned char *fp; /* flags pointer. */

// 结构长度+buf长度+1(空格),没问题
// buf和结构的地址是连在一起的,一起分配
sh = s_malloc(hdrlen+initlen+1);
if (init==SDS_NOINIT)
init = NULL;
else if (!init)
// 初始化,sh设置成hdrlen+initlen+1)个字节长的0
memset(sh, 0, hdrlen+initlen+1);
if (sh == NULL) return NULL;
// 这个是s要指向buf的意思
s = (char*)sh+hdrlen;

// flag pointer
// 指针前移1位,说明flags也只是占用一个字节
fp = ((unsigned char*)s)-1;
switch(type) {
case SDS_TYPE_5: {
// flags记录长度的时候用的是高5位
*fp = type | (initlen << SDS_TYPE_BITS);
break;
}
case SDS_TYPE_8: {
SDS_HDR_VAR(8,s); // 这个大概就是指针指向sdshdr结构
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;
}
}
if (initlen && init)
memcpy(s, init, initlen); // 把init的值copy到s去
s[initlen] = '\0'; // 结尾 \0
return s;
}


5. sdsMakeRoomFor

``` c
sds sdsMakeRoomFor(sds s, size_t addlen) {
void *sh, *newsh;
size_t avail = sdsavail(s);
size_t len, newlen;
// 反正这个s[-1]是取到了flags的值
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);
// sdshdr指针
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. */
// 避免使用sdshdr5
if (type == SDS_TYPE_5) type = SDS_TYPE_8;

hdrlen = sdsHdrSize(type);
if (oldtype==type) {
// 如果类型没有改变,直接给sh重新分配新空间
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
s = (char*)newsh+hdrlen;
// 重新定义s类型,即flags
s[-1] = type;
// 重新设置长度(会根据类型重新构建属性)
sdssetlen(s, len);
}
// 重新设置已分配长度
sdssetalloc(s, newlen);
return s;
}