Skip to content

Commit ddb3657

Browse files
authored
Merge pull request #140 from mrpapersonic/master
endianswap: use byteswap.h when available, and use inline functions for generic impl
2 parents aee5033 + 8ce9abc commit ddb3657

File tree

1 file changed

+48
-20
lines changed

1 file changed

+48
-20
lines changed

endianswap.h

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)