v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
vlq.h
Go to the documentation of this file.
1// Copyright 2021 the V8 project 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.
4
5#ifndef V8_BASE_VLQ_H_
6#define V8_BASE_VLQ_H_
7
8#include <limits>
9#include <vector>
10
11#include "src/base/memory.h"
12
13namespace v8 {
14namespace base {
15
16static constexpr uint32_t kContinueShift = 7;
17static constexpr uint32_t kContinueBit = 1 << kContinueShift;
18static constexpr uint32_t kDataMask = kContinueBit - 1;
19
20// Encodes an unsigned value using variable-length encoding and stores it using
21// the passed process_byte function.
22template <typename Function>
23inline void VLQEncodeUnsigned(Function&& process_byte, uint32_t value) {
24 // Write as many bytes as necessary to encode the value, with 7 bits of data
25 // per byte (leaving space for one continuation bit).
26 static constexpr uint32_t kDataBitsPerByte = kContinueShift;
27 if (value < 1 << (kDataBitsPerByte)) goto write_one_byte;
28 if (value < 1 << (2 * kDataBitsPerByte)) goto write_two_bytes;
29 if (value < 1 << (3 * kDataBitsPerByte)) goto write_three_bytes;
30 if (value < 1 << (4 * kDataBitsPerByte)) goto write_four_bytes;
31 process_byte(value | kContinueBit);
32 value >>= kContinueShift;
33write_four_bytes:
34 process_byte(value | kContinueBit);
35 value >>= kContinueShift;
36write_three_bytes:
37 process_byte(value | kContinueBit);
38 value >>= kContinueShift;
39write_two_bytes:
40 process_byte(value | kContinueBit);
41 value >>= kContinueShift;
42write_one_byte:
43 // The last value written doesn't need a continuation bit.
44 process_byte(value);
45}
46
47inline uint32_t VLQConvertToUnsigned(int32_t value) {
48 // This wouldn't handle kMinInt correctly if it ever encountered it.
49 DCHECK_NE(value, std::numeric_limits<int32_t>::min());
50 bool is_negative = value < 0;
51 // Encode sign in least significant bit.
52 uint32_t bits = static_cast<uint32_t>((is_negative ? -value : value) << 1) |
53 static_cast<uint32_t>(is_negative);
54 return bits;
55}
56
57// Encodes value using variable-length encoding and stores it using the passed
58// process_byte function.
59template <typename Function>
60inline void VLQEncode(Function&& process_byte, int32_t value) {
61 uint32_t bits = VLQConvertToUnsigned(value);
62 VLQEncodeUnsigned(std::forward<Function>(process_byte), bits);
63}
64
65// Wrapper of VLQEncode for std::vector backed storage containers.
66template <typename A>
67inline void VLQEncode(std::vector<uint8_t, A>* data, int32_t value) {
68 VLQEncode([data](uint8_t value) { data->push_back(value); }, value);
69}
70
71// Wrapper of VLQEncodeUnsigned for std::vector backed storage containers.
72template <typename A>
73inline void VLQEncodeUnsigned(std::vector<uint8_t, A>* data, uint32_t value) {
74 VLQEncodeUnsigned([data](uint8_t value) { data->push_back(value); }, value);
75}
76
77// Decodes a variable-length encoded unsigned value from bytes returned by
78// successive calls to the given function.
79template <typename GetNextFunction>
80inline uint32_t VLQDecodeUnsigned(GetNextFunction&& get_next)
81 requires std::is_same<decltype(std::declval<GetNextFunction>()()),
82 uint8_t>::value
83{
84 uint8_t cur_byte = get_next();
85 // Single byte fast path; no need to mask.
86 if (cur_byte <= kDataMask) {
87 return cur_byte;
88 }
89 uint32_t bits = cur_byte & kDataMask;
90 for (int shift = kContinueShift; shift <= 32; shift += kContinueShift) {
91 cur_byte = get_next();
92 bits |= (cur_byte & kDataMask) << shift;
93 if (cur_byte <= kDataMask) break;
94 }
95 return bits;
96}
97
98// Decodes a variable-length encoded unsigned value stored in contiguous memory
99// starting at data_start + index, updating index to where the next encoded
100// value starts.
101inline uint32_t VLQDecodeUnsigned(const uint8_t* data_start, int* index) {
102 return VLQDecodeUnsigned([&] { return data_start[(*index)++]; });
103}
104
105// Decodes a variable-length encoded value stored in contiguous memory starting
106// at data_start + index, updating index to where the next encoded value starts.
107inline int32_t VLQDecode(const uint8_t* data_start, int* index) {
108 uint32_t bits = VLQDecodeUnsigned(data_start, index);
109 bool is_negative = (bits & 1) == 1;
110 int32_t result = bits >> 1;
111 return is_negative ? -result : result;
112}
113
114} // namespace base
115} // namespace v8
116
117#endif // V8_BASE_VLQ_H_
ZoneVector< RpoNumber > & result
static constexpr uint32_t kContinueShift
Definition vlq.h:16
uint32_t VLQConvertToUnsigned(int32_t value)
Definition vlq.h:47
void VLQEncode(Function &&process_byte, int32_t value)
Definition vlq.h:60
static constexpr uint32_t kDataMask
Definition vlq.h:18
uint32_t VLQDecodeUnsigned(GetNextFunction &&get_next)
Definition vlq.h:80
static constexpr uint32_t kContinueBit
Definition vlq.h:17
int32_t VLQDecode(const uint8_t *data_start, int *index)
Definition vlq.h:107
void VLQEncodeUnsigned(Function &&process_byte, uint32_t value)
Definition vlq.h:23
#define DCHECK_NE(v1, v2)
Definition logging.h:486
std::unique_ptr< ValueMirror > value