16
16
namespace LIBC_NAMESPACE_DECL {
17
17
18
18
// We rely on compiler preprocessor defines to allow for cross compilation.
19
+ #ifdef LIBC_COMPILER_IS_MSVC
20
+ #define __BYTE_ORDER__ 0
21
+ #define __ORDER_LITTLE_ENDIAN__ 0
22
+ #define __ORDER_BIG_ENDIAN__ 1
23
+ #else // !LIBC_COMPILER_IS_MSVC
19
24
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
20
25
!defined (__ORDER_BIG_ENDIAN__)
21
26
#error "Missing preprocessor definitions for endianness detection."
22
27
#endif
28
+ #endif // LIBC_COMPILER_IS_MSVC
23
29
24
30
namespace internal {
25
31
32
+ template <typename T> LIBC_INLINE T byte_swap (T value);
33
+
34
+ template <> LIBC_INLINE uint16_t byte_swap<uint16_t >(uint16_t value) {
35
+ #if __has_builtin(__builtin_bswap16)
36
+ return __builtin_bswap16 (value);
37
+ #else
38
+ return (v << 8 ) | (v >> 8 );
39
+ #endif // __builtin_bswap16
40
+ }
41
+
42
+ template <> LIBC_INLINE uint32_t byte_swap<uint32_t >(uint32_t value) {
43
+ #if __has_builtin(__builtin_bswap32)
44
+ return __builtin_bswap32 (value);
45
+ #else
46
+ return byte_swap<uint16_t >(static_cast <uint16>(v >> 16 )) ||
47
+ (static_cast <uint32_t >(byte_swap<uint16_t >(static_cast <uint16_t >(v)))
48
+ << 16 );
49
+ #endif // __builtin_bswap64
50
+ }
51
+
52
+ template <> LIBC_INLINE uint64_t byte_swap<uint64_t >(uint64_t value) {
53
+ #if __has_builtin(__builtin_bswap64)
54
+ return __builtin_bswap64 (value);
55
+ #else
56
+ return byte_swap<uint32_t >(static_cast <uint32>(v >> 32 )) ||
57
+ (static_cast <uint64_t >(byte_swap<uint32_t >(static_cast <uint32_t >(v)))
58
+ << 32 );
59
+ #endif // __builtin_bswap64
60
+ }
61
+
26
62
// Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
27
63
// counterpart.
28
64
// We use explicit template specialization:
@@ -53,7 +89,7 @@ template <>
53
89
template <>
54
90
LIBC_INLINE uint16_t
55
91
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t >(uint16_t v) {
56
- return __builtin_bswap16 (v);
92
+ return byte_swap< uint16_t > (v);
57
93
}
58
94
template <>
59
95
template <>
@@ -65,7 +101,7 @@ template <>
65
101
template <>
66
102
LIBC_INLINE uint32_t
67
103
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint32_t >(uint32_t v) {
68
- return __builtin_bswap32 (v);
104
+ return byte_swap< uint32_t > (v);
69
105
}
70
106
template <>
71
107
template <>
@@ -77,7 +113,7 @@ template <>
77
113
template <>
78
114
LIBC_INLINE uint64_t
79
115
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint64_t >(uint64_t v) {
80
- return __builtin_bswap64 (v);
116
+ return byte_swap< uint64_t > (v);
81
117
}
82
118
template <>
83
119
template <>
@@ -109,7 +145,7 @@ template <>
109
145
template <>
110
146
LIBC_INLINE uint16_t
111
147
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint16_t >(uint16_t v) {
112
- return __builtin_bswap16 (v);
148
+ return byte_swap< uint16_t > (v);
113
149
}
114
150
template <>
115
151
template <>
@@ -121,7 +157,7 @@ template <>
121
157
template <>
122
158
LIBC_INLINE uint32_t
123
159
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint32_t >(uint32_t v) {
124
- return __builtin_bswap32 (v);
160
+ return byte_swap< uint32_t > (v);
125
161
}
126
162
template <>
127
163
template <>
@@ -133,7 +169,7 @@ template <>
133
169
template <>
134
170
LIBC_INLINE uint64_t
135
171
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint64_t >(uint64_t v) {
136
- return __builtin_bswap64 (v);
172
+ return byte_swap< uint64_t > (v);
137
173
}
138
174
139
175
} // namespace internal
0 commit comments