Coverage Report

Created: 2026-07-18 01:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
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
13
#ifndef __APPLE__
14
#include <endian.h>
15
#endif
16
#include <stdint.h>
17
#include <string.h>
18
19
#include "exec/common/endian.h"
20
#include "storage/olap_common.h"
21
#include "util/slice.h"
22
23
namespace doris {
24
// TODO(zc): add encode big endian later when we need it
25
// use big endian when we have order requirement.
26
// little endian is more efficient when we use X86 CPU, so
27
// when we have no order needs, we prefer little endian encoding
28
1
inline void encode_fixed8(uint8_t* buf, uint8_t val) {
29
1
    *buf = val;
30
1
}
31
32
985
inline void encode_fixed16_le(uint8_t* buf, uint16_t val) {
33
985
    val = to_endian<std::endian::little>(val);
34
985
    memcpy(buf, &val, sizeof(val));
35
985
}
36
37
1.05M
inline void encode_fixed32_le(uint8_t* buf, uint32_t val) {
38
1.05M
    val = to_endian<std::endian::little>(val);
39
1.05M
    memcpy(buf, &val, sizeof(val));
40
1.05M
}
41
42
74.2k
inline void encode_fixed64_le(uint8_t* buf, uint64_t val) {
43
74.2k
    val = to_endian<std::endian::little>(val);
44
74.2k
    memcpy(buf, &val, sizeof(val));
45
74.2k
}
46
47
24.4k
inline void encode_fixed128_le(uint8_t* buf, uint128_t val) {
48
24.4k
    val = to_endian<std::endian::little>(val);
49
24.4k
    memcpy(buf, &val, sizeof(val));
50
24.4k
}
51
52
131k
inline uint8_t decode_fixed8(const uint8_t* buf) {
53
131k
    return *buf;
54
131k
}
55
56
47.5k
inline uint16_t decode_fixed16_le(const uint8_t* buf) {
57
47.5k
    uint16_t res;
58
47.5k
    memcpy(&res, buf, sizeof(res));
59
47.5k
    return to_endian<std::endian::little>(res);
60
47.5k
}
61
62
751k
inline uint32_t decode_fixed32_le(const uint8_t* buf) {
63
751k
    uint32_t res;
64
751k
    memcpy(&res, buf, sizeof(res));
65
751k
    return to_endian<std::endian::little>(res);
66
751k
}
67
68
43.3k
inline uint64_t decode_fixed64_le(const uint8_t* buf) {
69
43.3k
    uint64_t res;
70
43.3k
    memcpy(&res, buf, sizeof(res));
71
43.3k
    return to_endian<std::endian::little>(res);
72
43.3k
}
73
74
411
inline void decode_fixed64_le_array(uint64_t* dst, const void* src, size_t n) {
75
411
    if (n == 0) {
76
0
        return;
77
0
    }
78
411
    if constexpr (std::endian::native == std::endian::little) {
79
411
        memcpy(dst, src, sizeof(uint64_t) * n);
80
    } else {
81
        const auto* ptr = reinterpret_cast<const uint8_t*>(src);
82
        for (size_t i = 0; i < n; ++i) {
83
            dst[i] = decode_fixed64_le(ptr);
84
            ptr += sizeof(uint64_t);
85
        }
86
    }
87
411
}
88
89
24.4k
inline uint128_t decode_fixed128_le(const uint8_t* buf) {
90
24.4k
    uint128_t res;
91
24.4k
    memcpy(&res, buf, sizeof(res));
92
24.4k
    return to_endian<std::endian::little>(res);
93
24.4k
}
94
95
template <typename T>
96
356k
void put_fixed32_le(T* dst, uint32_t val) {
97
356k
    uint8_t buf[sizeof(val)];
98
356k
    encode_fixed32_le(buf, val);
99
356k
    dst->append((char*)buf, sizeof(buf));
100
356k
}
_ZN5doris14put_fixed32_leINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_j
Line
Count
Source
96
38.7k
void put_fixed32_le(T* dst, uint32_t val) {
97
38.7k
    uint8_t buf[sizeof(val)];
98
38.7k
    encode_fixed32_le(buf, val);
99
38.7k
    dst->append((char*)buf, sizeof(buf));
100
38.7k
}
_ZN5doris14put_fixed32_leINS_10faststringEEEvPT_j
Line
Count
Source
96
318k
void put_fixed32_le(T* dst, uint32_t val) {
97
318k
    uint8_t buf[sizeof(val)];
98
318k
    encode_fixed32_le(buf, val);
99
318k
    dst->append((char*)buf, sizeof(buf));
100
318k
}
101
102
template <typename T>
103
25.0k
void put_fixed64_le(T* dst, uint64_t val) {
104
25.0k
    uint8_t buf[sizeof(val)];
105
25.0k
    encode_fixed64_le(buf, val);
106
25.0k
    dst->append((char*)buf, sizeof(buf));
107
25.0k
}
_ZN5doris14put_fixed64_leINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_m
Line
Count
Source
103
615
void put_fixed64_le(T* dst, uint64_t val) {
104
615
    uint8_t buf[sizeof(val)];
105
615
    encode_fixed64_le(buf, val);
106
615
    dst->append((char*)buf, sizeof(buf));
107
615
}
_ZN5doris14put_fixed64_leINS_10faststringEEEvPT_m
Line
Count
Source
103
24.4k
void put_fixed64_le(T* dst, uint64_t val) {
104
24.4k
    uint8_t buf[sizeof(val)];
105
24.4k
    encode_fixed64_le(buf, val);
106
24.4k
    dst->append((char*)buf, sizeof(buf));
107
24.4k
}
108
109
// Returns the length of the varint32 or varint64 encoding of "v"
110
14
inline int varint_length(uint64_t v) {
111
14
    int len = 1;
112
14
    while (v >= 128) {
113
0
        v >>= 7;
114
0
        len++;
115
0
    }
116
14
    return len;
117
14
}
118
119
template <typename T>
120
24.4k
void put_fixed128_le(T* dst, uint128_t val) {
121
24.4k
    uint8_t buf[sizeof(val)];
122
24.4k
    encode_fixed128_le(buf, val);
123
24.4k
    dst->append((char*)buf, sizeof(buf));
124
24.4k
}
125
126
extern uint8_t* encode_varint32(uint8_t* dst, uint32_t value);
127
extern uint8_t* encode_varint64(uint8_t* dst, uint64_t value);
128
129
45.0k
inline uint8_t* encode_varint64(uint8_t* dst, uint64_t v) {
130
45.0k
    static const unsigned int B = 128;
131
135k
    while (v >= B) {
132
        // Fetch low seven bits from current v, and the eight bit is marked as compression mark.
133
        // v | B is optimised from (v & (B-1)) | B, because result is assigned to uint8_t and other bits
134
        // is cleared by implicit conversion.
135
90.7k
        *(dst++) = uint8_t(v | B);
136
90.7k
        v >>= 7;
137
90.7k
    }
138
45.0k
    *(dst++) = static_cast<unsigned char>(v);
139
45.0k
    return dst;
140
45.0k
}
141
142
extern const uint8_t* decode_varint32_ptr_fallback(const uint8_t* p, const uint8_t* limit,
143
                                                   uint32_t* value);
144
145
inline const uint8_t* decode_varint32_ptr(const uint8_t* ptr, const uint8_t* limit,
146
1.12M
                                          uint32_t* value) {
147
1.12M
    if (ptr < limit) {
148
1.12M
        uint32_t result = *ptr;
149
1.12M
        if ((result & 128) == 0) {
150
1.09M
            *value = result;
151
1.09M
            return ptr + 1;
152
1.09M
        }
153
1.12M
    }
154
28.9k
    return decode_varint32_ptr_fallback(ptr, limit, value);
155
1.12M
}
156
157
extern const uint8_t* decode_varint64_ptr(const uint8_t* p, const uint8_t* limit, uint64_t* value);
158
159
template <typename T>
160
332k
void put_varint32(T* dst, uint32_t v) {
161
332k
    uint8_t buf[16];
162
332k
    uint8_t* ptr = encode_varint32(buf, v);
163
332k
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
164
332k
}
_ZN5doris12put_varint32INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_j
Line
Count
Source
160
1
void put_varint32(T* dst, uint32_t v) {
161
1
    uint8_t buf[16];
162
1
    uint8_t* ptr = encode_varint32(buf, v);
163
1
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
164
1
}
_ZN5doris12put_varint32INS_10faststringEEEvPT_j
Line
Count
Source
160
332k
void put_varint32(T* dst, uint32_t v) {
161
332k
    uint8_t buf[16];
162
332k
    uint8_t* ptr = encode_varint32(buf, v);
163
332k
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
164
332k
}
165
166
template <typename T>
167
1
void put_varint64(T* dst, uint64_t v) {
168
1
    uint8_t buf[16];
169
1
    uint8_t* ptr = encode_varint64(buf, v);
170
1
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
171
1
}
172
173
template <typename T>
174
45.0k
void put_length_prefixed_slice(T* dst, const Slice& value) {
175
45.0k
    put_varint32(dst, uint32_t(value.get_size()));
176
45.0k
    dst->append(value.get_data(), value.get_size());
177
45.0k
}
178
179
template <typename T>
180
45.0k
void put_varint64_varint32(T* dst, uint64_t v1, uint32_t v2) {
181
45.0k
    uint8_t buf[16];
182
45.0k
    uint8_t* ptr = encode_varint64(buf, v1);
183
45.0k
    ptr = encode_varint32(ptr, v2);
184
45.0k
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
185
45.0k
}
_ZN5doris21put_varint64_varint32INS_10faststringEEEvPT_mj
Line
Count
Source
180
45.0k
void put_varint64_varint32(T* dst, uint64_t v1, uint32_t v2) {
181
45.0k
    uint8_t buf[16];
182
45.0k
    uint8_t* ptr = encode_varint64(buf, v1);
183
45.0k
    ptr = encode_varint32(ptr, v2);
184
45.0k
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
185
45.0k
}
_ZN5doris21put_varint64_varint32INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_mj
Line
Count
Source
180
1
void put_varint64_varint32(T* dst, uint64_t v1, uint32_t v2) {
181
1
    uint8_t buf[16];
182
1
    uint8_t* ptr = encode_varint64(buf, v1);
183
1
    ptr = encode_varint32(ptr, v2);
184
1
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
185
1
}
186
187
// parse a varint32 from the start of `input` into `val`.
188
// on success, return true and advance `input` past the parsed value.
189
// on failure, return false and `input` is not modified.
190
62.9k
inline bool get_varint32(Slice* input, uint32_t* val) {
191
62.9k
    const auto* p = (const uint8_t*)input->data;
192
62.9k
    const uint8_t* limit = p + input->size;
193
62.9k
    const uint8_t* q = decode_varint32_ptr(p, limit, val);
194
62.9k
    if (q == nullptr) {
195
0
        return false;
196
62.9k
    } else {
197
62.9k
        *input = Slice(q, limit - q);
198
62.9k
        return true;
199
62.9k
    }
200
62.9k
}
201
202
// parse a varint64 from the start of `input` into `val`.
203
// on success, return true and advance `input` past the parsed value.
204
// on failure, return false and `input` is not modified.
205
20.4k
inline bool get_varint64(Slice* input, uint64_t* val) {
206
20.4k
    const auto* p = (const uint8_t*)input->data;
207
20.4k
    const uint8_t* limit = p + input->size;
208
20.4k
    const uint8_t* q = decode_varint64_ptr(p, limit, val);
209
20.4k
    if (q == nullptr) {
210
0
        return false;
211
20.4k
    } else {
212
20.4k
        *input = Slice(q, limit - q);
213
20.4k
        return true;
214
20.4k
    }
215
20.4k
}
216
217
// parse a length-prefixed-slice from the start of `input` into `val`.
218
// on success, return true and advance `input` past the parsed value.
219
// on failure, return false and `input` may or may not be modified.
220
20.4k
inline bool get_length_prefixed_slice(Slice* input, Slice* val) {
221
20.4k
    uint32_t len;
222
20.4k
    if (get_varint32(input, &len) && input->get_size() >= len) {
223
20.4k
        *val = Slice(input->get_data(), len);
224
20.4k
        input->remove_prefix(len);
225
20.4k
        return true;
226
20.4k
    } else {
227
0
        return false;
228
0
    }
229
20.4k
}
230
} // namespace doris