1616namespace LIBC_NAMESPACE_DECL {
1717
1818// 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
1924#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
2025 !defined (__ORDER_BIG_ENDIAN__)
2126#error "Missing preprocessor definitions for endianness detection."
2227#endif
28+ #endif // LIBC_COMPILER_IS_MSVC
2329
2430namespace internal {
2531
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+
2662// Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
2763// counterpart.
2864// We use explicit template specialization:
@@ -53,7 +89,7 @@ template <>
5389template <>
5490LIBC_INLINE uint16_t
5591Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t >(uint16_t v) {
56- return __builtin_bswap16 (v);
92+ return byte_swap< uint16_t > (v);
5793}
5894template <>
5995template <>
@@ -65,7 +101,7 @@ template <>
65101template <>
66102LIBC_INLINE uint32_t
67103Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint32_t >(uint32_t v) {
68- return __builtin_bswap32 (v);
104+ return byte_swap< uint32_t > (v);
69105}
70106template <>
71107template <>
@@ -77,7 +113,7 @@ template <>
77113template <>
78114LIBC_INLINE uint64_t
79115Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint64_t >(uint64_t v) {
80- return __builtin_bswap64 (v);
116+ return byte_swap< uint64_t > (v);
81117}
82118template <>
83119template <>
@@ -109,7 +145,7 @@ template <>
109145template <>
110146LIBC_INLINE uint16_t
111147Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint16_t >(uint16_t v) {
112- return __builtin_bswap16 (v);
148+ return byte_swap< uint16_t > (v);
113149}
114150template <>
115151template <>
@@ -121,7 +157,7 @@ template <>
121157template <>
122158LIBC_INLINE uint32_t
123159Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint32_t >(uint32_t v) {
124- return __builtin_bswap32 (v);
160+ return byte_swap< uint32_t > (v);
125161}
126162template <>
127163template <>
@@ -133,7 +169,7 @@ template <>
133169template <>
134170LIBC_INLINE uint64_t
135171Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint64_t >(uint64_t v) {
136- return __builtin_bswap64 (v);
172+ return byte_swap< uint64_t > (v);
137173}
138174
139175} // namespace internal
0 commit comments