Line data Source code
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 13921 : 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 13921 : }
19 :
20 107713 : 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 107713 : }
34 :
35 4015 : void PutFixed32(std::string* dst, uint32_t value) {
36 : char buf[sizeof(value)];
37 : EncodeFixed32(buf, value);
38 4015 : dst->append(buf, sizeof(buf));
39 4015 : }
40 :
41 512 : void PutFixed64(std::string* dst, uint64_t value) {
42 : char buf[sizeof(value)];
43 : EncodeFixed64(buf, value);
44 512 : dst->append(buf, sizeof(buf));
45 512 : }
46 :
47 176660 : char* EncodeVarint32(char* dst, uint32_t v) {
48 : // Operate on characters as unsigneds
49 176660 : unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
50 : static const int B = 128;
51 176660 : if (v < (1<<7)) {
52 176632 : *(ptr++) = v;
53 28 : } else if (v < (1<<14)) {
54 20 : *(ptr++) = v | B;
55 20 : *(ptr++) = v>>7;
56 8 : } else if (v < (1<<21)) {
57 8 : *(ptr++) = v | B;
58 8 : *(ptr++) = (v>>7) | B;
59 8 : *(ptr++) = v>>14;
60 0 : } else if (v < (1<<28)) {
61 0 : *(ptr++) = v | B;
62 0 : *(ptr++) = (v>>7) | B;
63 0 : *(ptr++) = (v>>14) | B;
64 0 : *(ptr++) = v>>21;
65 : } else {
66 0 : *(ptr++) = v | B;
67 0 : *(ptr++) = (v>>7) | B;
68 0 : *(ptr++) = (v>>14) | B;
69 0 : *(ptr++) = (v>>21) | B;
70 0 : *(ptr++) = v>>28;
71 : }
72 176660 : return reinterpret_cast<char*>(ptr);
73 : }
74 :
75 82904 : void PutVarint32(std::string* dst, uint32_t v) {
76 : char buf[5];
77 82904 : char* ptr = EncodeVarint32(buf, v);
78 82904 : dst->append(buf, ptr - buf);
79 82904 : }
80 :
81 0 : char* EncodeVarint64(char* dst, uint64_t v) {
82 : static const int B = 128;
83 3495 : unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
84 5594 : while (v >= B) {
85 2099 : *(ptr++) = (v & (B-1)) | B;
86 2099 : v >>= 7;
87 : }
88 3495 : *(ptr++) = static_cast<unsigned char>(v);
89 0 : return reinterpret_cast<char*>(ptr);
90 : }
91 :
92 3495 : void PutVarint64(std::string* dst, uint64_t v) {
93 : char buf[10];
94 3495 : char* ptr = EncodeVarint64(buf, v);
95 3495 : dst->append(buf, ptr - buf);
96 3495 : }
97 :
98 24049 : void PutLengthPrefixedSlice(std::string* dst, const Slice& value) {
99 24049 : PutVarint32(dst, value.size());
100 24049 : dst->append(value.data(), value.size());
101 24049 : }
102 :
103 57098 : int VarintLength(uint64_t v) {
104 57098 : int len = 1;
105 114214 : while (v >= 128) {
106 18 : v >>= 7;
107 18 : len++;
108 : }
109 57098 : return len;
110 : }
111 :
112 509 : const char* GetVarint32PtrFallback(const char* p,
113 : const char* limit,
114 : uint32_t* value) {
115 509 : uint32_t result = 0;
116 1326 : for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
117 304 : uint32_t byte = *(reinterpret_cast<const unsigned char*>(p));
118 304 : p++;
119 304 : if (byte & 128) {
120 : // More bytes are present
121 154 : result |= ((byte & 127) << shift);
122 : } else {
123 150 : result |= (byte << shift);
124 150 : *value = result;
125 150 : return reinterpret_cast<const char*>(p);
126 : }
127 : }
128 : return NULL;
129 : }
130 :
131 58631 : bool GetVarint32(Slice* input, uint32_t* value) {
132 58631 : const char* p = input->data();
133 58631 : const char* limit = p + input->size();
134 58631 : const char* q = GetVarint32Ptr(p, limit, value);
135 58631 : if (q == NULL) {
136 : return false;
137 : } else {
138 58272 : *input = Slice(q, limit - q);
139 58272 : return true;
140 : }
141 : }
142 :
143 60495 : const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) {
144 60495 : uint64_t result = 0;
145 223724 : for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) {
146 111862 : uint64_t byte = *(reinterpret_cast<const unsigned char*>(p));
147 111862 : p++;
148 111862 : if (byte & 128) {
149 : // More bytes are present
150 51367 : result |= ((byte & 127) << shift);
151 : } else {
152 60495 : result |= (byte << shift);
153 60495 : *value = result;
154 60495 : return reinterpret_cast<const char*>(p);
155 : }
156 : }
157 : return NULL;
158 : }
159 :
160 60495 : bool GetVarint64(Slice* input, uint64_t* value) {
161 60495 : const char* p = input->data();
162 60495 : const char* limit = p + input->size();
163 60495 : const char* q = GetVarint64Ptr(p, limit, value);
164 60495 : if (q == NULL) {
165 : return false;
166 : } else {
167 60495 : *input = Slice(q, limit - q);
168 60495 : return true;
169 : }
170 : }
171 :
172 0 : const char* GetLengthPrefixedSlice(const char* p, const char* limit,
173 : Slice* result) {
174 : uint32_t len;
175 0 : p = GetVarint32Ptr(p, limit, &len);
176 0 : if (p == NULL) return NULL;
177 0 : if (p + len > limit) return NULL;
178 0 : *result = Slice(p, len);
179 0 : return p + len;
180 : }
181 :
182 57105 : bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
183 : uint32_t len;
184 114210 : if (GetVarint32(input, &len) &&
185 57105 : input->size() >= len) {
186 57105 : *result = Slice(input->data(), len);
187 57105 : input->remove_prefix(len);
188 57105 : return true;
189 : } else {
190 : return false;
191 : }
192 : }
193 :
194 : } // namespace leveldb
|