Coverage Report

Created: 2025-07-24 22:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/gutil/endian.h
Line
Count
Source
1
// Copyright 2005 Google Inc.
2
//
3
// Licensed to the Apache Software Foundation (ASF) under one
4
// or more contributor license agreements.  See the NOTICE file
5
// distributed with this work for additional information
6
// regarding copyright ownership.  The ASF licenses this file
7
// to you under the Apache License, Version 2.0 (the
8
// "License"); you may not use this file except in compliance
9
// with the License.  You may obtain a copy of the License at
10
//
11
//   http://www.apache.org/licenses/LICENSE-2.0
12
//
13
// Unless required by applicable law or agreed to in writing,
14
// software distributed under the License is distributed on an
15
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
// KIND, either express or implied.  See the License for the
17
// specific language governing permissions and limitations
18
// under the License.
19
//
20
// ---
21
//
22
//
23
// Utility functions that depend on bytesex. We define htonll and ntohll,
24
// as well as "Google" versions of all the standards: ghtonl, ghtons, and
25
// so on. These functions do exactly the same as their standard variants,
26
// but don't require including the dangerous netinet/in.h.
27
//
28
// Buffer routines will copy to and from buffers without causing
29
// a bus error when the architecture requires different byte alignments
30
31
#pragma once
32
33
#include <assert.h>
34
35
#include "olap/uint24.h"
36
#include "vec/core/extended_types.h"
37
38
0
inline uint16_t UNALIGNED_LOAD16(const void* p) {
39
0
    uint16_t t;
40
0
    memcpy(&t, p, sizeof t);
41
0
    return t;
42
0
}
43
44
256k
inline uint32_t UNALIGNED_LOAD32(const void* p) {
45
256k
    uint32_t t;
46
256k
    memcpy(&t, p, sizeof t);
47
256k
    return t;
48
256k
}
49
50
5.39k
inline uint64_t UNALIGNED_LOAD64(const void* p) {
51
5.39k
    uint64_t t;
52
5.39k
    memcpy(&t, p, sizeof t);
53
5.39k
    return t;
54
5.39k
}
55
56
0
inline void UNALIGNED_STORE16(void* p, uint16_t v) {
57
0
    memcpy(p, &v, sizeof v);
58
0
}
59
60
0
inline void UNALIGNED_STORE32(void* p, uint32_t v) {
61
0
    memcpy(p, &v, sizeof v);
62
0
}
63
64
0
inline void UNALIGNED_STORE64(void* p, uint64_t v) {
65
0
    memcpy(p, &v, sizeof v);
66
0
}
67
68
4
inline uint64_t gbswap_64(uint64_t host_int) {
69
4
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
70
    // Adapted from /usr/include/byteswap.h.  Not available on Mac.
71
4
    if (__builtin_constant_p(host_int)) {
72
0
        return __bswap_constant_64(host_int);
73
4
    } else {
74
4
        uint64_t result;
75
4
        __asm__("bswap %0" : "=r"(result) : "0"(host_int));
76
4
        return result;
77
4
    }
78
#elif defined(bswap_64)
79
    return bswap_64(host_int);
80
#else
81
    return static_cast<uint64_t>(bswap_32(static_cast<uint32_t>(host_int >> 32))) |
82
           (static_cast<uint64_t>(bswap_32(static_cast<uint32_t>(host_int))) << 32);
83
#endif // bswap_64
84
4
}
85
86
3.87M
inline unsigned __int128 gbswap_128(unsigned __int128 host_int) {
87
3.87M
    return static_cast<unsigned __int128>(bswap_64(static_cast<uint64_t>(host_int >> 64))) |
88
3.87M
           (static_cast<unsigned __int128>(bswap_64(static_cast<uint64_t>(host_int))) << 64);
89
3.87M
}
90
91
1
inline wide::UInt256 gbswap_256(wide::UInt256 host_int) {
92
1
    wide::UInt256 result {gbswap_64(host_int.items[3]), gbswap_64(host_int.items[2]),
93
1
                          gbswap_64(host_int.items[1]), gbswap_64(host_int.items[0])};
94
1
    return result;
95
1
}
96
97
// Swap bytes of a 24-bit value.
98
0
inline uint32_t bswap_24(uint32_t x) {
99
0
    return ((x & 0x0000ffULL) << 16) | ((x & 0x00ff00ULL)) | ((x & 0xff0000ULL) >> 16);
100
0
}
101
102
template <typename T>
103
1.04M
T byte_swap(T x) {
104
1.04M
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
105
1
        return gbswap_256(x);
106
214
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
107
214
        return gbswap_128(x);
108
68.9k
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
109
68.9k
        return bswap_64(x);
110
978k
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
111
978k
        return bswap_32(x);
112
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
113
        return bswap_24(x);
114
250
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
115
250
        return bswap_16(x);
116
    } else {
117
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
118
        return x; // No byte swap needed for unsupported types
119
    }
120
1.04M
}
_Z9byte_swapItET_S0_
Line
Count
Source
103
250
T byte_swap(T x) {
104
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
105
        return gbswap_256(x);
106
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
107
        return gbswap_128(x);
108
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
109
        return bswap_64(x);
110
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
111
        return bswap_32(x);
112
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
113
        return bswap_24(x);
114
250
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
115
250
        return bswap_16(x);
116
    } else {
117
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
118
        return x; // No byte swap needed for unsupported types
119
    }
120
250
}
_Z9byte_swapIjET_S0_
Line
Count
Source
103
978k
T byte_swap(T x) {
104
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
105
        return gbswap_256(x);
106
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
107
        return gbswap_128(x);
108
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
109
        return bswap_64(x);
110
978k
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
111
978k
        return bswap_32(x);
112
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
113
        return bswap_24(x);
114
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
115
        return bswap_16(x);
116
    } else {
117
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
118
        return x; // No byte swap needed for unsupported types
119
    }
120
978k
}
_Z9byte_swapImET_S0_
Line
Count
Source
103
68.9k
T byte_swap(T x) {
104
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
105
        return gbswap_256(x);
106
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
107
        return gbswap_128(x);
108
68.9k
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
109
68.9k
        return bswap_64(x);
110
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
111
        return bswap_32(x);
112
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
113
        return bswap_24(x);
114
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
115
        return bswap_16(x);
116
    } else {
117
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
118
        return x; // No byte swap needed for unsupported types
119
    }
120
68.9k
}
Unexecuted instantiation: _Z9byte_swapIN5doris8uint24_tEET_S2_
_Z9byte_swapIoET_S0_
Line
Count
Source
103
214
T byte_swap(T x) {
104
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
105
        return gbswap_256(x);
106
214
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
107
214
        return gbswap_128(x);
108
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
109
        return bswap_64(x);
110
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
111
        return bswap_32(x);
112
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
113
        return bswap_24(x);
114
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
115
        return bswap_16(x);
116
    } else {
117
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
118
        return x; // No byte swap needed for unsupported types
119
    }
120
214
}
_Z9byte_swapIN4wide7integerILm256EjEEET_S3_
Line
Count
Source
103
1
T byte_swap(T x) {
104
1
    if constexpr (sizeof(T) == sizeof(wide::Int256)) {
105
1
        return gbswap_256(x);
106
    } else if constexpr (sizeof(T) == sizeof(__int128)) {
107
        return gbswap_128(x);
108
    } else if constexpr (sizeof(T) == sizeof(int64_t)) {
109
        return bswap_64(x);
110
    } else if constexpr (sizeof(T) == sizeof(int32_t)) {
111
        return bswap_32(x);
112
    } else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
113
        return bswap_24(x);
114
    } else if constexpr (sizeof(T) == sizeof(int16_t)) {
115
        return bswap_16(x);
116
    } else {
117
        static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
118
        return x; // No byte swap needed for unsupported types
119
    }
120
1
}
Unexecuted instantiation: _Z9byte_swapInET_S0_
121
122
template <std::endian target, typename T>
123
325M
T to_endian(T value) {
124
325M
    if constexpr (std::endian::native == target) {
125
324M
        return value; // No swap needed
126
324M
    } else {
127
1.04M
        static_assert(std::endian::native == std::endian::big ||
128
1.04M
                              std::endian::native == std::endian::little,
129
1.04M
                      "Unsupported endianness");
130
1.04M
        return byte_swap(value);
131
1.04M
    }
132
325M
}
_Z9to_endianILSt6endian1234EtET0_S1_
Line
Count
Source
123
48.5k
T to_endian(T value) {
124
48.5k
    if constexpr (std::endian::native == target) {
125
48.5k
        return value; // No swap needed
126
    } else {
127
        static_assert(std::endian::native == std::endian::big ||
128
                              std::endian::native == std::endian::little,
129
                      "Unsupported endianness");
130
        return byte_swap(value);
131
    }
132
48.5k
}
_Z9to_endianILSt6endian1234EjET0_S1_
Line
Count
Source
123
902k
T to_endian(T value) {
124
902k
    if constexpr (std::endian::native == target) {
125
902k
        return value; // No swap needed
126
    } else {
127
        static_assert(std::endian::native == std::endian::big ||
128
                              std::endian::native == std::endian::little,
129
                      "Unsupported endianness");
130
        return byte_swap(value);
131
    }
132
902k
}
_Z9to_endianILSt6endian1234EmET0_S1_
Line
Count
Source
123
323M
T to_endian(T value) {
124
323M
    if constexpr (std::endian::native == target) {
125
323M
        return value; // No swap needed
126
    } else {
127
        static_assert(std::endian::native == std::endian::big ||
128
                              std::endian::native == std::endian::little,
129
                      "Unsupported endianness");
130
        return byte_swap(value);
131
    }
132
323M
}
_Z9to_endianILSt6endian4321EtET0_S1_
Line
Count
Source
123
250
T to_endian(T value) {
124
    if constexpr (std::endian::native == target) {
125
        return value; // No swap needed
126
250
    } else {
127
250
        static_assert(std::endian::native == std::endian::big ||
128
250
                              std::endian::native == std::endian::little,
129
250
                      "Unsupported endianness");
130
250
        return byte_swap(value);
131
250
    }
132
250
}
_Z9to_endianILSt6endian4321EjET0_S1_
Line
Count
Source
123
978k
T to_endian(T value) {
124
    if constexpr (std::endian::native == target) {
125
        return value; // No swap needed
126
978k
    } else {
127
978k
        static_assert(std::endian::native == std::endian::big ||
128
978k
                              std::endian::native == std::endian::little,
129
978k
                      "Unsupported endianness");
130
978k
        return byte_swap(value);
131
978k
    }
132
978k
}
_Z9to_endianILSt6endian4321EmET0_S1_
Line
Count
Source
123
68.9k
T to_endian(T value) {
124
    if constexpr (std::endian::native == target) {
125
        return value; // No swap needed
126
68.9k
    } else {
127
68.9k
        static_assert(std::endian::native == std::endian::big ||
128
68.9k
                              std::endian::native == std::endian::little,
129
68.9k
                      "Unsupported endianness");
130
68.9k
        return byte_swap(value);
131
68.9k
    }
132
68.9k
}
Unexecuted instantiation: _Z9to_endianILSt6endian1234EoET0_S1_
Unexecuted instantiation: _Z9to_endianILSt6endian4321EN5doris8uint24_tEET0_S3_
_Z9to_endianILSt6endian4321EoET0_S1_
Line
Count
Source
123
214
T to_endian(T value) {
124
    if constexpr (std::endian::native == target) {
125
        return value; // No swap needed
126
214
    } else {
127
214
        static_assert(std::endian::native == std::endian::big ||
128
214
                              std::endian::native == std::endian::little,
129
214
                      "Unsupported endianness");
130
214
        return byte_swap(value);
131
214
    }
132
214
}
_Z9to_endianILSt6endian4321EN4wide7integerILm256EjEEET0_S4_
Line
Count
Source
123
1
T to_endian(T value) {
124
    if constexpr (std::endian::native == target) {
125
        return value; // No swap needed
126
1
    } else {
127
1
        static_assert(std::endian::native == std::endian::big ||
128
1
                              std::endian::native == std::endian::little,
129
1
                      "Unsupported endianness");
130
1
        return byte_swap(value);
131
1
    }
132
1
}
Unexecuted instantiation: _Z9to_endianILSt6endian4321EnET0_S1_
133
134
// Utilities to convert numbers between the current hosts's native byte
135
// order and little-endian byte order
136
//
137
// Load/Store methods are alignment safe
138
class LittleEndian {
139
public:
140
    // Functions to do unaligned loads and stores in little-endian order.
141
0
    static uint16_t Load16(const void* p) {
142
0
        return to_endian<std::endian::little>(UNALIGNED_LOAD16(p));
143
0
    }
144
145
0
    static void Store16(void* p, uint16_t v) {
146
0
        UNALIGNED_STORE16(p, to_endian<std::endian::little>(v));
147
0
    }
148
149
256k
    static uint32_t Load32(const void* p) {
150
256k
        return to_endian<std::endian::little>(UNALIGNED_LOAD32(p));
151
256k
    }
152
153
0
    static void Store32(void* p, uint32_t v) {
154
0
        UNALIGNED_STORE32(p, to_endian<std::endian::little>(v));
155
0
    }
156
157
4.19k
    static uint64_t Load64(const void* p) {
158
4.19k
        return to_endian<std::endian::little>(UNALIGNED_LOAD64(p));
159
4.19k
    }
160
161
0
    static void Store64(void* p, uint64_t v) {
162
0
        UNALIGNED_STORE64(p, to_endian<std::endian::little>(v));
163
0
    }
164
};
165
166
// Utilities to convert numbers between the current hosts's native byte
167
// order and big-endian byte order (same as network byte order)
168
//
169
// Load/Store methods are alignment safe
170
class BigEndian {
171
public:
172
    // Functions to do unaligned loads and stores in little-endian order.
173
0
    static uint16_t Load16(const void* p) {
174
0
        return to_endian<std::endian::big>(UNALIGNED_LOAD16(p));
175
0
    }
176
177
0
    static void Store16(void* p, uint16_t v) {
178
0
        UNALIGNED_STORE16(p, to_endian<std::endian::big>(v));
179
0
    }
180
181
0
    static uint32_t Load32(const void* p) {
182
0
        return to_endian<std::endian::big>(UNALIGNED_LOAD32(p));
183
0
    }
184
185
0
    static void Store32(void* p, uint32_t v) {
186
0
        UNALIGNED_STORE32(p, to_endian<std::endian::big>(v));
187
0
    }
188
189
0
    static uint64_t Load64(const void* p) {
190
0
        return to_endian<std::endian::big>(UNALIGNED_LOAD64(p));
191
0
    }
192
193
0
    static void Store64(void* p, uint64_t v) {
194
0
        UNALIGNED_STORE64(p, to_endian<std::endian::big>(v));
195
0
    }
196
}; // BigEndian
197
198
// Network byte order is big-endian
199
typedef BigEndian NetworkByteOrder;