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;
}

 

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