github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/src/coding.cc (about)

     1  // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file. See the AUTHORS file for names of contributors.
     4  
     5  #include "util/coding.h"
     6  
     7  namespace leveldb {
     8  
     9  void EncodeFixed32(char* buf, uint32_t value) {
    10    if (port::kLittleEndian) {
    11      memcpy(buf, &value, sizeof(value));
    12    } else {
    13      buf[0] = value & 0xff;
    14      buf[1] = (value >> 8) & 0xff;
    15      buf[2] = (value >> 16) & 0xff;
    16      buf[3] = (value >> 24) & 0xff;
    17    }
    18  }
    19  
    20  void EncodeFixed64(char* buf, uint64_t value) {
    21    if (port::kLittleEndian) {
    22      memcpy(buf, &value, sizeof(value));
    23    } else {
    24      buf[0] = value & 0xff;
    25      buf[1] = (value >> 8) & 0xff;
    26      buf[2] = (value >> 16) & 0xff;
    27      buf[3] = (value >> 24) & 0xff;
    28      buf[4] = (value >> 32) & 0xff;
    29      buf[5] = (value >> 40) & 0xff;
    30      buf[6] = (value >> 48) & 0xff;
    31      buf[7] = (value >> 56) & 0xff;
    32    }
    33  }
    34  
    35  void PutFixed32(std::string* dst, uint32_t value) {
    36    char buf[sizeof(value)];
    37    EncodeFixed32(buf, value);
    38    dst->append(buf, sizeof(buf));
    39  }
    40  
    41  void PutFixed64(std::string* dst, uint64_t value) {
    42    char buf[sizeof(value)];
    43    EncodeFixed64(buf, value);
    44    dst->append(buf, sizeof(buf));
    45  }
    46  
    47  char* EncodeVarint32(char* dst, uint32_t v) {
    48    // Operate on characters as unsigneds
    49    unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
    50    static const int B = 128;
    51    if (v < (1<<7)) {
    52      *(ptr++) = v;
    53    } else if (v < (1<<14)) {
    54      *(ptr++) = v | B;
    55      *(ptr++) = v>>7;
    56    } else if (v < (1<<21)) {
    57      *(ptr++) = v | B;
    58      *(ptr++) = (v>>7) | B;
    59      *(ptr++) = v>>14;
    60    } else if (v < (1<<28)) {
    61      *(ptr++) = v | B;
    62      *(ptr++) = (v>>7) | B;
    63      *(ptr++) = (v>>14) | B;
    64      *(ptr++) = v>>21;
    65    } else {
    66      *(ptr++) = v | B;
    67      *(ptr++) = (v>>7) | B;
    68      *(ptr++) = (v>>14) | B;
    69      *(ptr++) = (v>>21) | B;
    70      *(ptr++) = v>>28;
    71    }
    72    return reinterpret_cast<char*>(ptr);
    73  }
    74  
    75  void PutVarint32(std::string* dst, uint32_t v) {
    76    char buf[5];
    77    char* ptr = EncodeVarint32(buf, v);
    78    dst->append(buf, ptr - buf);
    79  }
    80  
    81  char* EncodeVarint64(char* dst, uint64_t v) {
    82    static const int B = 128;
    83    unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
    84    while (v >= B) {
    85      *(ptr++) = (v & (B-1)) | B;
    86      v >>= 7;
    87    }
    88    *(ptr++) = static_cast<unsigned char>(v);
    89    return reinterpret_cast<char*>(ptr);
    90  }
    91  
    92  void PutVarint64(std::string* dst, uint64_t v) {
    93    char buf[10];
    94    char* ptr = EncodeVarint64(buf, v);
    95    dst->append(buf, ptr - buf);
    96  }
    97  
    98  void PutLengthPrefixedSlice(std::string* dst, const Slice& value) {
    99    PutVarint32(dst, value.size());
   100    dst->append(value.data(), value.size());
   101  }
   102  
   103  int VarintLength(uint64_t v) {
   104    int len = 1;
   105    while (v >= 128) {
   106      v >>= 7;
   107      len++;
   108    }
   109    return len;
   110  }
   111  
   112  const char* GetVarint32PtrFallback(const char* p,
   113                                     const char* limit,
   114                                     uint32_t* value) {
   115    uint32_t result = 0;
   116    for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
   117      uint32_t byte = *(reinterpret_cast<const unsigned char*>(p));
   118      p++;
   119      if (byte & 128) {
   120        // More bytes are present
   121        result |= ((byte & 127) << shift);
   122      } else {
   123        result |= (byte << shift);
   124        *value = result;
   125        return reinterpret_cast<const char*>(p);
   126      }
   127    }
   128    return NULL;
   129  }
   130  
   131  bool GetVarint32(Slice* input, uint32_t* value) {
   132    const char* p = input->data();
   133    const char* limit = p + input->size();
   134    const char* q = GetVarint32Ptr(p, limit, value);
   135    if (q == NULL) {
   136      return false;
   137    } else {
   138      *input = Slice(q, limit - q);
   139      return true;
   140    }
   141  }
   142  
   143  const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) {
   144    uint64_t result = 0;
   145    for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) {
   146      uint64_t byte = *(reinterpret_cast<const unsigned char*>(p));
   147      p++;
   148      if (byte & 128) {
   149        // More bytes are present
   150        result |= ((byte & 127) << shift);
   151      } else {
   152        result |= (byte << shift);
   153        *value = result;
   154        return reinterpret_cast<const char*>(p);
   155      }
   156    }
   157    return NULL;
   158  }
   159  
   160  bool GetVarint64(Slice* input, uint64_t* value) {
   161    const char* p = input->data();
   162    const char* limit = p + input->size();
   163    const char* q = GetVarint64Ptr(p, limit, value);
   164    if (q == NULL) {
   165      return false;
   166    } else {
   167      *input = Slice(q, limit - q);
   168      return true;
   169    }
   170  }
   171  
   172  const char* GetLengthPrefixedSlice(const char* p, const char* limit,
   173                                     Slice* result) {
   174    uint32_t len;
   175    p = GetVarint32Ptr(p, limit, &len);
   176    if (p == NULL) return NULL;
   177    if (p + len > limit) return NULL;
   178    *result = Slice(p, len);
   179    return p + len;
   180  }
   181  
   182  bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
   183    uint32_t len;
   184    if (GetVarint32(input, &len) &&
   185        input->size() >= len) {
   186      *result = Slice(input->data(), len);
   187      input->remove_prefix(len);
   188      return true;
   189    } else {
   190      return false;
   191    }
   192  }
   193  
   194  }  // namespace leveldb