@@ -30,12 +30,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
3030
3131#ifdef __GNUG__ /* GCC, ICC and Clang */
3232
33- # ifdef __APPLE__
34- # include <machine/endian.h>
35- # else
36- # include <endian.h>
37- # endif
38-
3933# define BYTESWAP_16 (x ) (__builtin_bswap16 (x))
4034# define BYTESWAP_32 (x ) (__builtin_bswap32 (x))
4135# define BYTESWAP_64 (x ) (__builtin_bswap64 (x))
@@ -48,24 +42,58 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
4842# define BYTESWAP_32 (x ) (_byteswap_ulong (x))
4943# define BYTESWAP_64 (x ) (_byteswap_uint64 (x))
5044
51- #else
45+ #elif __has_include(<byteswap.h>) /* Many unixes */
5246
53- # warning "Unknown byte swapping built-ins (do it the slow way)!"
47+ # include < byteswap.h >
5448
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))
5652
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
5956
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))
6997
7098#endif
7199
0 commit comments