varint-levelDB源碼解析

【什麼是變長整型?】

大家知道,int整型一般是4個字節,那變長整型所需要的空間在1-5個字節之間,因爲長度是不固定的,所以稱之爲變長整型。其特點就是隻要數值小於2^21,那麼就會節省空間。

【編碼原理】


如圖所示爲300,編碼後的字節圖,只佔了2個字節。這是怎麼實現的呢?請看下面的詳解:

300的二進制編碼爲00000000 00000000 00000001 00101100,從低位到高位,每次取7位,如果能取完,最高位補0,表示這個數字已經表示完整了,如果不是,最高位補1,表示這個數字還沒表示完整。由於存儲的每個字節的最高位用來標識有沒有結束,所以實際上每個字節只用了7位來表示數字,這也是爲什麼最多需要5個字節來表示的原因,4*7 < 32, 5*7 > 32.

【代碼實現】

編碼:

  char* EncodeVarint32(char* dst, uint32_t v) {

    // Operate on characters as unsigneds

    unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);

    static const int B = 128;

    if (v < (1<<7)) {

      *(ptr++) = v;           //先給*ptr的內存賦值v,然後ptr指針向右移一位

    } else if (v < (1<<14)) {

      *(ptr++) = v | B;

      *(ptr++) = v>>7;

    } else if (v < (1<<21)) {

      *(ptr++) = v | B;

      *(ptr++) = (v>>7) | B;

      *(ptr++) = v>>14;

    } else if (v < (1<<28)) {

      *(ptr++) = v | B;

      *(ptr++) = (v>>7) | B;

      *(ptr++) = (v>>14) | B;

      *(ptr++) = v>>21;

    } else {

      *(ptr++) = v | B;

      *(ptr++) = (v>>7) | B;

      *(ptr++) = (v>>14) | B;

      *(ptr++) = (v>>21) | B;

      *(ptr++) = v>>28;

    }

    return reinterpret_cast<char*>(ptr);

  }


解碼:

  inline const char* GetVarint32Ptr(const char* p,

                                    const char* limit,

                                    uint32_t* value) {

    if (p < limit) {

      uint32_t result = *(reinterpret_cast<const unsigned char*>(p));

      if ((result & 128) == 0) {

        *value = result;

        return p + 1;

      }

    }

    return GetVarint32PtrFallback(p, limit, value);

  }




  const char* GetVarint32PtrFallback(const char* p,                                                                                                          

                                     const char* limit,

                                     uint32_t* value) {

    uint32_t result = 0;

    for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {

      uint32_t byte = *(reinterpret_cast<const unsigned char*>(p));

      p++;

      if (byte & 128) {

        // More bytes are present

        result |= ((byte & 127) << shift);

      } else { 

        result |= (byte << shift);

        *value = result;

        return reinterpret_cast<const char*>(p);

      }

    }

    return NULL;

  }

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