/root/doris/be/src/util/coding.h
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
6 | | // Use of this source code is governed by a BSD-style license that can be |
7 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
8 | | |
9 | | #pragma once |
10 | | |
11 | | #include <bit> |
12 | | #ifndef __APPLE__ |
13 | | #include <endian.h> |
14 | | #endif |
15 | | #include <stdint.h> |
16 | | #include <string.h> |
17 | | |
18 | | #include "olap/olap_common.h" |
19 | | #include "util/slice.h" |
20 | | |
21 | | namespace doris { |
22 | | |
23 | | // TODO(zc): add encode big endian later when we need it |
24 | | // use big endian when we have order requirement. |
25 | | // little endian is more efficient when we use X86 CPU, so |
26 | | // when we have no order needs, we prefer little endian encoding |
27 | | inline void encode_fixed8(uint8_t* buf, uint8_t val) { |
28 | | *buf = val; |
29 | | } |
30 | | |
31 | 550k | inline void encode_fixed16_le(uint8_t* buf, uint16_t val) { |
32 | 550k | val = to_endian<std::endian::little>(val); |
33 | 550k | memcpy(buf, &val, sizeof(val)); |
34 | 550k | } |
35 | | |
36 | 122M | inline void encode_fixed32_le(uint8_t* buf, uint32_t val) { |
37 | 122M | val = to_endian<std::endian::little>(val); |
38 | 122M | memcpy(buf, &val, sizeof(val)); |
39 | 122M | } |
40 | | |
41 | 504k | inline void encode_fixed64_le(uint8_t* buf, uint64_t val) { |
42 | 504k | val = to_endian<std::endian::little>(val); |
43 | 504k | memcpy(buf, &val, sizeof(val)); |
44 | 504k | } |
45 | | |
46 | 48.8k | inline void encode_fixed128_le(uint8_t* buf, uint128_t val) { |
47 | 48.8k | val = to_endian<std::endian::little>(val); |
48 | 48.8k | memcpy(buf, &val, sizeof(val)); |
49 | 48.8k | } |
50 | | |
51 | 7.15M | inline uint8_t decode_fixed8(const uint8_t* buf) { |
52 | 7.15M | return *buf; |
53 | 7.15M | } |
54 | | |
55 | 646k | inline uint16_t decode_fixed16_le(const uint8_t* buf) { |
56 | 646k | uint16_t res; |
57 | 646k | memcpy(&res, buf, sizeof(res)); |
58 | 646k | return to_endian<std::endian::little>(res); |
59 | 646k | } |
60 | | |
61 | 295M | inline uint32_t decode_fixed32_le(const uint8_t* buf) { |
62 | 295M | uint32_t res; |
63 | 295M | memcpy(&res, buf, sizeof(res)); |
64 | 295M | return to_endian<std::endian::little>(res); |
65 | 295M | } |
66 | | |
67 | 3.92G | inline uint64_t decode_fixed64_le(const uint8_t* buf) { |
68 | 3.92G | uint64_t res; |
69 | 3.92G | memcpy(&res, buf, sizeof(res)); |
70 | 3.92G | return to_endian<std::endian::little>(res); |
71 | 3.92G | } |
72 | | |
73 | 48.8k | inline uint128_t decode_fixed128_le(const uint8_t* buf) { |
74 | 48.8k | uint128_t res; |
75 | 48.8k | memcpy(&res, buf, sizeof(res)); |
76 | 48.8k | return to_endian<std::endian::little>(res); |
77 | 48.8k | } |
78 | | |
79 | | template <typename T> |
80 | 108M | void put_fixed32_le(T* dst, uint32_t val) { |
81 | 108M | uint8_t buf[sizeof(val)]; |
82 | 108M | encode_fixed32_le(buf, val); |
83 | 108M | dst->append((char*)buf, sizeof(buf)); |
84 | 108M | } _ZN5doris14put_fixed32_leINS_10faststringEEEvPT_j Line | Count | Source | 80 | 103M | void put_fixed32_le(T* dst, uint32_t val) { | 81 | 103M | uint8_t buf[sizeof(val)]; | 82 | 103M | encode_fixed32_le(buf, val); | 83 | 103M | dst->append((char*)buf, sizeof(buf)); | 84 | 103M | } |
_ZN5doris14put_fixed32_leINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_j Line | Count | Source | 80 | 4.73M | void put_fixed32_le(T* dst, uint32_t val) { | 81 | 4.73M | uint8_t buf[sizeof(val)]; | 82 | 4.73M | encode_fixed32_le(buf, val); | 83 | 4.73M | dst->append((char*)buf, sizeof(buf)); | 84 | 4.73M | } |
|
85 | | |
86 | | template <typename T> |
87 | 62.5k | void put_fixed64_le(T* dst, uint64_t val) { |
88 | 62.5k | uint8_t buf[sizeof(val)]; |
89 | 62.5k | encode_fixed64_le(buf, val); |
90 | 62.5k | dst->append((char*)buf, sizeof(buf)); |
91 | 62.5k | } _ZN5doris14put_fixed64_leINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_m Line | Count | Source | 87 | 13.6k | void put_fixed64_le(T* dst, uint64_t val) { | 88 | 13.6k | uint8_t buf[sizeof(val)]; | 89 | 13.6k | encode_fixed64_le(buf, val); | 90 | 13.6k | dst->append((char*)buf, sizeof(buf)); | 91 | 13.6k | } |
_ZN5doris14put_fixed64_leINS_10faststringEEEvPT_m Line | Count | Source | 87 | 48.9k | void put_fixed64_le(T* dst, uint64_t val) { | 88 | 48.9k | uint8_t buf[sizeof(val)]; | 89 | 48.9k | encode_fixed64_le(buf, val); | 90 | 48.9k | dst->append((char*)buf, sizeof(buf)); | 91 | 48.9k | } |
|
92 | | |
93 | | // Returns the length of the varint32 or varint64 encoding of "v" |
94 | 70 | inline int varint_length(uint64_t v) { |
95 | 70 | int len = 1; |
96 | 70 | while (v >= 128) { |
97 | 0 | v >>= 7; |
98 | 0 | len++; |
99 | 0 | } |
100 | 70 | return len; |
101 | 70 | } |
102 | | |
103 | | template <typename T> |
104 | 48.8k | void put_fixed128_le(T* dst, uint128_t val) { |
105 | 48.8k | uint8_t buf[sizeof(val)]; |
106 | 48.8k | encode_fixed128_le(buf, val); |
107 | 48.8k | dst->append((char*)buf, sizeof(buf)); |
108 | 48.8k | } |
109 | | |
110 | | extern uint8_t* encode_varint32(uint8_t* dst, uint32_t value); |
111 | | extern uint8_t* encode_varint64(uint8_t* dst, uint64_t value); |
112 | | |
113 | 4.00M | inline uint8_t* encode_varint64(uint8_t* dst, uint64_t v) { |
114 | 4.00M | static const unsigned int B = 128; |
115 | 9.03M | while (v >= B) { |
116 | | // Fetch low seven bits from current v, and the eight bit is marked as compression mark. |
117 | | // v | B is optimised from (v & (B-1)) | B, because result is assigned to uint8_t and other bits |
118 | | // is cleared by implicit conversion. |
119 | 5.03M | *(dst++) = v | B; |
120 | 5.03M | v >>= 7; |
121 | 5.03M | } |
122 | 4.00M | *(dst++) = static_cast<unsigned char>(v); |
123 | 4.00M | return dst; |
124 | 4.00M | } |
125 | | |
126 | | extern const uint8_t* decode_varint32_ptr_fallback(const uint8_t* p, const uint8_t* limit, |
127 | | uint32_t* value); |
128 | | |
129 | | inline const uint8_t* decode_varint32_ptr(const uint8_t* ptr, const uint8_t* limit, |
130 | 245M | uint32_t* value) { |
131 | 245M | if (ptr < limit) { |
132 | 245M | uint32_t result = *ptr; |
133 | 245M | if ((result & 128) == 0) { |
134 | 245M | *value = result; |
135 | 245M | return ptr + 1; |
136 | 245M | } |
137 | 245M | } |
138 | 257k | return decode_varint32_ptr_fallback(ptr, limit, value); |
139 | 245M | } |
140 | | |
141 | | extern const uint8_t* decode_varint64_ptr(const uint8_t* p, const uint8_t* limit, uint64_t* value); |
142 | | |
143 | | template <typename T> |
144 | 67.0M | void put_varint32(T* dst, uint32_t v) { |
145 | 67.0M | uint8_t buf[16]; |
146 | 67.0M | uint8_t* ptr = encode_varint32(buf, v); |
147 | 67.0M | dst->append((char*)buf, static_cast<size_t>(ptr - buf)); |
148 | 67.0M | } |
149 | | |
150 | | template <typename T> |
151 | | void put_varint64(T* dst, uint64_t v) { |
152 | | uint8_t buf[16]; |
153 | | uint8_t* ptr = encode_varint64(buf, v); |
154 | | dst->append((char*)buf, static_cast<size_t>(ptr - buf)); |
155 | | } |
156 | | |
157 | | template <typename T> |
158 | 4.00M | void put_length_prefixed_slice(T* dst, const Slice& value) { |
159 | 4.00M | put_varint32(dst, value.get_size()); |
160 | 4.00M | dst->append(value.get_data(), value.get_size()); |
161 | 4.00M | } |
162 | | |
163 | | template <typename T> |
164 | 4.00M | void put_varint64_varint32(T* dst, uint64_t v1, uint32_t v2) { |
165 | 4.00M | uint8_t buf[16]; |
166 | 4.00M | uint8_t* ptr = encode_varint64(buf, v1); |
167 | 4.00M | ptr = encode_varint32(ptr, v2); |
168 | 4.00M | dst->append((char*)buf, static_cast<size_t>(ptr - buf)); |
169 | 4.00M | } |
170 | | |
171 | | // parse a varint32 from the start of `input` into `val`. |
172 | | // on success, return true and advance `input` past the parsed value. |
173 | | // on failure, return false and `input` is not modified. |
174 | 1.06M | inline bool get_varint32(Slice* input, uint32_t* val) { |
175 | 1.06M | const uint8_t* p = (const uint8_t*)input->data; |
176 | 1.06M | const uint8_t* limit = p + input->size; |
177 | 1.06M | const uint8_t* q = decode_varint32_ptr(p, limit, val); |
178 | 1.06M | if (q == nullptr) { |
179 | 0 | return false; |
180 | 1.06M | } else { |
181 | 1.06M | *input = Slice(q, limit - q); |
182 | 1.06M | return true; |
183 | 1.06M | } |
184 | 1.06M | } |
185 | | |
186 | | // parse a varint64 from the start of `input` into `val`. |
187 | | // on success, return true and advance `input` past the parsed value. |
188 | | // on failure, return false and `input` is not modified. |
189 | 401k | inline bool get_varint64(Slice* input, uint64_t* val) { |
190 | 401k | const uint8_t* p = (const uint8_t*)input->data; |
191 | 401k | const uint8_t* limit = p + input->size; |
192 | 401k | const uint8_t* q = decode_varint64_ptr(p, limit, val); |
193 | 401k | if (q == nullptr) { |
194 | 0 | return false; |
195 | 401k | } else { |
196 | 401k | *input = Slice(q, limit - q); |
197 | 401k | return true; |
198 | 401k | } |
199 | 401k | } |
200 | | |
201 | | // parse a length-prefixed-slice from the start of `input` into `val`. |
202 | | // on success, return true and advance `input` past the parsed value. |
203 | | // on failure, return false and `input` may or may not be modified. |
204 | 410k | inline bool get_length_prefixed_slice(Slice* input, Slice* val) { |
205 | 410k | uint32_t len; |
206 | 410k | if (get_varint32(input, &len) && input->get_size() >= len) { |
207 | 404k | *val = Slice(input->get_data(), len); |
208 | 404k | input->remove_prefix(len); |
209 | 404k | return true; |
210 | 404k | } else { |
211 | 6.06k | return false; |
212 | 6.06k | } |
213 | 410k | } |
214 | | |
215 | | } // namespace doris |