10#ifndef M5_UTILITY_STL_BYTESWAP_HPP
11#define M5_UTILITY_STL_BYTESWAP_HPP
26#if defined(__SIZEOF_INT128__)
28struct is_int128<__int128> : std::true_type {
32struct is_int128<unsigned __int128> : std::true_type {
37struct is_integer_or_enum : std::integral_constant<bool, std::is_integral<typename std::remove_cv<T>::type>::value ||
38 std::is_enum<typename std::remove_cv<T>::type>::value ||
39 is_int128<typename std::remove_cv<T>::type>::value> {
46#if defined(__SIZEOF_INT128__)
54 using type =
typename std::make_unsigned<T>::type;
62#if defined(__SIZEOF_INT128__)
65 using type =
unsigned __int128;
69struct make_unsigned_impl<unsigned __int128> {
70 using type =
unsigned __int128;
79 typename std::enable_if<
sizeof(U) == 2 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
80inline constexpr U bswap_portable(U x)
noexcept
82 return static_cast<U
>((
static_cast<uint16_t
>(x >> 8) & 0x00FFu) | (
static_cast<uint16_t
>(x << 8) & 0xFF00u));
86 typename std::enable_if<
sizeof(U) == 4 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
87inline constexpr U bswap_portable(U x)
noexcept
89 return static_cast<U
>(((
static_cast<uint32_t
>(x) >> 24)) | ((
static_cast<uint32_t
>(x) >> 8) & 0x0000FF00u) |
90 ((
static_cast<uint32_t
>(x) << 8) & 0x00FF0000u) | ((
static_cast<uint32_t
>(x) << 24)));
94 typename std::enable_if<
sizeof(U) == 8 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
95inline constexpr U bswap_portable(U x)
noexcept
97 return static_cast<U
>(
98 ((
static_cast<uint64_t
>(x) >> 56)) | ((
static_cast<uint64_t
>(x) >> 40) & 0x000000000000FF00ull) |
99 ((
static_cast<uint64_t
>(x) >> 24) & 0x0000000000FF0000ull) |
100 ((
static_cast<uint64_t
>(x) >> 8) & 0x00000000FF000000ull) |
101 ((
static_cast<uint64_t
>(x) << 8) & 0x000000FF00000000ull) |
102 ((
static_cast<uint64_t
>(x) << 24) & 0x0000FF0000000000ull) |
103 ((
static_cast<uint64_t
>(x) << 40) & 0x00FF000000000000ull) | ((
static_cast<uint64_t
>(x) << 56)));
106#if defined(__GNUC__) || defined(__clang__)
109 typename std::enable_if<
sizeof(U) == 2 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
110inline constexpr U bswap_fixed(U x)
noexcept
112 return static_cast<U
>(__builtin_bswap16(
static_cast<uint16_t
>(x)));
116 typename std::enable_if<
sizeof(U) == 4 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
117inline constexpr U bswap_fixed(U x)
noexcept
119 return static_cast<U
>(__builtin_bswap32(
static_cast<uint32_t
>(x)));
123 typename std::enable_if<
sizeof(U) == 8 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
124inline constexpr U bswap_fixed(U x)
noexcept
126 return static_cast<U
>(__builtin_bswap64(
static_cast<uint64_t
>(x)));
130template <
typename U,
typename std::enable_if<(sizeof(U) >= 2 && sizeof(U) <= 8) && detail::is_
unsigned_ex<U>::value,
131 std::
nullptr_t>::type =
nullptr>
132inline constexpr U bswap_fixed(U x)
noexcept
134 return bswap_portable(x);
138#if defined(__SIZEOF_INT128__)
140 typename std::enable_if<
sizeof(U) == 16 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
141inline constexpr U bswap_portable(U x)
noexcept
143 return ((
static_cast<U
>(bswap_portable<uint64_t>(
static_cast<uint64_t
>(x))) << 64) |
144 static_cast<U
>(bswap_portable<uint64_t>(
static_cast<uint64_t
>(x >> 64))));
148#if defined(__has_builtin)
149#if __has_builtin(__builtin_bswap128)
150#define M5_HAS_BUILTIN_BSWAP128 1
152#elif defined(__GNUC__) && (__GNUC__ >= 13)
153#define M5_HAS_BUILTIN_BSWAP128 1
157 typename std::enable_if<
sizeof(U) == 16 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
158inline constexpr U bswap_fixed(U x)
noexcept
160#if defined(M5_HAS_BUILTIN_BSWAP128)
161 return static_cast<U
>(__builtin_bswap128(
static_cast<unsigned __int128
>(x)));
163 return ((
static_cast<U
>(bswap_fixed<uint64_t>(
static_cast<uint64_t
>(x))) << 64) |
164 static_cast<U
>(bswap_fixed<uint64_t>(
static_cast<uint64_t
>(x >> 64))));
170 typename std::enable_if<
sizeof(U) == 1 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
171inline constexpr U bswap_portable(U x)
noexcept
177 typename std::enable_if<
sizeof(U) == 1 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type =
nullptr>
178inline constexpr U bswap_fixed(U x)
noexcept
183template <typename T, typename std::enable_if<detail::is_integer_or_enum<T>::value, std::nullptr_t>::type =
nullptr>
184inline constexpr T byteswap_constexpr(T v)
noexcept
186 using U =
typename detail::make_unsigned_ex<T>::type;
187 return static_cast<T
>(bswap_fixed<U>(
static_cast<U
>(v)));
192template <typename T, typename std::enable_if<detail::is_integer_or_enum<T>::value, std::nullptr_t>::type =
nullptr>
195 return byteswap_constexpr(v);
199template <typename T, typename std::enable_if<detail::is_integer_or_enum<T>::value, std::nullptr_t>::type =
nullptr>
202 using U =
typename detail::make_unsigned_ex<T>::type;
203 return static_cast<T
>(bswap_portable<U>(
static_cast<U
>(v)));
207template <typename T, typename std::enable_if<!detail::is_integer_or_enum<T>::value, std::nullptr_t>::type =
nullptr>
208T byteswap(T) =
delete;
constexpr T byteswap_with_portable(T v) noexcept
byteswap using portable bit manipulation (always available, for testing both paths)
Definition byteswap.hpp:200
constexpr T byteswap(T v) noexcept
byteswap for integral type
Definition byteswap.hpp:193
Top level namespace of M5.
Definition base64.cpp:39
STL compatibility functions and classes.
Definition byteswap.hpp:23
Definition byteswap.hpp:39
Definition byteswap.hpp:43
Definition byteswap.hpp:58
Definition byteswap.hpp:53