text: // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file. See the AUTHORS file for names of contributors.
  
  #include "util/coding.h"
  
  namespace leveldb {
  
  void PutFixed32(std::string* dst, uint32_t value) {
    char buf[sizeof(value)];
    EncodeFixed32(buf, value);
    dst->append(buf, sizeof(buf));
  }
  
  void PutFixed64(std::string* dst, uint64_t value) {
    char buf[sizeof(value)];
    EncodeFixed64(buf, value);
    dst->append(buf, sizeof(buf));
  }
  
  //变长存储  
  char* EncodeVarint32(char* dst, uint32_t v) {
    // Operate on characters as unsigneds
    uint8_t* ptr = reinterpret_cast<uint8_t*>(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);
  }
  
  void PutVarint32(std::string* dst, uint32_t v) {
    char buf[5];
    char* ptr = EncodeVarint32(buf, v);
    dst->append(buf, ptr - buf);
  }
  
  char* EncodeVarint64(char* dst, uint64_t v) {
    static const int B = 128;
    uint8_t* ptr = reinterpret_cast<uint8_t*>(dst);
    while (v >= B) {
      *(ptr++) = v | B;
      v >>= 7;
    }
    *(ptr++) = static_cast<uint8_t>(v);
    return reinterpret_cast<char*>(ptr);
  }
  
  void PutVarint64(std::string* dst, uint64_t v) {
    char buf[10];
    char* ptr = EncodeVarint64(buf, v);
    dst->append(buf, ptr - buf);
  }
  
  void PutLengthPrefixedSlice(std::string* dst, const Slice& value) {
    PutVarint32(dst, value.size());
    dst->append(value.data(), value.size());
  }
  
  int VarintLength(uint64_t v) {
    int len = 1;
    while (v >= 128) {
      v >>= 7;
      len++;
    }
    return len;
  }
  
  const char* GetVarint32PtrFallback(const char* p, const char* limit,
                                     uint32_t* value) {
    /*
      对于超过一个字节的长度编码，解码的过程就是按小端顺序，
      每7位取出，然后移位来组装最后的实际长度，组装结束的表示就是MSB位为0
    */                                   
    uint32_t result = 0;
    for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
      uint32_t byte = *(reinterpret_cast<const uint8_t*>(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 nullptr;
  }
  
  // 解码就是编码的逆过程，这里涉及到对Slice数据的解析
  bool GetVarint32(Slice* input, uint32_t* value) {
    const char* p = input->data();
    const char* limit = p + input->size();
    const char* q = GetVarint32Ptr(p, limit, value);
    if (q == nullptr) {
      return false;
    } else {
      *input = Slice(q, limit - q);
      return true;
    }
  }
  
  const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) {
    uint64_t result = 0;
    for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) {
      uint64_t byte = *(reinterpret_cast<const uint8_t*>(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 nullptr;
  }
  
  bool GetVarint64(Slice* input, uint64_t* value) {
    const char* p = input->data();
    const char* limit = p + input->size();
    //对input的下标做更新。
    const char* q = GetVarint64Ptr(p, limit, value);
    if (q == nullptr) {
      return false;
    } else {
      //对input的下标做更新。input变了
      *input = Slice(q, limit - q);
      return true;
    }
  }
  
  const char* GetLengthPrefixedSlice(const char* p, const char* limit,
                                     Slice* result) {
    uint32_t len;
    p = GetVarint32Ptr(p, limit, &len);
    if (p == nullptr) return nullptr;
    if (p + len > limit) return nullptr;
    *result = Slice(p, len);
    return p + len;
  }
  
  bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
    uint32_t len;
    if (GetVarint32(input, &len) && input->size() >= len) {
      *result = Slice(input->data(), len);
      input->remove_prefix(len);
      return true;
    } else {
      return false;
    }
  }
  
  }  // namespace leveldb
  