coding.cc
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 PutFixed32(std::string* dst, uint32_t value) { 10 char buf[sizeof(value)]; 11 EncodeFixed32(buf, value); 12 dst->append(buf, sizeof(buf)); 13 } 14 15 void PutFixed64(std::string* dst, uint64_t value) { 16 char buf[sizeof(value)]; 17 EncodeFixed64(buf, value); 18 dst->append(buf, sizeof(buf)); 19 } 20 21 char* EncodeVarint32(char* dst, uint32_t v) { 22 // Operate on characters as unsigneds 23 uint8_t* ptr = reinterpret_cast<uint8_t*>(dst); 24 static const int B = 128; 25 if (v < (1 << 7)) { 26 *(ptr++) = v; 27 } else if (v < (1 << 14)) { 28 *(ptr++) = v | B; 29 *(ptr++) = v >> 7; 30 } else if (v < (1 << 21)) { 31 *(ptr++) = v | B; 32 *(ptr++) = (v >> 7) | B; 33 *(ptr++) = v >> 14; 34 } else if (v < (1 << 28)) { 35 *(ptr++) = v | B; 36 *(ptr++) = (v >> 7) | B; 37 *(ptr++) = (v >> 14) | B; 38 *(ptr++) = v >> 21; 39 } else { 40 *(ptr++) = v | B; 41 *(ptr++) = (v >> 7) | B; 42 *(ptr++) = (v >> 14) | B; 43 *(ptr++) = (v >> 21) | B; 44 *(ptr++) = v >> 28; 45 } 46 return reinterpret_cast<char*>(ptr); 47 } 48 49 void PutVarint32(std::string* dst, uint32_t v) { 50 char buf[5]; 51 char* ptr = EncodeVarint32(buf, v); 52 dst->append(buf, ptr - buf); 53 } 54 55 char* EncodeVarint64(char* dst, uint64_t v) { 56 static const int B = 128; 57 uint8_t* ptr = reinterpret_cast<uint8_t*>(dst); 58 while (v >= B) { 59 *(ptr++) = v | B; 60 v >>= 7; 61 } 62 *(ptr++) = static_cast<uint8_t>(v); 63 return reinterpret_cast<char*>(ptr); 64 } 65 66 void PutVarint64(std::string* dst, uint64_t v) { 67 char buf[10]; 68 char* ptr = EncodeVarint64(buf, v); 69 dst->append(buf, ptr - buf); 70 } 71 72 void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { 73 PutVarint32(dst, value.size()); 74 dst->append(value.data(), value.size()); 75 } 76 77 int VarintLength(uint64_t v) { 78 int len = 1; 79 while (v >= 128) { 80 v >>= 7; 81 len++; 82 } 83 return len; 84 } 85 86 const char* GetVarint32PtrFallback(const char* p, const char* limit, 87 uint32_t* value) { 88 uint32_t result = 0; 89 for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { 90 uint32_t byte = *(reinterpret_cast<const uint8_t*>(p)); 91 p++; 92 if (byte & 128) { 93 // More bytes are present 94 result |= ((byte & 127) << shift); 95 } else { 96 result |= (byte << shift); 97 *value = result; 98 return reinterpret_cast<const char*>(p); 99 } 100 } 101 return nullptr; 102 } 103 104 bool GetVarint32(Slice* input, uint32_t* value) { 105 const char* p = input->data(); 106 const char* limit = p + input->size(); 107 const char* q = GetVarint32Ptr(p, limit, value); 108 if (q == nullptr) { 109 return false; 110 } else { 111 *input = Slice(q, limit - q); 112 return true; 113 } 114 } 115 116 const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { 117 uint64_t result = 0; 118 for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { 119 uint64_t byte = *(reinterpret_cast<const uint8_t*>(p)); 120 p++; 121 if (byte & 128) { 122 // More bytes are present 123 result |= ((byte & 127) << shift); 124 } else { 125 result |= (byte << shift); 126 *value = result; 127 return reinterpret_cast<const char*>(p); 128 } 129 } 130 return nullptr; 131 } 132 133 bool GetVarint64(Slice* input, uint64_t* value) { 134 const char* p = input->data(); 135 const char* limit = p + input->size(); 136 const char* q = GetVarint64Ptr(p, limit, value); 137 if (q == nullptr) { 138 return false; 139 } else { 140 *input = Slice(q, limit - q); 141 return true; 142 } 143 } 144 145 const char* GetLengthPrefixedSlice(const char* p, const char* limit, 146 Slice* result) { 147 uint32_t len; 148 p = GetVarint32Ptr(p, limit, &len); 149 if (p == nullptr) return nullptr; 150 if (p + len > limit) return nullptr; 151 *result = Slice(p, len); 152 return p + len; 153 } 154 155 bool GetLengthPrefixedSlice(Slice* input, Slice* result) { 156 uint32_t len; 157 if (GetVarint32(input, &len) && input->size() >= len) { 158 *result = Slice(input->data(), len); 159 input->remove_prefix(len); 160 return true; 161 } else { 162 return false; 163 } 164 } 165 166 } // namespace leveldb