Home | History | Annotate | Download | only in util
      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
    195