Leveldb源碼分析--2

3 Int Coding

輕鬆一刻,前面約定中講過Leveldb使用了很多VarInt型編碼,典型的如後面將涉及到的各種key。其中的編碼、解碼函數分爲VarInt和FixedInt兩種。int32和int64操作都是類似的。

3.1 Decode

首先是FixedInt編碼,直接上代碼,很簡單明瞭。

void EncodeFixed32(char* buf, uint32_t value)

{

  if (port::kLittleEndian) {

    memcpy(buf, &value,sizeof(value));

  } else {

    buf[0] = value & 0xff;

    buf[1] = (value >> 8)& 0xff;

    buf[2] = (value >> 16)& 0xff;

    buf[3] = (value >> 24)& 0xff;

  }

}

下面是VarInt編碼,int32和int64格式,代碼如下,有效位是7bit的,因此把uint32按7bit分割,對unsigned char賦值時,超出0xFF會自動截斷,因此直接*(ptr++) = v|B即可,不需要再把(v|B)與0xFF作&操作。

char* EncodeVarint32(char* dst, uint32_t v)

{

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

  static const int B = 128;

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

    *(ptr++) = v;

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

}

char* EncodeVarint64(char* dst, uint64_t v) {// 對於uint64,直接循環

  static const int B = 128;

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

  while (v >= B) {

    *(ptr++) = (v & (B-1)) |B;

    v >>= 7;

  }

  *(ptr++) =static_cast<unsigned char>(v);

  returnreinterpret_cast<char*>(ptr);

}

3.2 Decode

Fixed Int的Decode,操作,代碼:

inline uint32_t DecodeFixed32(const char* ptr)

{

  if (port::kLittleEndian) {

    uint32_t result;

    memcpy(&result, ptr,sizeof(result));  // gcc optimizes this to a plain load

    return result;

  } else {

    return((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))

        |(static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) <<8)

        | (static_cast<uint32_t>(static_cast<unsignedchar>(ptr[2])) << 16)

        |(static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) <<24));

  }

}

再來看看VarInt的解碼,很簡單,依次讀取1byte,直到最高位爲0的byte結束,取低7bit,作(<<7)移位操作組合成Int。看代碼:

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;

      returnreinterpret_cast<const char*>(p);

    }

  }

  return NULL;

}

發佈了90 篇原創文章 · 獲贊 99 · 訪問量 164萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章