intset数据结构
typedef struct intset {
uint32_t encoding;//编码方式 2字节 4字节 8字节
uint32_t length;//长度
int8_t contents[];//数据数组
} intset;
主要api
intset *intsetNew(void);//创建一个空的 intset
intset *intsetAdd(intset *is, int64_t value, uint8_t *success);//添加一个 数据
intset *intsetRemove(intset *is, int64_t value, int *success);//移除一个数据
uint8_t intsetFind(intset *is, int64_t value);//查找这个值是否属于 intset
int64_t intsetRandom(intset *is);//随机返回一个intset中的数据
uint8_t intsetGet(intset *is, uint32_t pos, int64_t *value);//返回某个位置上的数据
uint32_t intsetLen(const intset *is);//返回intset数据的个数
size_t intsetBlobLen(intset *is);//intset所有数据所占内存的大小
intset的精华就是intsetAdd函数下面对它解析
intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {
uint8_t valenc = _intsetValueEncoding(value);//正确的编码方式 16位 32位 64位
uint32_t pos;
if (success) *success = 1;
if (valenc > intrev32ifbe(is->encoding)) {//如果目前编码大小无法存储value 需要重新分配内存
return intsetUpgradeAndAdd(is,value);//重新分配内存 并 插入数据
} else {
if (intsetSearch(is,value,&pos)) {//如果intset中有此数据 直接返回
if (success) *success = 0;
return is;
}
is = intsetResize(is,intrev32ifbe(is->length)+1);//如果没有 realloc内存
if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);//将pos位置以及往后的数据向后平移一位
}
_intsetSet(is,pos,value);//pos位置插入数据
is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
return is;
}
static intset *intsetUpgradeAndAdd(intset *is, int64_t value) {
//既然走进这个函数 那么value 必然是插到intset的头部或者尾部的
uint8_t curenc = intrev32ifbe(is->encoding);
uint8_t newenc = _intsetValueEncoding(value);
int length = intrev32ifbe(is->length);
int prepend = value < 0 ? 1 : 0;
is->encoding = intrev32ifbe(newenc);
is = intsetResize(is,intrev32ifbe(is->length)+1);
while(length--)//从后向前复制数据
_intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));
if (prepend)//判断插入头部还是尾部
_intsetSet(is,0,value);
else
_intsetSet(is,intrev32ifbe(is->length),value);
is->length = intrev32ifbe(intrev32ifbe(is->length)+1);//更新数据个数
return is;
}