💡 核心设计思想
- len 字段:记录已用长度,O(1) 获取字符串长度
- alloc 字段:记录已分配空间,支持惰性释放
- flags 字段:低 3 位标识类型,高位存储短长度
- 二进制安全:不依赖 \0 结尾,可存储任意字节
- 空间预分配:小于 1MB 时翻倍扩容,大于 1MB 时每次 +1MB
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len;
uint8_t alloc;
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
uint16_t len;
uint16_t alloc;
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len;
uint32_t alloc;
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
uint64_t len;
uint64_t alloc;
unsigned char flags;
char buf[];
};
#define SDS_TYPE_5 0
#define SDS_TYPE_8 1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4
#define SDS_TYPE_MASK 7
#define SDS_MAX_PREALLOC (1024*1024)
#define SDS_HDR(T, s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
static inline size_t sdslen(const sds s) {
unsigned char flags = s[-1];
switch(flags & SDS_TYPE_MASK) {
case SDS_TYPE_5: return SDS_TYPE_5_LEN(flags);
case SDS_TYPE_8: return SDS_HDR(8,s)->len;
case SDS_TYPE_16: return SDS_HDR(16,s)->len;
case SDS_TYPE_32: return SDS_HDR(32,s)->len;
case SDS_TYPE_64: return SDS_HDR(64,s)->len;
}
return 0;
}
static inline size_t sdsavail(const sds s) {
unsigned char flags = s[-1];
switch(flags & SDS_TYPE_MASK) {
case SDS_TYPE_8: {
SDS_HDR_VAR(8,s);
return sh->alloc - sh->len;
}
}
return 0;
}
📐 sdshdr8 内存布局示例("Hello")
buf[]
'H' 'e' 'l' 'l' 'o' '\0'
内存地址: ... | 05 | 08 | 01 | 48 | 65 | 6c | 6c | 6f | 00 | .. | ..
类型选择策略
- • len ≤ 31 → sdshdr5 (未使用)
- • len ≤ 255 → sdshdr8
- • len ≤ 65535 → sdshdr16
- • len ≤ 2³² → sdshdr32
- • len > 2³² → sdshdr64
空间预分配规则
- • alloc-len < 1MB: 新空间 = len * 2
- • alloc-len ≥ 1MB: 新空间 = len + 1MB
- • 最大预分配: 1MB
- • 惰性释放: 缩短时不立即回收