@@ -30,12 +30,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
30
30
31
31
#ifdef __GNUG__ /* GCC, ICC and Clang */
32
32
33
- # ifdef __APPLE__
34
- # include <machine/endian.h>
35
- # else
36
- # include <endian.h>
37
- # endif
38
-
39
33
# define BYTESWAP_16 (x ) (__builtin_bswap16 (x))
40
34
# define BYTESWAP_32 (x ) (__builtin_bswap32 (x))
41
35
# define BYTESWAP_64 (x ) (__builtin_bswap64 (x))
@@ -48,24 +42,58 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
48
42
# define BYTESWAP_32 (x ) (_byteswap_ulong (x))
49
43
# define BYTESWAP_64 (x ) (_byteswap_uint64 (x))
50
44
51
- #else
45
+ #elif __has_include(<byteswap.h>) /* Many unixes */
52
46
53
- # warning "Unknown byte swapping built-ins (do it the slow way)!"
47
+ # include < byteswap.h >
54
48
55
- # define BYTESWAP_16 (x ) (((x) >> 8) | (((x) & 0xFFUL) << 8))
49
+ # define BYTESWAP_16 (x ) (bswap_16(x))
50
+ # define BYTESWAP_32 (x ) (bswap_32(x))
51
+ # define BYTESWAP_64 (x ) (bswap_64(x))
56
52
57
- # define BYTESWAP_32 (x ) (((x) >> 24) | (((x) >> 8) & 0xFF00UL) | \
58
- (((x) & 0xFF00UL) << 8) | ((x) << 24))
53
+ // TODO: C++23 has std::byteswap
54
+
55
+ #else
59
56
60
- # define BYTESWAP_64 (x ) \
61
- (((x) >> 56) | \
62
- (((x) & 0x00FF000000000000ULL) >> 40) | \
63
- (((x) & 0x0000FF0000000000ULL) >> 24) | \
64
- (((x) & 0x000000FF00000000ULL) >> 8) | \
65
- (((x) & 0x00000000FF000000ULL) << 8) | \
66
- (((x) & 0x0000000000FF0000ULL) << 24) | \
67
- (((x) & 0x000000000000FF00ULL) << 40) | \
68
- (((x) & 0x00000000000000FFULL) << 56))
57
+ // #warning is not standard until C++23:
58
+ //
59
+ // # warning "Unknown byte swapping built-ins (do it the slow way)!"
60
+
61
+ # include < cstdint>
62
+
63
+ // Most optimizing compilers will translate these functions directly
64
+ // into their native instructions (e.g. bswap on x86).
65
+ inline std::uint16_t byteswap_16_impl (std::uint16_t x)
66
+ {
67
+ return (x >> 8 ) | (x << 8 );
68
+ }
69
+
70
+ inline std::uint32_t byteswap_32_impl (std::uint32_t x)
71
+ {
72
+ return (
73
+ ((x & UINT32_C (0x000000FF )) << 24 )
74
+ | ((x & UINT32_C (0x0000FF00 )) << 8 )
75
+ | ((x & UINT32_C (0x00FF0000 )) >> 8 )
76
+ | ((x & UINT32_C (0xFF000000 )) >> 24 )
77
+ );
78
+ }
79
+
80
+ inline std::uint64_t byteswap_64_impl (std::uint64_t x)
81
+ {
82
+ return (
83
+ ((x & UINT64_C (0x00000000000000FF )) << 56 )
84
+ | ((x & UINT64_C (0x000000000000FF00 )) << 40 )
85
+ | ((x & UINT64_C (0x0000000000FF0000 )) << 24 )
86
+ | ((x & UINT64_C (0x00000000FF000000 )) << 8 )
87
+ | ((x & UINT64_C (0x000000FF00000000 )) >> 8 )
88
+ | ((x & UINT64_C (0x0000FF0000000000 )) >> 24 )
89
+ | ((x & UINT64_C (0x00FF000000000000 )) >> 40 )
90
+ | ((x & UINT64_C (0xFF00000000000000 )) >> 56 )
91
+ );
92
+ }
93
+
94
+ # define BYTESWAP_16 (x ) (byteswap_16_impl(x))
95
+ # define BYTESWAP_32 (x ) (byteswap_32_impl(x))
96
+ # define BYTESWAP_64 (x ) (byteswap_64_impl(x))
69
97
70
98
#endif
71
99
0 commit comments