Coverage Report

Created: 2026-04-22 15:01

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
inline void encode_fixed8(uint8_t* buf, uint8_t val) {
29
    *buf = val;
30
}
31
32
192k
inline void encode_fixed16_le(uint8_t* buf, uint16_t val) {
33
192k
    val = to_endian<std::endian::little>(val);
34
192k
    memcpy(buf, &val, sizeof(val));
35
192k
}
36
37
52.7M
inline void encode_fixed32_le(uint8_t* buf, uint32_t val) {
38
52.7M
    val = to_endian<std::endian::little>(val);
39
52.7M
    memcpy(buf, &val, sizeof(val));
40
52.7M
}
41
42
370k
inline void encode_fixed64_le(uint8_t* buf, uint64_t val) {
43
370k
    val = to_endian<std::endian::little>(val);
44
370k
    memcpy(buf, &val, sizeof(val));
45
370k
}
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
4.75M
inline uint8_t decode_fixed8(const uint8_t* buf) {
53
4.75M
    return *buf;
54
4.75M
}
55
56
240k
inline uint16_t decode_fixed16_le(const uint8_t* buf) {
57
240k
    uint16_t res;
58
240k
    memcpy(&res, buf, sizeof(res));
59
240k
    return to_endian<std::endian::little>(res);
60
240k
}
61
62
209M
inline uint32_t decode_fixed32_le(const uint8_t* buf) {
63
209M
    uint32_t res;
64
209M
    memcpy(&res, buf, sizeof(res));
65
209M
    return to_endian<std::endian::little>(res);
66
209M
}
67
68
349k
inline uint64_t decode_fixed64_le(const uint8_t* buf) {
69
349k
    uint64_t res;
70
349k
    memcpy(&res, buf, sizeof(res));
71
349k
    return to_endian<std::endian::little>(res);
72
349k
}
73
74
24.4k
inline uint128_t decode_fixed128_le(const uint8_t* buf) {
75
24.4k
    uint128_t res;
76
24.4k
    memcpy(&res, buf, sizeof(res));
77
24.4k
    return to_endian<std::endian::little>(res);
78
24.4k
}
79
80
template <typename T>
81
28.0M
void put_fixed32_le(T* dst, uint32_t val) {
82
28.0M
    uint8_t buf[sizeof(val)];
83
28.0M
    encode_fixed32_le(buf, val);
84
28.0M
    dst->append((char*)buf, sizeof(buf));
85
28.0M
}
_ZN5doris14put_fixed32_leINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_j
Line
Count
Source
81
2.21M
void put_fixed32_le(T* dst, uint32_t val) {
82
2.21M
    uint8_t buf[sizeof(val)];
83
2.21M
    encode_fixed32_le(buf, val);
84
2.21M
    dst->append((char*)buf, sizeof(buf));
85
2.21M
}
_ZN5doris14put_fixed32_leINS_10faststringEEEvPT_j
Line
Count
Source
81
25.8M
void put_fixed32_le(T* dst, uint32_t val) {
82
25.8M
    uint8_t buf[sizeof(val)];
83
25.8M
    encode_fixed32_le(buf, val);
84
25.8M
    dst->append((char*)buf, sizeof(buf));
85
25.8M
}
86
87
template <typename T>
88
33.1k
void put_fixed64_le(T* dst, uint64_t val) {
89
33.1k
    uint8_t buf[sizeof(val)];
90
33.1k
    encode_fixed64_le(buf, val);
91
33.1k
    dst->append((char*)buf, sizeof(buf));
92
33.1k
}
_ZN5doris14put_fixed64_leINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvPT_m
Line
Count
Source
88
8.70k
void put_fixed64_le(T* dst, uint64_t val) {
89
8.70k
    uint8_t buf[sizeof(val)];
90
8.70k
    encode_fixed64_le(buf, val);
91
8.70k
    dst->append((char*)buf, sizeof(buf));
92
8.70k
}
_ZN5doris14put_fixed64_leINS_10faststringEEEvPT_m
Line
Count
Source
88
24.4k
void put_fixed64_le(T* dst, uint64_t val) {
89
24.4k
    uint8_t buf[sizeof(val)];
90
24.4k
    encode_fixed64_le(buf, val);
91
24.4k
    dst->append((char*)buf, sizeof(buf));
92
24.4k
}
93
94
// Returns the length of the varint32 or varint64 encoding of "v"
95
35
inline int varint_length(uint64_t v) {
96
35
    int len = 1;
97
35
    while (v >= 128) {
98
0
        v >>= 7;
99
0
        len++;
100
0
    }
101
35
    return len;
102
35
}
103
104
template <typename T>
105
24.4k
void put_fixed128_le(T* dst, uint128_t val) {
106
24.4k
    uint8_t buf[sizeof(val)];
107
24.4k
    encode_fixed128_le(buf, val);
108
24.4k
    dst->append((char*)buf, sizeof(buf));
109
24.4k
}
110
111
extern uint8_t* encode_varint32(uint8_t* dst, uint32_t value);
112
extern uint8_t* encode_varint64(uint8_t* dst, uint64_t value);
113
114
1.85M
inline uint8_t* encode_varint64(uint8_t* dst, uint64_t v) {
115
1.85M
    static const unsigned int B = 128;
116
4.01M
    while (v >= B) {
117
        // Fetch low seven bits from current v, and the eight bit is marked as compression mark.
118
        // v | B is optimised from (v & (B-1)) | B, because result is assigned to uint8_t and other bits
119
        // is cleared by implicit conversion.
120
2.16M
        *(dst++) = uint8_t(v | B);
121
2.16M
        v >>= 7;
122
2.16M
    }
123
1.85M
    *(dst++) = static_cast<unsigned char>(v);
124
1.85M
    return dst;
125
1.85M
}
126
127
extern const uint8_t* decode_varint32_ptr_fallback(const uint8_t* p, const uint8_t* limit,
128
                                                   uint32_t* value);
129
130
inline const uint8_t* decode_varint32_ptr(const uint8_t* ptr, const uint8_t* limit,
131
206M
                                          uint32_t* value) {
132
206M
    if (ptr < limit) {
133
206M
        uint32_t result = *ptr;
134
206M
        if ((result & 128) == 0) {
135
201M
            *value = result;
136
201M
            return ptr + 1;
137
201M
        }
138
206M
    }
139
4.00M
    return decode_varint32_ptr_fallback(ptr, limit, value);
140
206M
}
141
142
extern const uint8_t* decode_varint64_ptr(const uint8_t* p, const uint8_t* limit, uint64_t* value);
143
144
template <typename T>
145
21.3M
void put_varint32(T* dst, uint32_t v) {
146
21.3M
    uint8_t buf[16];
147
21.3M
    uint8_t* ptr = encode_varint32(buf, v);
148
21.3M
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
149
21.3M
}
150
151
template <typename T>
152
void put_varint64(T* dst, uint64_t v) {
153
    uint8_t buf[16];
154
    uint8_t* ptr = encode_varint64(buf, v);
155
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
156
}
157
158
template <typename T>
159
1.85M
void put_length_prefixed_slice(T* dst, const Slice& value) {
160
1.85M
    put_varint32(dst, uint32_t(value.get_size()));
161
1.85M
    dst->append(value.get_data(), value.get_size());
162
1.85M
}
163
164
template <typename T>
165
1.85M
void put_varint64_varint32(T* dst, uint64_t v1, uint32_t v2) {
166
1.85M
    uint8_t buf[16];
167
1.85M
    uint8_t* ptr = encode_varint64(buf, v1);
168
1.85M
    ptr = encode_varint32(ptr, v2);
169
1.85M
    dst->append((char*)buf, static_cast<size_t>(ptr - buf));
170
1.85M
}
171
172
// parse a varint32 from the start of `input` into `val`.
173
// on success, return true and advance `input` past the parsed value.
174
// on failure, return false and `input` is not modified.
175
8.30M
inline bool get_varint32(Slice* input, uint32_t* val) {
176
8.30M
    const auto* p = (const uint8_t*)input->data;
177
8.30M
    const uint8_t* limit = p + input->size;
178
8.30M
    const uint8_t* q = decode_varint32_ptr(p, limit, val);
179
8.30M
    if (q == nullptr) {
180
0
        return false;
181
8.30M
    } else {
182
8.30M
        *input = Slice(q, limit - q);
183
8.30M
        return true;
184
8.30M
    }
185
8.30M
}
186
187
// parse a varint64 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
3.61M
inline bool get_varint64(Slice* input, uint64_t* val) {
191
3.61M
    const auto* p = (const uint8_t*)input->data;
192
3.61M
    const uint8_t* limit = p + input->size;
193
3.61M
    const uint8_t* q = decode_varint64_ptr(p, limit, val);
194
3.61M
    if (q == nullptr) {
195
0
        return false;
196
3.61M
    } else {
197
3.61M
        *input = Slice(q, limit - q);
198
3.61M
        return true;
199
3.61M
    }
200
3.61M
}
201
202
// parse a length-prefixed-slice 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` may or may not be modified.
205
3.61M
inline bool get_length_prefixed_slice(Slice* input, Slice* val) {
206
3.61M
    uint32_t len;
207
3.61M
    if (get_varint32(input, &len) && input->get_size() >= len) {
208
3.61M
        *val = Slice(input->get_data(), len);
209
3.61M
        input->remove_prefix(len);
210
3.61M
        return true;
211
18.4E
    } else {
212
18.4E
        return false;
213
18.4E
    }
214
3.61M
}
215
} // namespace doris