Redis-压缩表-ziplistIndex详解

/* 返回压缩表zl的第index个结点,
index为非负:从表头开始查找,0表示返回第一个结点
index为负:从表尾开始查找,-1表示返回最后一个结点
*/
unsigned char *ziplistIndex(unsigned char *zl, int index) {
    unsigned char *p; /* 保存目标结点地址 */
    zlentry entry; /* 未对改变量进行初始化,考虑到该变量会被函数zipEntry返回值直接赋值,可以原谅未初始化 */

    if (index < 0) {
        /* 将索引转换为正数,因为负数索引从-1开始,所以转换为正数之后索引值-1,
           保证索引为-1,通过计算获得索引是0,指向的是从表尾开始查找时的最后一个结点 */
        index = (-index) - 1;

        /* p指向表尾结点,即最后一个结点 */
        p = ZIPLIST_ENTRY_TAIL(zl);

        /* 如果压缩表不为空 */
        if (p[0] != ZIP_END) {
            entry = zipEntry(p); /* 只有列表不为空时,p才指向一个结点,才能获得p指向的结点信息entry */

            /* 通过遍历index次获得指定索引的结点 */
            /* prevrawlen:前置结点的长度 */
            while (entry.prevrawlen > 0 && index--) {
                p -= entry.prevrawlen;
                entry = zipEntry(p); /* 必须确保前置结点长度大于0(entry.prevrawlen > 0),该操作才有意义 */
            }
        }
    } else {
        /* 获得压缩表的第一个结点指针 */
        p = ZIPLIST_ENTRY_HEAD(zl);

        /* 通过遍历index次获得指定索引的结点 */
        /* p[0] != ZIP_END:保证p执行的结点是有效结点 */
        while (p[0] != ZIP_END && index--) {
            p += zipRawEntryLength(p); /* 函数zipRawEntryLength功能:返回p指向的结点占用的字节长度 */
        }
    }

    /* p[0] == ZIP_END:指定的索引值大于0时查找,查找到表尾,还没有查找到指定索引的结点,
       或者p[0] == ZIP_END的同时,index=0,此时索引值大于压缩表的结点数,仍然返回NULL;
       index > 0:指定的索引值小于0时查找,已经到表头,index仍然大于0,说明指定的索引值超出压缩表的索引范围*/
    return (p[0] == ZIP_END || index > 0) ? NULL : p;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章