Coverage Report

Created: 2026-08-21 19:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/common/endian.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include "core/extended_types.h"
21
#include "core/uint24.h"
22
#include "util/unaligned.h"
23
24
namespace doris {
25
// This header used to lean on the bswap_16/32/64 macros that protobuf's
26
// stubs/port.h happened to leak into most TUs; use the compiler builtins
27
// directly so it stands on its own natural include closure (redefining the
28
// macros here would clash with protobuf's unguarded definitions).
29
693k
inline uint16_t gbswap_16(uint16_t host_int) {
30
693k
    return __builtin_bswap16(host_int);
31
693k
}
32
33
24.5M
inline uint32_t gbswap_32(uint32_t host_int) {
34
24.5M
    return __builtin_bswap32(host_int);
35
24.5M
}
36
37
29.5M
inline uint64_t gbswap_64(uint64_t host_int) {
38
29.5M
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
39
    // Adapted from /usr/include/byteswap.h.  Not available on Mac.
40
29.5M
    if (__builtin_constant_p(host_int)) {
41
0
        return __bswap_constant_64(host_int);
42
29.5M
    } else {
43
29.5M
        uint64_t result;
44
29.5M
        __asm__("bswap %0" : "=r"(result) : "0"(host_int));
45
29.5M
        return result;
46
29.5M
    }
47
#else
48
    return __builtin_bswap64(host_int);
49
#endif
50
29.5M
}
51
52
6.04M
inline unsigned __int128 gbswap_128(unsigned __int128 host_int) {
53
6.04M
    return static_cast<unsigned __int128>(gbswap_64(static_cast<uint64_t>(host_int >> 64))) |
54
6.04M
           (static_cast<unsigned __int128>(gbswap_64(static_cast<uint64_t>(host_int))) << 64);
55
6.04M
}
56
57
50.8k
inline wide::UInt256 gbswap_256(wide::UInt256 host_int) {
58
50.8k
    wide::UInt256 result {gbswap_64(host_int.items[3]), gbswap_64(host_int.items[2]),
59
50.8k
                          gbswap_64(host_int.items[1]), gbswap_64(host_int.items[0])};
60
50.8k
    return result;
61
50.8k
}
62
63
// Swap bytes of a 24-bit value.
64
461k
inline uint32_t bswap_24(uint32_t x) {
65
461k
    return uint32_t((x & 0x0000ffULL) << 16) | ((x & 0x00ff00ULL)) | ((x & 0xff0000ULL) >> 16);
66
461k
}
67
68
// use std::byteswap after doris enable cpp23
69
template <typename T>
70
50.4M
T byte_swap(T x) {
71
50.4M
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
50.8k
        return gbswap_256(x);
73
6.04M
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
6.04M
        return gbswap_128(x);
75
17.3M
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
17.3M
        return gbswap_64(x);
77
24.5M
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
24.5M
        return gbswap_32(x);
79
24.5M
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
462k
        return bswap_24(x);
81
693k
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
693k
        return gbswap_16(x);
83
1.26M
    } else {
84
1.26M
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
1.26M
        return x; // No byte swap needed for unsupported types
86
1.26M
    }
87
50.4M
}
_ZN5doris9byte_swapItEET_S1_
Line
Count
Source
70
693k
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
693k
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
693k
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
693k
}
_ZN5doris9byte_swapIjEET_S1_
Line
Count
Source
70
24.5M
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
24.5M
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
24.5M
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
24.5M
}
_ZN5doris9byte_swapImEET_S1_
Line
Count
Source
70
16.8M
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
16.8M
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
16.8M
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
16.8M
}
_ZN5doris9byte_swapIoEET_S1_
Line
Count
Source
70
2.03M
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
2.03M
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
2.03M
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
2.03M
}
_ZN5doris9byte_swapIlEET_S1_
Line
Count
Source
70
533k
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
533k
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
533k
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
533k
}
_ZN5doris9byte_swapInEET_S1_
Line
Count
Source
70
4.00M
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
4.00M
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
4.00M
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
4.00M
}
Unexecuted instantiation: _ZN5doris9byte_swapIN4wide7integerILm256EiEEEET_S4_
Unexecuted instantiation: _ZN5doris9byte_swapIiEET_S1_
_ZN5doris9byte_swapINS_8uint24_tEEET_S2_
Line
Count
Source
70
462k
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
462k
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
462k
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
462k
}
_ZN5doris9byte_swapIhEET_S1_
Line
Count
Source
70
1.26M
T byte_swap(T x) {
71
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
1.26M
    } else {
84
1.26M
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
1.26M
        return x; // No byte swap needed for unsupported types
86
1.26M
    }
87
1.26M
}
_ZN5doris9byte_swapIN4wide7integerILm256EjEEEET_S4_
Line
Count
Source
70
50.8k
T byte_swap(T x) {
71
50.8k
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
72
50.8k
        return gbswap_256(x);
73
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
74
        return gbswap_128(x);
75
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
76
        return gbswap_64(x);
77
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
78
        return gbswap_32(x);
79
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
80
        return bswap_24(x);
81
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
82
        return gbswap_16(x);
83
    } else {
84
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
85
        return x; // No byte swap needed for unsupported types
86
    }
87
50.8k
}
88
89
template <std::endian target, typename T>
90
327M
T to_endian(T value) {
91
327M
    if constexpr (std::endian::native == target) {
92
276M
        return value; // No swap needed
93
276M
    } else {
94
50.4M
        static_assert(std::endian::native == std::endian::big ||
95
50.4M
                              std::endian::native == std::endian::little,
96
50.4M
                      "Unsupported endianness");
97
50.4M
        return byte_swap(value);
98
50.4M
    }
99
327M
}
_ZN5doris9to_endianILSt6endian1234EtEET0_S2_
Line
Count
Source
90
61.2k
T to_endian(T value) {
91
61.2k
    if constexpr (std::endian::native == target) {
92
61.2k
        return value; // No swap needed
93
    } else {
94
        static_assert(std::endian::native == std::endian::big ||
95
                              std::endian::native == std::endian::little,
96
                      "Unsupported endianness");
97
        return byte_swap(value);
98
    }
99
61.2k
}
_ZN5doris9to_endianILSt6endian1234EjEET0_S2_
Line
Count
Source
90
273M
T to_endian(T value) {
91
273M
    if constexpr (std::endian::native == target) {
92
273M
        return value; // No swap needed
93
    } else {
94
        static_assert(std::endian::native == std::endian::big ||
95
                              std::endian::native == std::endian::little,
96
                      "Unsupported endianness");
97
        return byte_swap(value);
98
    }
99
273M
}
_ZN5doris9to_endianILSt6endian1234EmEET0_S2_
Line
Count
Source
90
3.42M
T to_endian(T value) {
91
3.42M
    if constexpr (std::endian::native == target) {
92
3.42M
        return value; // No swap needed
93
    } else {
94
        static_assert(std::endian::native == std::endian::big ||
95
                              std::endian::native == std::endian::little,
96
                      "Unsupported endianness");
97
        return byte_swap(value);
98
    }
99
3.42M
}
_ZN5doris9to_endianILSt6endian4321EtEET0_S2_
Line
Count
Source
90
693k
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
693k
    } else {
94
693k
        static_assert(std::endian::native == std::endian::big ||
95
693k
                              std::endian::native == std::endian::little,
96
693k
                      "Unsupported endianness");
97
693k
        return byte_swap(value);
98
693k
    }
99
693k
}
_ZN5doris9to_endianILSt6endian4321EjEET0_S2_
Line
Count
Source
90
24.5M
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
24.5M
    } else {
94
24.5M
        static_assert(std::endian::native == std::endian::big ||
95
24.5M
                              std::endian::native == std::endian::little,
96
24.5M
                      "Unsupported endianness");
97
24.5M
        return byte_swap(value);
98
24.5M
    }
99
24.5M
}
_ZN5doris9to_endianILSt6endian4321EmEET0_S2_
Line
Count
Source
90
16.8M
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
16.8M
    } else {
94
16.8M
        static_assert(std::endian::native == std::endian::big ||
95
16.8M
                              std::endian::native == std::endian::little,
96
16.8M
                      "Unsupported endianness");
97
16.8M
        return byte_swap(value);
98
16.8M
    }
99
16.8M
}
_ZN5doris9to_endianILSt6endian1234EoEET0_S2_
Line
Count
Source
90
48.8k
T to_endian(T value) {
91
48.8k
    if constexpr (std::endian::native == target) {
92
48.8k
        return value; // No swap needed
93
    } else {
94
        static_assert(std::endian::native == std::endian::big ||
95
                              std::endian::native == std::endian::little,
96
                      "Unsupported endianness");
97
        return byte_swap(value);
98
    }
99
48.8k
}
_ZN5doris9to_endianILSt6endian4321EoEET0_S2_
Line
Count
Source
90
2.03M
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
2.03M
    } else {
94
2.03M
        static_assert(std::endian::native == std::endian::big ||
95
2.03M
                              std::endian::native == std::endian::little,
96
2.03M
                      "Unsupported endianness");
97
2.03M
        return byte_swap(value);
98
2.03M
    }
99
2.03M
}
_ZN5doris9to_endianILSt6endian4321ElEET0_S2_
Line
Count
Source
90
533k
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
533k
    } else {
94
533k
        static_assert(std::endian::native == std::endian::big ||
95
533k
                              std::endian::native == std::endian::little,
96
533k
                      "Unsupported endianness");
97
533k
        return byte_swap(value);
98
533k
    }
99
533k
}
_ZN5doris9to_endianILSt6endian4321EnEET0_S2_
Line
Count
Source
90
4.00M
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
4.00M
    } else {
94
4.00M
        static_assert(std::endian::native == std::endian::big ||
95
4.00M
                              std::endian::native == std::endian::little,
96
4.00M
                      "Unsupported endianness");
97
4.00M
        return byte_swap(value);
98
4.00M
    }
99
4.00M
}
Unexecuted instantiation: _ZN5doris9to_endianILSt6endian4321EN4wide7integerILm256EiEEEET0_S5_
Unexecuted instantiation: _ZN5doris9to_endianILSt6endian4321EiEET0_S2_
_ZN5doris9to_endianILSt6endian4321ENS_8uint24_tEEET0_S3_
Line
Count
Source
90
462k
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
462k
    } else {
94
462k
        static_assert(std::endian::native == std::endian::big ||
95
462k
                              std::endian::native == std::endian::little,
96
462k
                      "Unsupported endianness");
97
462k
        return byte_swap(value);
98
462k
    }
99
462k
}
_ZN5doris9to_endianILSt6endian4321EhEET0_S2_
Line
Count
Source
90
1.26M
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
1.26M
    } else {
94
1.26M
        static_assert(std::endian::native == std::endian::big ||
95
1.26M
                              std::endian::native == std::endian::little,
96
1.26M
                      "Unsupported endianness");
97
1.26M
        return byte_swap(value);
98
1.26M
    }
99
1.26M
}
_ZN5doris9to_endianILSt6endian4321EN4wide7integerILm256EjEEEET0_S5_
Line
Count
Source
90
50.8k
T to_endian(T value) {
91
    if constexpr (std::endian::native == target) {
92
        return value; // No swap needed
93
50.8k
    } else {
94
50.8k
        static_assert(std::endian::native == std::endian::big ||
95
50.8k
                              std::endian::native == std::endian::little,
96
50.8k
                      "Unsupported endianness");
97
50.8k
        return byte_swap(value);
98
50.8k
    }
99
50.8k
}
100
101
// Utilities to convert numbers between the current hosts's native byte
102
// order and little-endian byte order
103
//
104
// Load/Store methods are alignment safe
105
class LittleEndian {
106
public:
107
    // Functions to do unaligned loads and stores in little-endian order.
108
0
    static uint16_t Load16(const void* p) {
109
0
        return to_endian<std::endian::little>(unaligned_load<uint16_t>(p));
110
0
    }
111
112
0
    static void Store16(void* p, uint16_t v) {
113
0
        unaligned_store<uint16_t>(p, to_endian<std::endian::little>(v));
114
0
    }
115
116
21.0M
    static uint32_t Load32(const void* p) {
117
21.0M
        return to_endian<std::endian::little>(unaligned_load<uint32_t>(p));
118
21.0M
    }
119
120
2.56k
    static void Store32(void* p, uint32_t v) {
121
2.56k
        unaligned_store<uint32_t>(p, to_endian<std::endian::little>(v));
122
2.56k
    }
123
124
3.06M
    static uint64_t Load64(const void* p) {
125
3.06M
        return to_endian<std::endian::little>(unaligned_load<uint64_t>(p));
126
3.06M
    }
127
128
2.73k
    static void Store64(void* p, uint64_t v) {
129
2.73k
        unaligned_store<uint64_t>(p, to_endian<std::endian::little>(v));
130
2.73k
    }
131
};
132
133
// Utilities to convert numbers between the current hosts's native byte
134
// order and big-endian byte order (same as network byte order)
135
//
136
// Load/Store methods are alignment safe
137
class BigEndian {
138
public:
139
    // Functions to do unaligned loads and stores in little-endian order.
140
0
    static uint16_t Load16(const void* p) {
141
0
        return to_endian<std::endian::big>(unaligned_load<uint16_t>(p));
142
0
    }
143
144
0
    static void Store16(void* p, uint16_t v) {
145
0
        unaligned_store<uint16_t>(p, to_endian<std::endian::big>(v));
146
0
    }
147
148
1.20k
    static uint32_t Load32(const void* p) {
149
1.20k
        return to_endian<std::endian::big>(unaligned_load<uint32_t>(p));
150
1.20k
    }
151
152
271
    static void Store32(void* p, uint32_t v) {
153
271
        unaligned_store<uint32_t>(p, to_endian<std::endian::big>(v));
154
271
    }
155
156
0
    static uint64_t Load64(const void* p) {
157
0
        return to_endian<std::endian::big>(unaligned_load<uint64_t>(p));
158
0
    }
159
160
0
    static void Store64(void* p, uint64_t v) {
161
0
        unaligned_store<uint64_t>(p, to_endian<std::endian::big>(v));
162
0
    }
163
}; // BigEndian
164
} // namespace doris