YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/coding.h
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
//
24
// Endian-neutral encoding:
25
// * Fixed-length numbers are encoded with least-significant byte first
26
// * In addition we support variable length "varint" encoding
27
// * Strings are encoded prefixed by their length in varint format
28
#ifndef YB_ROCKSDB_UTIL_CODING_H
29
#define YB_ROCKSDB_UTIL_CODING_H
30
31
#pragma once
32
33
#include <stdint.h>
34
#include <string.h>
35
36
#include <algorithm>
37
#include <string>
38
39
#include "yb/rocksdb/port/port.h"
40
41
#include "yb/util/cast.h"
42
#include "yb/util/fast_varint.h"
43
44
namespace rocksdb {
45
46
// Standard Put... routines append to a string
47
extern void PutFixed32(std::string* dst, uint32_t value);
48
extern void PutFixed64(std::string* dst, uint64_t value);
49
extern void PutVarint32(std::string* dst, uint32_t value);
50
extern void PutVarint64(std::string* dst, uint64_t value);
51
extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value);
52
extern void PutLengthPrefixedSliceParts(std::string* dst,
53
                                        const SliceParts& slice_parts);
54
55
// Standard Get... routines parse a value from the beginning of a Slice
56
// and advance the slice past the parsed value.
57
extern bool GetFixed64(Slice* input, uint64_t* value);
58
bool GetVarint32(Slice* input, uint32_t* value);
59
extern bool GetVarint64(Slice* input, uint64_t* value);
60
extern bool GetLengthPrefixedSlice(Slice* input, Slice* result);
61
// This function assumes data is well-formed.
62
extern Slice GetLengthPrefixedSlice(const char* data);
63
64
extern Slice GetSliceUntil(Slice* slice, char delimiter);
65
66
// Pointer-based variants of GetVarint...  These either store a value
67
// in *v and return a pointer just past the parsed value, or return
68
// nullptr on error.  These routines only look at bytes in the range
69
// [p..limit-1]
70
extern const char* GetVarint32Ptr(const char* p, const char* limit, uint32_t* v);
71
extern const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* v);
72
73
// Might use effective performance optimization that reads before src, but not before
74
// read_allowed_from.
75
inline const char* GetSignedVarint64Ptr(
76
348k
    const char* p, const char* limit, const char* read_allowed_from, int64_t* value) {
77
348k
  size_t decoded_size;
78
348k
  if (!yb::util::FastDecodeSignedVarInt(p, limit - p, read_allowed_from, value, &decoded_size)
79
0
           .ok()) {
80
0
    return nullptr;
81
0
  }
82
348k
  return p + decoded_size;
83
348k
}
84
85
// Returns the length of the varint32 or varint64 encoding of "v"
86
extern int VarintLength(uint64_t v);
87
88
// Lower-level versions of Put... that write directly into a character buffer
89
// REQUIRES: dst has enough space for the value being written
90
extern void EncodeFixed32(char* dst, uint32_t value);
91
extern void EncodeFixed64(char* dst, uint64_t value);
92
93
// Lower-level versions of Put... that write directly into a character buffer
94
// and return a pointer just past the last byte written.
95
// REQUIRES: dst has enough space for the value being written
96
extern char* EncodeVarint32(char* dst, uint32_t value);
97
extern char* EncodeVarint64(char* dst, uint64_t value);
98
99
// Lower-level versions of Get... that read directly from a character buffer
100
// without any bounds checking.
101
102
72.6k
inline uint8_t DecodeFixed8(const char* ptr) {
103
72.6k
  return pointer_cast<const uint8_t*>(ptr)[0];
104
72.6k
}
105
106
11.8G
inline uint32_t DecodeFixed32(const char* ptr) {
107
11.8G
  if (port::kLittleEndian) {
108
    // Load the raw bytes
109
11.8G
    uint32_t result;
110
11.8G
    memcpy(&result, ptr, sizeof(result));  // gcc optimizes this to a plain load
111
11.8G
    return result;
112
264k
  } else {
113
264k
    return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))
114
264k
        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
115
264k
        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
116
264k
        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
117
264k
  }
118
11.8G
}
119
120
14.6k
inline uint32_t DecodeFixed32(const uint8_t* ptr) {
121
14.6k
  return DecodeFixed32(reinterpret_cast<const char*>(ptr));
122
14.6k
}
123
124
1.63G
inline uint64_t DecodeFixed64(const char* ptr) {
125
1.63G
  if (port::kLittleEndian) {
126
    // Load the raw bytes
127
1.63G
    uint64_t result;
128
1.63G
    memcpy(&result, ptr, sizeof(result));  // gcc optimizes this to a plain load
129
1.63G
    return result;
130
18.4E
  } else {
131
18.4E
    uint64_t lo = DecodeFixed32(ptr);
132
18.4E
    uint64_t hi = DecodeFixed32(ptr + 4);
133
18.4E
    return (hi << 32) | lo;
134
18.4E
  }
135
1.63G
}
136
137
1.62G
inline uint64_t DecodeFixed64(const uint8_t* ptr) {
138
1.62G
  return DecodeFixed64(reinterpret_cast<const char*>(ptr));
139
1.62G
}
140
141
// Internal routine for use by fallback path of GetVarint32Ptr
142
extern const char* GetVarint32PtrFallback(const char* p,
143
                                          const char* limit,
144
                                          uint32_t* value);
145
146
const char* GetVarint64PtrFallback(const char* p, const char* limit, uint64_t* value);
147
148
inline const char* GetVarint32Ptr(const char* p,
149
                                  const char* limit,
150
20.1G
                                  uint32_t* value) {
151
20.3G
  if (p < limit) {
152
20.3G
    uint32_t result = *(reinterpret_cast<const unsigned char*>(p));
153
20.3G
    if ((result & 128) == 0) {
154
20.1G
      *value = result;
155
20.1G
      return p + 1;
156
20.1G
    }
157
37.3M
  }
158
37.3M
  return GetVarint32PtrFallback(p, limit, value);
159
37.3M
}
160
161
inline const char* GetVarint64Ptr(const char* p,
162
                                  const char* limit,
163
74.5M
                                  uint64_t* value) {
164
74.5M
  if (p < limit) {
165
74.5M
    uint64_t result = *(reinterpret_cast<const unsigned char*>(p));
166
74.5M
    if ((result & 128) == 0) {
167
7.25M
      *value = result;
168
7.25M
      return p + 1;
169
7.25M
    }
170
67.2M
  }
171
67.2M
  return GetVarint64PtrFallback(p, limit, value);
172
67.2M
}
173
174
// -- Implementation of the functions declared above
175
79.1M
inline void EncodeFixed32(char* buf, uint32_t value) {
176
79.1M
#if __BYTE_ORDER == __LITTLE_ENDIAN
177
79.1M
  memcpy(buf, &value, sizeof(value));
178
#else
179
  buf[0] = value & 0xff;
180
  buf[1] = (value >> 8) & 0xff;
181
  buf[2] = (value >> 16) & 0xff;
182
  buf[3] = (value >> 24) & 0xff;
183
#endif
184
79.1M
}
185
186
360M
inline void EncodeFixed64(char* buf, uint64_t value) {
187
360M
#if __BYTE_ORDER == __LITTLE_ENDIAN
188
360M
  memcpy(buf, &value, sizeof(value));
189
#else
190
  buf[0] = value & 0xff;
191
  buf[1] = (value >> 8) & 0xff;
192
  buf[2] = (value >> 16) & 0xff;
193
  buf[3] = (value >> 24) & 0xff;
194
  buf[4] = (value >> 32) & 0xff;
195
  buf[5] = (value >> 40) & 0xff;
196
  buf[6] = (value >> 48) & 0xff;
197
  buf[7] = (value >> 56) & 0xff;
198
#endif
199
360M
}
200
201
693k
inline void PutFixed8(std::string* dst, uint8_t value) {
202
693k
  dst->push_back(value);
203
693k
}
204
205
15.2M
inline void PutFixed32(std::string* dst, uint32_t value) {
206
15.2M
  char buf[sizeof(value)];
207
15.2M
  EncodeFixed32(buf, value);
208
15.2M
  dst->append(buf, sizeof(buf));
209
15.2M
}
210
211
2.69M
inline void PutFixed64(std::string* dst, uint64_t value) {
212
2.69M
  char buf[sizeof(value)];
213
2.69M
  EncodeFixed64(buf, value);
214
2.69M
  dst->append(buf, sizeof(buf));
215
2.69M
}
216
217
452M
inline void PutVarint32(std::string* dst, uint32_t v) {
218
452M
  char buf[5];
219
452M
  char* ptr = EncodeVarint32(buf, v);
220
452M
  dst->append(buf, static_cast<size_t>(ptr - buf));
221
452M
}
222
223
111k
inline void PutSignedVarint(std::string* dst, int64_t v) {
224
111k
  char buf[yb::util::kMaxVarIntBufferSize];
225
111k
  size_t encoded_size;
226
111k
  yb::util::FastEncodeSignedVarInt(v, pointer_cast<uint8_t*>(buf), &encoded_size);
227
111k
  dst->append(buf, encoded_size);
228
111k
}
229
230
33.8M
inline char* EncodeVarint64(char* dst, uint64_t v) {
231
33.8M
  static const unsigned int B = 128;
232
33.8M
  unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
233
76.0M
  while (v >= B) {
234
42.1M
    *(ptr++) = (v & (B - 1)) | B;
235
42.1M
    v >>= 7;
236
42.1M
  }
237
33.8M
  *(ptr++) = static_cast<unsigned char>(v);
238
33.8M
  return reinterpret_cast<char*>(ptr);
239
33.8M
}
240
241
580k
inline char* FastEncodeVarint64(char* dst, uint64_t v) {
242
580k
  if (v <= std::numeric_limits<uint32_t>::max()) {
243
580k
    return EncodeVarint32(dst, static_cast<uint32_t>(v));
244
580k
  }
245
97
  return EncodeVarint64(dst, v);
246
97
}
247
248
6.37M
inline void PutVarint64(std::string* dst, uint64_t v) {
249
6.37M
  char buf[10];
250
6.37M
  char* ptr = EncodeVarint64(buf, v);
251
6.37M
  dst->append(buf, static_cast<size_t>(ptr - buf));
252
6.37M
}
253
254
580k
inline void FastPutVarint64(std::string* dst, uint64_t v) {
255
580k
  char buf[yb::util::kMaxVarIntBufferSize];
256
580k
  char* ptr = FastEncodeVarint64(buf, v);
257
580k
  dst->append(buf, static_cast<size_t>(ptr - buf));
258
580k
}
259
260
74.6M
inline void PutLengthPrefixedSlice(std::string* dst, const Slice& value) {
261
74.6M
  PutVarint32(dst, static_cast<uint32_t>(value.size()));
262
74.6M
  dst->append(value.cdata(), value.size());
263
74.6M
}
264
265
inline void PutLengthPrefixedSliceParts(std::string* dst,
266
123
                                        const SliceParts& slice_parts) {
267
123
  size_t total_bytes = 0;
268
340
  for (int i = 0; i < slice_parts.num_parts; ++i) {
269
217
    total_bytes += slice_parts.parts[i].size();
270
217
  }
271
123
  PutVarint32(dst, static_cast<uint32_t>(total_bytes));
272
340
  for (int i = 0; i < slice_parts.num_parts; ++i) {
273
217
    dst->append(slice_parts.parts[i].cdata(), slice_parts.parts[i].size());
274
217
  }
275
123
}
276
277
544M
inline int VarintLength(uint64_t v) {
278
544M
  int len = 1;
279
570M
  while (v >= 128) {
280
26.3M
    v >>= 7;
281
26.3M
    len++;
282
26.3M
  }
283
544M
  return len;
284
544M
}
285
286
0
inline bool GetFixed64(Slice* input, uint64_t* value) {
287
0
  if (input->size() < sizeof(uint64_t)) {
288
0
    return false;
289
0
  }
290
0
  *value = DecodeFixed64(input->data());
291
0
  input->remove_prefix(sizeof(uint64_t));
292
0
  return true;
293
0
}
294
295
151M
inline bool GetVarint32(Slice* input, uint32_t* value) {
296
151M
  const char* p = input->cdata();
297
151M
  const char* limit = p + input->size();
298
151M
  const char* q = GetVarint32Ptr(p, limit, value);
299
151M
  if (q == nullptr) {
300
0
    return false;
301
151M
  } else {
302
151M
    *input = Slice(q, static_cast<size_t>(limit - q));
303
151M
    return true;
304
151M
  }
305
151M
}
306
307
50.5M
inline bool GetVarint64(Slice* input, uint64_t* value) {
308
50.5M
  const char* p = input->cdata();
309
50.5M
  const char* limit = p + input->size();
310
50.5M
  const char* q = GetVarint64Ptr(p, limit, value);
311
50.5M
  if (q == nullptr) {
312
0
    return false;
313
50.5M
  } else {
314
50.5M
    *input = Slice(q, static_cast<size_t>(limit - q));
315
50.5M
    return true;
316
50.5M
  }
317
50.5M
}
318
319
127M
inline bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
320
127M
  uint32_t len = 0;
321
127M
  if (GetVarint32(input, &len) && input->size() >= len) {
322
127M
    *result = Slice(input->data(), len);
323
127M
    input->remove_prefix(len);
324
127M
    return true;
325
894
  } else {
326
894
    return false;
327
894
  }
328
127M
}
329
330
19.9G
inline Slice GetLengthPrefixedSlice(const char* data) {
331
19.9G
  uint32_t len = 0;
332
  // +5: we assume "data" is not corrupted
333
19.9G
  auto p = GetVarint32Ptr(data, data + 5 /* limit */, &len);
334
19.9G
  return Slice(p, len);
335
19.9G
}
336
337
0
inline Slice GetSliceUntil(Slice* slice, char delimiter) {
338
0
  uint32_t len = 0;
339
0
  for (len = 0; len < slice->size() && slice->data()[len] != delimiter; ++len) {
340
0
    // nothing
341
0
  }
342
0
343
0
  Slice ret(slice->data(), len);
344
0
  slice->remove_prefix(len + ((len < slice->size()) ? 1 : 0));
345
0
  return ret;
346
0
}
347
348
}  // namespace rocksdb
349
350
#endif // YB_ROCKSDB_UTIL_CODING_H