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