Coverage Report

Created: 2026-10-17 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/s2geometry/src/s2/util/coding/varint.h
Line
Count
Source
1
// Copyright 2001 Google Inc. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
16
//
17
// Raw support for varint encoding.  Higher level interfaces are
18
// provided by Encoder/Decoder/IOBuffer.  Clients should typically use
19
// those interfaces, unless speed is paramount.
20
//
21
// If decoding speed is very important, consider using PrefixVarint instead.
22
// It has the same compression ratio, but generally faster decoding.
23
//
24
// Provided routines:
25
//      vi_parse32_unchecked
26
//      vi_parse64_unchecked
27
//      vi_encode32_unchecked
28
//      vi_encode64_unchecked
29
30
#ifndef S2_UTIL_CODING_VARINT_H_
31
#define S2_UTIL_CODING_VARINT_H_
32
33
// Avoid adding expensive includes here.
34
#include <cassert>
35
#include <cstddef>
36
#include <cstdint>
37
#include <limits>
38
#include <string>
39
#include <utility>
40
41
#include "absl/base/macros.h"
42
#include "absl/numeric/bits.h"
43
44
// Just a namespace, not a real class
45
class Varint {
46
 public:
47
  // Maximum lengths of varint encoding of uint32 and uint64
48
  static constexpr int kMax32 = 5;
49
  static constexpr int kMax64 = 10;
50
51
  // The decoder does not read past the end of the encoded data.
52
  static constexpr int kSlopBytes = 0;
53
54
  // REQUIRES   "ptr" points to a buffer of length at least kMaxXX
55
  // EFFECTS    Scan next varint from "ptr" and store in OUTPUT.
56
  //            Returns pointer just past last read byte.  Returns
57
  //            nullptr if a valid varint value was not found.
58
  static const char* Parse32(const char* ptr, uint32_t* OUTPUT);
59
  static const char* Parse64(const char* ptr, uint64_t* OUTPUT);
60
61
  // A fully inlined version of Parse32: useful in the most time critical
62
  // routines, but its code size is large
63
  static const char* Parse32Inline(const char* ptr, uint32_t* OUTPUT);
64
65
  // REQUIRES   "ptr" points just past the last byte of a varint-encoded value.
66
  // REQUIRES   A second varint must be encoded just before the one we parse,
67
  //            OR "base" must point to the first byte of the one we parse.
68
  // REQUIRES   Bytes [base, ptr-1] are readable
69
  //
70
  // EFFECTS    Scan backwards from "ptr" and store in OUTPUT. Stop at the last
71
  //            byte of the previous varint, OR at "base", whichever one comes
72
  //            first. Returns pointer to the first byte of the decoded varint
73
  //            nullptr if a valid varint value was not found.
74
  static const char* Parse32Backward(const char* ptr, const char* base,
75
                                     uint32_t* OUTPUT);
76
  static const char* Parse64Backward(const char* ptr, const char* base,
77
                                     uint64_t* OUTPUT);
78
79
  // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
80
  // Never reads a character at or beyond limit.  If a valid/terminated varint32
81
  // was found in the range, stores it in *OUTPUT and returns a pointer just
82
  // past the last byte of the varint32. Else returns nullptr.  On success,
83
  // "result <= limit".
84
  static const char* Parse32WithLimit(const char* ptr, const char* limit,
85
                                      uint32_t* OUTPUT);
86
  static const char* Parse64WithLimit(const char* ptr, const char* limit,
87
                                      uint64_t* OUTPUT);
88
89
  // REQUIRES   "ptr" points to the first byte of a varint-encoded value.
90
  // EFFECTS     Scans until the end of the varint and returns a pointer just
91
  //             past the last byte. Returns nullptr if "ptr" does not point to
92
  //             a valid varint value.
93
  static const char* Skip32(const char* ptr);
94
  static const char* Skip64(const char* ptr);
95
96
  // REQUIRES   "ptr" points just past the last byte of a varint-encoded value.
97
  // REQUIRES   A second varint must be encoded just before the one we parse,
98
  //            OR "base" must point to the first byte of the one we parse.
99
  // REQUIRES   Bytes [base, ptr-1] are readable
100
  //
101
  // EFFECTS    Scan backwards from "ptr" and stop at the last byte of the
102
  //            previous varint, OR at "base", whichever one comes first.
103
  //            Returns pointer to the first byte of the skipped varint or
104
  //            nullptr if a valid varint value was not found.
105
  static const char* Skip32Backward(const char* ptr, const char* base);
106
  static const char* Skip64Backward(const char* ptr, const char* base);
107
108
  // REQUIRES   "ptr" points to a buffer of length sufficient to hold "v".
109
  // EFFECTS    Encodes "v" into "ptr" and returns a pointer to the
110
  //            byte just past the last encoded byte.
111
  static char* Encode32(char* ptr, uint32_t v);
112
  static char* Encode64(char* ptr, uint64_t v);
113
114
  // A fully inlined version of Encode32: useful in the most time critical
115
  // routines, but its code size is large
116
  static char* Encode32Inline(char* ptr, uint32_t v);
117
118
  // EFFECTS    Returns the encoding length of the specified value.
119
  static int Length32(uint32_t v);
120
  static int Length64(uint64_t v);
121
122
  // EFFECTS    Appends the varint representation of "value" to "*s".
123
  static void Append32(std::string* s, uint32_t value);
124
  static void Append64(std::string* s, uint64_t value);
125
126
  // Decode and sum up a sequence of deltas until the sum >= goal.
127
  // It is significantly faster than calling ParseXXInline in a loop.
128
  // NOTE(user): The code does NO error checking, it assumes all the
129
  // deltas are valid and the sum of deltas will never exceed
130
  // numeric_limits<int64>::max(). The code works for both 32bits and
131
  // 64bits varint, and on 64 bits machines, the 64 bits version is
132
  // almost always faster. Thus we only have a 64 bits interface here.
133
  // The interface is slightly different from the other functions in that
134
  // it requires *signed* integers.
135
  // REQUIRES   "ptr" points to the first byte of a varint-encoded delta.
136
  //            The sum of deltas >= goal (the code does NO boundary check).
137
  //            goal is positive and fit into a signed int64.
138
  // EFFECTS    Returns a pointer just past last read byte.
139
  //            "out" stores the actual sum.
140
  static const char* FastDecodeDeltas(const char* ptr, int64_t goal,
141
                                      int64_t* out);
142
143
 private:
144
  static const char* Parse32FallbackInline(const char* p, uint32_t* val);
145
  static const char* Parse32Fallback(const char* p, uint32_t* val);
146
#if defined(__x86_64__)
147
  static std::pair<const char*, uint64_t> Parse64FallbackPair(const char* p,
148
                                                              int64_t res1);
149
#else
150
  static const char* Parse64Fallback(const char* p, uint64_t* val);
151
#endif
152
  template <typename T>
153
  static int LengthImpl(T);
154
155
  static const char* Parse32BackwardSlow(const char* ptr, const char* base,
156
                                         uint32_t* OUTPUT);
157
  static const char* Parse64BackwardSlow(const char* ptr, const char* base,
158
                                         uint64_t* OUTPUT);
159
  static const char* Skip32BackwardSlow(const char* ptr, const char* base);
160
  static const char* Skip64BackwardSlow(const char* ptr, const char* base);
161
162
  static void Append32Slow(std::string* s, uint32_t value);
163
  static void Append64Slow(std::string* s, uint64_t value);
164
};
165
166
/***** Implementation details; clients should ignore *****/
167
168
// NOLINTBEGIN(readability/braces) Many false positives.
169
170
inline const char* Varint::Parse32FallbackInline(const char* p,
171
0
                                                 uint32_t* OUTPUT) {
172
  // Fast path
173
0
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
174
0
  uint32_t byte, result;
175
0
  byte = *(ptr++); result = byte & 127;
176
0
  assert(byte >= 128);   // Already checked in inlined prelude
177
0
  byte = *(ptr++); result |= (byte & 127) <<  7; if (byte < 128) goto done;
178
0
  byte = *(ptr++); result |= (byte & 127) << 14; if (byte < 128) goto done;
179
0
  byte = *(ptr++); result |= (byte & 127) << 21; if (byte < 128) goto done;
180
0
  byte = *(ptr++); result |= (byte & 127) << 28; if (byte < 16) goto done;
181
0
  return nullptr;       // Value is too long to be a varint32
182
0
 done:
183
0
  *OUTPUT = result;
184
0
  return reinterpret_cast<const char*>(ptr);
185
0
}
186
187
0
inline const char* Varint::Parse32(const char* p, uint32_t* OUTPUT) {
188
  // Fast path for inlining
189
0
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
190
0
  uint32_t byte = *ptr;
191
0
  if (byte < 128) {
192
0
    *OUTPUT = byte;
193
0
    return reinterpret_cast<const char*>(ptr) + 1;
194
0
  } else {
195
0
    return Parse32Fallback(p, OUTPUT);
196
0
  }
197
0
}
198
199
0
inline const char* Varint::Parse32Inline(const char* p, uint32_t* OUTPUT) {
200
0
  // Fast path for inlining
201
0
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
202
0
  uint32_t byte = *ptr;
203
0
  if (byte < 128) {
204
0
    *OUTPUT = byte;
205
0
    return reinterpret_cast<const char*>(ptr) + 1;
206
0
  } else {
207
0
    return Parse32FallbackInline(p, OUTPUT);
208
0
  }
209
0
}
210
211
0
inline const char* Varint::Skip32(const char* p) {
212
0
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
213
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
214
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
215
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
216
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
217
0
  if (*ptr++ < 16) return reinterpret_cast<const char*>(ptr);
218
0
  return nullptr;  // value is too long to be a varint32
219
0
}
220
221
inline const char* Varint::Parse32Backward(const char* p, const char* base,
222
0
                                           uint32_t* OUTPUT) {
223
0
  if (p > base + kMax32) {
224
0
    // Fast path
225
0
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
226
0
    uint32_t byte, result;
227
0
    byte = *(--ptr); if (byte > 127) return nullptr;
228
0
    result = byte;
229
0
    byte = *(--ptr); if (byte < 128) goto done;
230
0
    result <<= 7; result |= (byte & 127);
231
0
    byte = *(--ptr); if (byte < 128) goto done;
232
0
    result <<= 7; result |= (byte & 127);
233
0
    byte = *(--ptr); if (byte < 128) goto done;
234
0
    result <<= 7; result |= (byte & 127);
235
0
    byte = *(--ptr); if (byte < 128) goto done;
236
0
    result <<= 7; result |= (byte & 127);
237
0
    byte = *(--ptr); if (byte < 128) goto done;
238
0
    return nullptr;  // Value is too long to be a varint32
239
0
  done:
240
0
    *OUTPUT = result;
241
0
    return reinterpret_cast<const char*>(ptr+1);
242
0
  } else {
243
0
    return Parse32BackwardSlow(p, base, OUTPUT);
244
0
  }
245
0
}
246
247
0
inline const char* Varint::Skip32Backward(const char* p, const char* base) {
248
0
  if (p > base + kMax32) {
249
0
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
250
0
    if (*(--ptr) > 127) return nullptr;
251
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
252
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
253
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
254
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
255
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
256
0
    return nullptr;  // value is too long to be a varint32
257
0
  } else {
258
0
    return Skip32BackwardSlow(p, base);
259
0
  }
260
0
}
261
262
inline const char* Varint::Parse32WithLimit(const char* p, const char* l,
263
0
                                            uint32_t* OUTPUT) {
264
  // Version with bounds checks.
265
  // This formerly had an optimization to inline the non-bounds checking Parse32
266
  // but it was found to be slower than the straightforward implementation.
267
0
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
268
0
  const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
269
0
  uint32_t b, result;
270
0
  if (ptr >= limit) return nullptr;
271
0
  b = *(ptr++); result = b & 127;          if (b < 128) goto done;
272
0
  if (ptr >= limit) return nullptr;
273
0
  b = *(ptr++); result |= (b & 127) <<  7; if (b < 128) goto done;
274
0
  if (ptr >= limit) return nullptr;
275
0
  b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
276
0
  if (ptr >= limit) return nullptr;
277
0
  b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
278
0
  if (ptr >= limit) return nullptr;
279
0
  b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
280
0
  return nullptr;       // Value is too long to be a varint32
281
0
 done:
282
0
  *OUTPUT = result;
283
0
  return reinterpret_cast<const char*>(ptr);
284
0
}
285
286
0
inline const char* Varint::Parse64(const char* p, uint64_t* OUTPUT) {
287
0
#if defined(__x86_64__)
288
0
  auto ptr = reinterpret_cast<const int8_t*>(p);
289
0
  int64_t byte = *ptr;
290
0
  if (byte >= 0) {
291
0
    *OUTPUT = static_cast<uint64_t>(byte);
292
0
    return reinterpret_cast<const char*>(ptr) + 1;
293
0
  } else {
294
0
    auto tmp = Parse64FallbackPair(p, byte);
295
0
    if (ABSL_PREDICT_TRUE(tmp.first)) *OUTPUT = tmp.second;
296
0
    return tmp.first;
297
0
  }
298
#else
299
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
300
  uint32_t byte = *ptr;
301
  if (byte < 128) {
302
    *OUTPUT = byte;
303
    return reinterpret_cast<const char*>(ptr) + 1;
304
  } else {
305
    return Parse64Fallback(p, OUTPUT);
306
  }
307
#endif
308
0
}
309
310
0
inline const char* Varint::Skip64(const char* p) {
311
0
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
312
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
313
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
314
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
315
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
316
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
317
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
318
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
319
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
320
0
  if (*ptr++ < 128) return reinterpret_cast<const char*>(ptr);
321
0
  if (*ptr++ < 2) return reinterpret_cast<const char*>(ptr);
322
0
  return nullptr;  // value is too long to be a varint64
323
0
}
324
325
inline const char* Varint::Parse64Backward(const char* p, const char* b,
326
0
                                           uint64_t* OUTPUT) {
327
0
  if (p > b + kMax64) {
328
0
    // Fast path
329
0
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
330
0
    uint32_t byte;
331
0
    uint64_t res;
332
0
333
0
    byte = *(--ptr); if (byte > 127) return nullptr;
334
0
335
0
    res = byte;
336
0
    byte = *(--ptr); if (byte < 128) goto done;
337
0
    res <<= 7; res |= (byte & 127);
338
0
    byte = *(--ptr); if (byte < 128) goto done;
339
0
    res <<= 7; res |= (byte & 127);
340
0
    byte = *(--ptr); if (byte < 128) goto done;
341
0
    res <<= 7; res |= (byte & 127);
342
0
    byte = *(--ptr); if (byte < 128) goto done;
343
0
    res <<= 7; res |= (byte & 127);
344
0
    byte = *(--ptr); if (byte < 128) goto done;
345
0
    res <<= 7; res |= (byte & 127);
346
0
    byte = *(--ptr); if (byte < 128) goto done;
347
0
    res <<= 7; res |= (byte & 127);
348
0
    byte = *(--ptr); if (byte < 128) goto done;
349
0
    res <<= 7; res |= (byte & 127);
350
0
    byte = *(--ptr); if (byte < 128) goto done;
351
0
    res <<= 7; res |= (byte & 127);
352
0
    byte = *(--ptr); if (byte < 128) goto done;
353
0
    res <<= 7; res |= (byte & 127);
354
0
    byte = *(--ptr); if (byte < 128) goto done;
355
0
356
0
    return nullptr;       // Value is too long to be a varint64
357
0
358
0
 done:
359
0
    *OUTPUT = res;
360
0
    return reinterpret_cast<const char*>(ptr + 1);
361
0
  } else {
362
0
    return Parse64BackwardSlow(p, b, OUTPUT);
363
0
  }
364
0
}
365
366
0
inline const char* Varint::Skip64Backward(const char* p, const char* b) {
367
0
  if (p > b + kMax64) {
368
0
    // Fast path
369
0
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
370
0
    if (*(--ptr) > 127) return nullptr;
371
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
372
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
373
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
374
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
375
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
376
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
377
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
378
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
379
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
380
0
    if (*(--ptr) < 128) return reinterpret_cast<const char*>(ptr+1);
381
0
    return nullptr;  // value is too long to be a varint64
382
0
  } else {
383
0
    return Skip64BackwardSlow(p, b);
384
0
  }
385
0
}
386
387
template <typename T>
388
0
int Varint::LengthImpl(T v) {
389
0
  static_assert(std::numeric_limits<T>::digits == 32 ||
390
0
                    std::numeric_limits<T>::digits == 64,
391
0
                "Unexpected length. This implementation works up to 448 bits, "
392
0
                "but performance has not been tested other than 32 and 64.");
393
// X86 CPUs lacking the lzcnt instruction are faster with the bit_width-based
394
// implementation.  Both absl::bit_width and absl::count_lzero will use lzcnt
395
// when available, and bsr otherwise.  For K8 (no lzcnt), bit_width produces
396
// better code; for Haswell and AArch64, countl_zero does.  MSVC and clang do
397
// not define __LZCNT__, the nearest option that they interpret as lzcnt
398
// availability is __AVX2__.
399
0
#if (defined(__x86__) || defined(__x86_64__) || defined(_M_IX86) || \
400
0
     defined(_M_X64)) &&                                            \
401
0
    !(defined(__LZCNT__) || defined(__AVX2__))
402
0
  return (absl::bit_width(v | T{1}) * 9 + 64) / 64;
403
#else
404
  // This computes value == 0 ? 1 : floor(log2(v)) / 7 + 1
405
  // Rather than using division by 7 to accomplish this, we use multiplication
406
  // by 9/64. This has a number of important properties:
407
  //   * It's roughly 1/7.111111. This makes the 0 bits set case have the same
408
  //     value as the 7 bits set case, so offsetting by 1 gives us the correct
409
  //     value for integers up to 448 bits.
410
  //   * Multiplying by 9 is special. x * 9 = x << 3 + x, and so this
411
  //     multiplication can be done by a single shifted add on arm:
412
  //       add w0, w0, w0, lsl #3
413
  //     or a single lea instruction on x86/64:
414
  //       leal (%rax,%rax,8), %eax)
415
  //   * Dividing by 64 is a 6 bit right shift.
416
  //
417
  // Summarized:
418
  //
419
  // value == 0 ? 1 : (floor(log2(v)) / 7 + 1)
420
  // floor((32 - clz) / 7.1111) + 1
421
  // ((32 - clz) * 9) / 64 + 1
422
  // (((32 - clz) * 9) >> 6) + 1
423
  // ((32 - clz) * 9 + (1 << 6)) >> 6
424
  // (32 * 9 + 64 - clz * 9) >> 6
425
  // (352 - clz * 9) >> 6
426
  // on arm:
427
  //  (352 - (clz + (clz << 3))) >> 6
428
  // on x86:
429
  //  (352 - lea(clz, clz, 8)) >> 6
430
  const int clz = absl::countl_zero(v);
431
  return ((std::numeric_limits<T>::digits * 9 + 64) - (clz * 9)) >> 6;
432
#endif
433
0
}
Unexecuted instantiation: int Varint::LengthImpl<unsigned int>(unsigned int)
Unexecuted instantiation: int Varint::LengthImpl<unsigned long>(unsigned long)
434
435
0
inline int Varint::Length32(uint32_t v) { return LengthImpl(v); }
436
0
inline int Varint::Length64(uint64_t v) { return LengthImpl(v); }
437
438
0
inline void Varint::Append32(std::string* s, uint32_t value) {
439
0
  // Inline the fast-path for single-character output, but fall back to the .cc
440
0
  // file for the full version. The size<capacity check is so the compiler can
441
0
  // optimize out the string resize code.
442
0
  if (value < 128 && s->size() < s->capacity()) {
443
0
    s->push_back(static_cast<unsigned char>(value));
444
0
  } else {
445
0
    Append32Slow(s, value);
446
0
  }
447
0
}
448
449
0
inline void Varint::Append64(std::string* s, uint64_t value) {
450
0
  // Inline the fast-path for single-character output, but fall back to the .cc
451
0
  // file for the full version. The size<capacity check is so the compiler can
452
0
  // optimize out the string resize code.
453
0
  if (value < 128 && s->size() < s->capacity()) {
454
0
    s->push_back(static_cast<unsigned char>(value));
455
0
  } else {
456
0
    Append64Slow(s, value);
457
0
  }
458
0
}
459
460
0
inline char* Varint::Encode32Inline(char* sptr, uint32_t v) {
461
  // Operate on characters as unsigneds
462
0
  uint8_t* ptr = reinterpret_cast<uint8_t*>(sptr);
463
0
  static const uint32_t B = 128;
464
0
  if (v < (1<<7)) {
465
0
    *(ptr++) = static_cast<uint8_t>(v);
466
0
  } else if (v < (1<<14)) {
467
0
    *(ptr++) = static_cast<uint8_t>(v | B);
468
0
    *(ptr++) = static_cast<uint8_t>(v >> 7);
469
0
  } else if (v < (1<<21)) {
470
0
    *(ptr++) = static_cast<uint8_t>(v | B);
471
0
    *(ptr++) = static_cast<uint8_t>((v >> 7) | B);
472
0
    *(ptr++) = static_cast<uint8_t>(v >> 14);
473
0
  } else if (v < (1<<28)) {
474
0
    *(ptr++) = static_cast<uint8_t>(v | B);
475
0
    *(ptr++) = static_cast<uint8_t>((v >> 7) | B);
476
0
    *(ptr++) = static_cast<uint8_t>((v >> 14) | B);
477
0
    *(ptr++) = static_cast<uint8_t>(v >> 21);
478
0
  } else {
479
0
    *(ptr++) = static_cast<uint8_t>(v | B);
480
0
    *(ptr++) = static_cast<uint8_t>((v >> 7) | B);
481
0
    *(ptr++) = static_cast<uint8_t>((v >> 14) | B);
482
0
    *(ptr++) = static_cast<uint8_t>((v >> 21) | B);
483
0
    *(ptr++) = static_cast<uint8_t>(v >> 28);
484
0
  }
485
0
  return reinterpret_cast<char*>(ptr);
486
0
}
487
488
#if (-1 >> 1) != -1
489
#error FastDecodeDeltas() needs right-shift to sign-extend.
490
#endif
491
inline const char* Varint::FastDecodeDeltas(const char* ptr, int64_t goal,
492
0
                                            int64_t* out) {
493
0
  int64_t value;
494
0
  int64_t sum = -goal;
495
0
  int64_t shift = 0;
496
0
  // Make decoding faster by eliminating unpredictable branching.
497
0
  do {
498
0
    value = static_cast<int8_t>(*ptr++);  // sign extend one byte of data
499
0
    sum += (value & 0x7F) << shift;
500
0
    shift += 7;
501
0
    // (value >> 7) is either -1(continuation byte) or 0 (stop byte)
502
0
    shift &= value >> 7;
503
0
    // Loop if we haven't reached goal (sum < 0) or we haven't finished
504
0
    // parsing current delta (value < 0). We write it in the form of
505
0
    // (a | b) < 0 as opposed to (a < 0 || b < 0) as the former one is
506
0
    // usually as fast as a test for (a < 0).
507
0
  } while ((sum | value) < 0);
508
0
509
0
  *out = goal + sum;
510
0
  return ptr;
511
0
}
512
513
// NOLINTEND(readability/braces)
514
515
#endif  // S2_UTIL_CODING_VARINT_H_