M5Utility 0.0.10 git rev:e54335a
Loading...
Searching...
No Matches
byteswap.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UTILITY_STL_BYTESWAP_HPP
11#define M5_UTILITY_STL_BYTESWAP_HPP
12
13#include <stdint.h>
14#include <type_traits>
15#include <cstring> // memcpy
16
17namespace m5 {
18namespace stl {
19
20namespace detail {
21
22template <typename T>
23struct is_int128 : std::false_type {};
24
25#if defined(__SIZEOF_INT128__)
26template <>
27struct is_int128<__int128> : std::true_type {};
28
29template <>
30struct is_int128<unsigned __int128> : std::true_type {};
31#endif
32
33template <typename T>
34struct is_integer_or_enum : std::integral_constant<bool, std::is_integral<typename std::remove_cv<T>::type>::value ||
35 std::is_enum<typename std::remove_cv<T>::type>::value ||
36 is_int128<typename std::remove_cv<T>::type>::value> {};
37
38template <typename T>
39struct is_unsigned_ex : std::is_unsigned<typename std::remove_cv<T>::type> {};
40
41#if defined(__SIZEOF_INT128__)
42template <>
43struct is_unsigned_ex<unsigned __int128> : std::true_type {};
44#endif
45
46template <typename T>
48 using type = typename std::make_unsigned<T>::type;
49};
50
51template <typename T>
53 using type = typename make_unsigned_impl<typename std::remove_cv<T>::type>::type;
54};
55
56#if defined(__SIZEOF_INT128__)
57template <>
58struct make_unsigned_impl<__int128> {
59 using type = unsigned __int128;
60};
61
62template <>
63struct make_unsigned_impl<unsigned __int128> {
64 using type = unsigned __int128;
65};
66#endif
67
68} // namespace detail
69
71template <typename U,
72 typename std::enable_if<sizeof(U) == 2 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type = nullptr>
73inline constexpr U bswap_fixed(U x) noexcept
74{
75 return static_cast<U>((static_cast<uint16_t>(x >> 8) & 0x00FFu) | (static_cast<uint16_t>(x << 8) & 0xFF00u));
76}
77
78template <typename U,
79 typename std::enable_if<sizeof(U) == 4 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type = nullptr>
80inline constexpr U bswap_fixed(U x) noexcept
81{
82 return static_cast<U>(((static_cast<uint32_t>(x) >> 24)) | ((static_cast<uint32_t>(x) >> 8) & 0x0000FF00u) |
83 ((static_cast<uint32_t>(x) << 8) & 0x00FF0000u) | ((static_cast<uint32_t>(x) << 24)));
84}
85
86template <typename U,
87 typename std::enable_if<sizeof(U) == 8 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type = nullptr>
88inline constexpr U bswap_fixed(U x) noexcept
89{
90 return static_cast<U>(
91 ((static_cast<uint64_t>(x) >> 56)) | ((static_cast<uint64_t>(x) >> 40) & 0x000000000000FF00ull) |
92 ((static_cast<uint64_t>(x) >> 24) & 0x0000000000FF0000ull) |
93 ((static_cast<uint64_t>(x) >> 8) & 0x00000000FF000000ull) |
94 ((static_cast<uint64_t>(x) << 8) & 0x000000FF00000000ull) |
95 ((static_cast<uint64_t>(x) << 24) & 0x0000FF0000000000ull) |
96 ((static_cast<uint64_t>(x) << 40) & 0x00FF000000000000ull) | ((static_cast<uint64_t>(x) << 56)));
97}
98
99#if defined(__SIZEOF_INT128__)
100template <typename U,
101 typename std::enable_if<sizeof(U) == 16 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type = nullptr>
102inline constexpr U bswap_fixed(U x) noexcept
103{
104 return ((static_cast<U>(bswap_fixed<uint64_t>(static_cast<uint64_t>(x))) << 64) |
105 static_cast<U>(bswap_fixed<uint64_t>(static_cast<uint64_t>(x >> 64))));
106}
107#endif
108
109template <typename U,
110 typename std::enable_if<sizeof(U) == 1 && detail::is_unsigned_ex<U>::value, std::nullptr_t>::type = nullptr>
111inline constexpr U bswap_fixed(U x) noexcept
112{
113 return x;
114}
115
116template <typename T, typename std::enable_if<detail::is_integer_or_enum<T>::value, std::nullptr_t>::type = nullptr>
117inline constexpr T byteswap_constexpr(T v) noexcept
118{
119 using U = typename detail::make_unsigned_ex<T>::type;
120 return static_cast<T>(bswap_fixed<U>(static_cast<U>(v)));
121}
123
125template <typename T, typename std::enable_if<detail::is_integer_or_enum<T>::value, std::nullptr_t>::type = nullptr>
126inline constexpr T byteswap(T v) noexcept
127{
128 return byteswap_constexpr(v);
129}
130
131// If the type is not integral , it is prohibited
132template <typename T, typename std::enable_if<!detail::is_integer_or_enum<T>::value, std::nullptr_t>::type = nullptr>
133T byteswap(T) = delete;
134
135} // namespace stl
136} // namespace m5
137
138#endif
constexpr T byteswap(T v) noexcept
byteswap for integral type
Definition byteswap.hpp:126
Top level namespace of M5.
Definition base64.cpp:39
STL compatibility functions and classes.
Definition byteswap.hpp:23
Definition byteswap.hpp:36
Definition byteswap.hpp:39
Definition byteswap.hpp:52
Definition byteswap.hpp:47