xref: /aosp_15_r20/external/webrtc/third_party/abseil-cpp/absl/base/internal/endian.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 
16 #ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
17 #define ABSL_BASE_INTERNAL_ENDIAN_H_
18 
19 #include <cstdint>
20 #include <cstdlib>
21 
22 #include "absl/base/casts.h"
23 #include "absl/base/config.h"
24 #include "absl/base/internal/unaligned_access.h"
25 #include "absl/base/port.h"
26 
27 namespace absl {
28 ABSL_NAMESPACE_BEGIN
29 
gbswap_64(uint64_t host_int)30 inline uint64_t gbswap_64(uint64_t host_int) {
31 #if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
32   return __builtin_bswap64(host_int);
33 #elif defined(_MSC_VER)
34   return _byteswap_uint64(host_int);
35 #else
36   return (((host_int & uint64_t{0xFF}) << 56) |
37           ((host_int & uint64_t{0xFF00}) << 40) |
38           ((host_int & uint64_t{0xFF0000}) << 24) |
39           ((host_int & uint64_t{0xFF000000}) << 8) |
40           ((host_int & uint64_t{0xFF00000000}) >> 8) |
41           ((host_int & uint64_t{0xFF0000000000}) >> 24) |
42           ((host_int & uint64_t{0xFF000000000000}) >> 40) |
43           ((host_int & uint64_t{0xFF00000000000000}) >> 56));
44 #endif
45 }
46 
gbswap_32(uint32_t host_int)47 inline uint32_t gbswap_32(uint32_t host_int) {
48 #if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
49   return __builtin_bswap32(host_int);
50 #elif defined(_MSC_VER)
51   return _byteswap_ulong(host_int);
52 #else
53   return (((host_int & uint32_t{0xFF}) << 24) |
54           ((host_int & uint32_t{0xFF00}) << 8) |
55           ((host_int & uint32_t{0xFF0000}) >> 8) |
56           ((host_int & uint32_t{0xFF000000}) >> 24));
57 #endif
58 }
59 
gbswap_16(uint16_t host_int)60 inline uint16_t gbswap_16(uint16_t host_int) {
61 #if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
62   return __builtin_bswap16(host_int);
63 #elif defined(_MSC_VER)
64   return _byteswap_ushort(host_int);
65 #else
66   return (((host_int & uint16_t{0xFF}) << 8) |
67           ((host_int & uint16_t{0xFF00}) >> 8));
68 #endif
69 }
70 
71 #ifdef ABSL_IS_LITTLE_ENDIAN
72 
73 // Portable definitions for htonl (host-to-network) and friends on little-endian
74 // architectures.
ghtons(uint16_t x)75 inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }
ghtonl(uint32_t x)76 inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }
ghtonll(uint64_t x)77 inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }
78 
79 #elif defined ABSL_IS_BIG_ENDIAN
80 
81 // Portable definitions for htonl (host-to-network) etc on big-endian
82 // architectures. These definitions are simpler since the host byte order is the
83 // same as network byte order.
ghtons(uint16_t x)84 inline uint16_t ghtons(uint16_t x) { return x; }
ghtonl(uint32_t x)85 inline uint32_t ghtonl(uint32_t x) { return x; }
ghtonll(uint64_t x)86 inline uint64_t ghtonll(uint64_t x) { return x; }
87 
88 #else
89 #error \
90     "Unsupported byte order: Either ABSL_IS_BIG_ENDIAN or " \
91        "ABSL_IS_LITTLE_ENDIAN must be defined"
92 #endif  // byte order
93 
gntohs(uint16_t x)94 inline uint16_t gntohs(uint16_t x) { return ghtons(x); }
gntohl(uint32_t x)95 inline uint32_t gntohl(uint32_t x) { return ghtonl(x); }
gntohll(uint64_t x)96 inline uint64_t gntohll(uint64_t x) { return ghtonll(x); }
97 
98 // Utilities to convert numbers between the current hosts's native byte
99 // order and little-endian byte order
100 //
101 // Load/Store methods are alignment safe
102 namespace little_endian {
103 // Conversion functions.
104 #ifdef ABSL_IS_LITTLE_ENDIAN
105 
FromHost16(uint16_t x)106 inline uint16_t FromHost16(uint16_t x) { return x; }
ToHost16(uint16_t x)107 inline uint16_t ToHost16(uint16_t x) { return x; }
108 
FromHost32(uint32_t x)109 inline uint32_t FromHost32(uint32_t x) { return x; }
ToHost32(uint32_t x)110 inline uint32_t ToHost32(uint32_t x) { return x; }
111 
FromHost64(uint64_t x)112 inline uint64_t FromHost64(uint64_t x) { return x; }
ToHost64(uint64_t x)113 inline uint64_t ToHost64(uint64_t x) { return x; }
114 
IsLittleEndian()115 inline constexpr bool IsLittleEndian() { return true; }
116 
117 #elif defined ABSL_IS_BIG_ENDIAN
118 
119 inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
120 inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
121 
122 inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
123 inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
124 
125 inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
126 inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
127 
128 inline constexpr bool IsLittleEndian() { return false; }
129 
130 #endif /* ENDIAN */
131 
FromHost(uint8_t x)132 inline uint8_t FromHost(uint8_t x) { return x; }
FromHost(uint16_t x)133 inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
FromHost(uint32_t x)134 inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
FromHost(uint64_t x)135 inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
ToHost(uint8_t x)136 inline uint8_t ToHost(uint8_t x) { return x; }
ToHost(uint16_t x)137 inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
ToHost(uint32_t x)138 inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
ToHost(uint64_t x)139 inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
140 
FromHost(int8_t x)141 inline int8_t FromHost(int8_t x) { return x; }
FromHost(int16_t x)142 inline int16_t FromHost(int16_t x) {
143   return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
144 }
FromHost(int32_t x)145 inline int32_t FromHost(int32_t x) {
146   return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
147 }
FromHost(int64_t x)148 inline int64_t FromHost(int64_t x) {
149   return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
150 }
ToHost(int8_t x)151 inline int8_t ToHost(int8_t x) { return x; }
ToHost(int16_t x)152 inline int16_t ToHost(int16_t x) {
153   return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
154 }
ToHost(int32_t x)155 inline int32_t ToHost(int32_t x) {
156   return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
157 }
ToHost(int64_t x)158 inline int64_t ToHost(int64_t x) {
159   return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
160 }
161 
162 // Functions to do unaligned loads and stores in little-endian order.
Load16(const void * p)163 inline uint16_t Load16(const void *p) {
164   return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
165 }
166 
Store16(void * p,uint16_t v)167 inline void Store16(void *p, uint16_t v) {
168   ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
169 }
170 
Load32(const void * p)171 inline uint32_t Load32(const void *p) {
172   return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
173 }
174 
Store32(void * p,uint32_t v)175 inline void Store32(void *p, uint32_t v) {
176   ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
177 }
178 
Load64(const void * p)179 inline uint64_t Load64(const void *p) {
180   return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
181 }
182 
Store64(void * p,uint64_t v)183 inline void Store64(void *p, uint64_t v) {
184   ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
185 }
186 
187 }  // namespace little_endian
188 
189 // Utilities to convert numbers between the current hosts's native byte
190 // order and big-endian byte order (same as network byte order)
191 //
192 // Load/Store methods are alignment safe
193 namespace big_endian {
194 #ifdef ABSL_IS_LITTLE_ENDIAN
195 
FromHost16(uint16_t x)196 inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
ToHost16(uint16_t x)197 inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
198 
FromHost32(uint32_t x)199 inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
ToHost32(uint32_t x)200 inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
201 
FromHost64(uint64_t x)202 inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
ToHost64(uint64_t x)203 inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
204 
IsLittleEndian()205 inline constexpr bool IsLittleEndian() { return true; }
206 
207 #elif defined ABSL_IS_BIG_ENDIAN
208 
209 inline uint16_t FromHost16(uint16_t x) { return x; }
210 inline uint16_t ToHost16(uint16_t x) { return x; }
211 
212 inline uint32_t FromHost32(uint32_t x) { return x; }
213 inline uint32_t ToHost32(uint32_t x) { return x; }
214 
215 inline uint64_t FromHost64(uint64_t x) { return x; }
216 inline uint64_t ToHost64(uint64_t x) { return x; }
217 
218 inline constexpr bool IsLittleEndian() { return false; }
219 
220 #endif /* ENDIAN */
221 
FromHost(uint8_t x)222 inline uint8_t FromHost(uint8_t x) { return x; }
FromHost(uint16_t x)223 inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
FromHost(uint32_t x)224 inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
FromHost(uint64_t x)225 inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
ToHost(uint8_t x)226 inline uint8_t ToHost(uint8_t x) { return x; }
ToHost(uint16_t x)227 inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
ToHost(uint32_t x)228 inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
ToHost(uint64_t x)229 inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
230 
FromHost(int8_t x)231 inline int8_t FromHost(int8_t x) { return x; }
FromHost(int16_t x)232 inline int16_t FromHost(int16_t x) {
233   return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
234 }
FromHost(int32_t x)235 inline int32_t FromHost(int32_t x) {
236   return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
237 }
FromHost(int64_t x)238 inline int64_t FromHost(int64_t x) {
239   return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
240 }
ToHost(int8_t x)241 inline int8_t ToHost(int8_t x) { return x; }
ToHost(int16_t x)242 inline int16_t ToHost(int16_t x) {
243   return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
244 }
ToHost(int32_t x)245 inline int32_t ToHost(int32_t x) {
246   return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
247 }
ToHost(int64_t x)248 inline int64_t ToHost(int64_t x) {
249   return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
250 }
251 
252 // Functions to do unaligned loads and stores in big-endian order.
Load16(const void * p)253 inline uint16_t Load16(const void *p) {
254   return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
255 }
256 
Store16(void * p,uint16_t v)257 inline void Store16(void *p, uint16_t v) {
258   ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
259 }
260 
Load32(const void * p)261 inline uint32_t Load32(const void *p) {
262   return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
263 }
264 
Store32(void * p,uint32_t v)265 inline void Store32(void *p, uint32_t v) {
266   ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
267 }
268 
Load64(const void * p)269 inline uint64_t Load64(const void *p) {
270   return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
271 }
272 
Store64(void * p,uint64_t v)273 inline void Store64(void *p, uint64_t v) {
274   ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
275 }
276 
277 }  // namespace big_endian
278 
279 ABSL_NAMESPACE_END
280 }  // namespace absl
281 
282 #endif  // ABSL_BASE_INTERNAL_ENDIAN_H_
283