18#if HI_COMPILER == HI_CC_MSVC
28hi_warning_ignore_msvc(26472);
30namespace hi::inline
v1 {
32template<std::
unsigned_
integral T>
33[[nodiscard]]
constexpr T byte_swap(T x)
noexcept
35 if (not std::is_constant_evaluated()) {
36#if HI_COMPILER == HI_CC_CLANG || HI_COMPILER == HI_CC_GCC
37 if constexpr (
sizeof(T) ==
sizeof(uint64_t)) {
38 return static_cast<T
>(__builtin_bswap64(
static_cast<uint64_t
>(x)));
39 }
else if constexpr (
sizeof(T) ==
sizeof(uint32_t)) {
40 return static_cast<T
>(__builtin_bswap32(
static_cast<uint32_t
>(x)));
41 }
else if constexpr (
sizeof(T) ==
sizeof(uint16_t)) {
42 return static_cast<T
>(__builtin_bswap16(
static_cast<uint16_t
>(x)));
44#elif HI_COMPILER == HI_CC_MSVC
45 if constexpr (
sizeof(T) ==
sizeof(uint64_t)) {
46 return static_cast<T
>(_byteswap_uint64(
static_cast<uint64_t
>(x)));
47 }
else if constexpr (
sizeof(T) ==
sizeof(
unsigned long)) {
48 return static_cast<T
>(_byteswap_ulong(
static_cast<unsigned long>(x)));
49 }
else if constexpr (
sizeof(T) ==
sizeof(
unsigned short)) {
50 return static_cast<T
>(_byteswap_ushort(
static_cast<unsigned short>(x)));
55 if constexpr (
sizeof(T) == 1) {
59 for (
auto i = 0_uz; i !=
sizeof(T); ++i) {
61 r |=
static_cast<uint8_t
>(x);
68template<std::
signed_
integral T>
69[[nodiscard]]
constexpr T byte_swap(T x)
noexcept
71 return static_cast<T
>(byte_swap(
static_cast<std::make_unsigned_t<T>
>(x)));
74template<std::
floating_po
int T>
75[[nodiscard]]
constexpr T byte_swap(T x)
noexcept
77 if constexpr (std::is_same_v<T, float>) {
78 auto utmp = std::bit_cast<uint32_t>(x);
79 utmp = byte_swap(utmp);
80 return std::bit_cast<float>(x);
81 }
else if constexpr (std::is_same_v<T, double>) {
82 auto utmp = std::bit_cast<uint64_t>(x);
83 utmp = byte_swap(utmp);
84 return std::bit_cast<double>(x);
90template<std::
integral T>
91[[nodiscard]]
constexpr T little_to_native(T x)
93 if constexpr (std::endian::native == std::endian::little) {
100template<std::
integral T>
101[[nodiscard]]
constexpr T big_to_native(T x)
103 if constexpr (std::endian::native == std::endian::big) {
110template<std::
integral T>
111[[nodiscard]]
constexpr T native_to_little(T x)
113 if constexpr (std::endian::native == std::endian::little) {
120template<std::
integral T>
121[[nodiscard]]
constexpr T native_to_big(T x)
123 if constexpr (std::endian::native == std::endian::big) {
130template<numeric T, std::endian Endian = std::endian::native>
131[[nodiscard]]
constexpr T load(T
const *src)
noexcept
134 if constexpr (Endian != std::endian::native) {
135 value = byte_swap(value);
140template<numeric T, std::endian Endian = std::endian::native,
byte_like B>
141[[nodiscard]]
constexpr T load(B
const *src)
noexcept
143 auto value = unaligned_load<T>(src);
144 if constexpr (Endian != std::endian::native) {
145 value = byte_swap(value);
150template<numeric T, std::endian Endian = std::endian::native>
151[[nodiscard]]
inline T load(
void const *src)
noexcept
153 auto value = unaligned_load<T>(src);
154 if constexpr (Endian != std::endian::native) {
155 value = byte_swap(value);
161[[nodiscard]]
constexpr T load_le(T
const *src)
noexcept
163 return load<T, std::endian::little>(src);
166template<numeric T,
byte_like B>
167[[nodiscard]]
constexpr T load_le(B
const *src)
noexcept
169 return load<T, std::endian::little>(src);
173[[nodiscard]]
inline T load_le(
void const *src)
noexcept
175 return load<T, std::endian::little>(src);
179[[nodiscard]]
constexpr T load_be(T
const *src)
noexcept
181 return load<T, std::endian::big>(src);
184template<numeric T,
byte_like B>
185[[nodiscard]]
constexpr T load_be(B
const *src)
noexcept
187 return load<T, std::endian::big>(src);
191[[nodiscard]]
inline T load_be(
void const *src)
noexcept
193 return load<T, std::endian::big>(src);
196template<std::endian Endian = std::endian::native, numeric T,
byte_like B>
197constexpr void store(T value, B
const *dst)
noexcept
199 if constexpr (Endian != std::endian::native) {
200 value = byte_swap(value);
202 unaligned_store<T>(value, dst);
205template<std::endian Endian = std::endian::native, numeric T>
206constexpr void store(T value,
void const *dst)
noexcept
208 if constexpr (Endian != std::endian::native) {
209 value = byte_swap(value);
211 unaligned_store<T>(value, dst);
214template<numeric T,
byte_like B>
215constexpr void store_le(T value, B
const *dst)
noexcept
217 store<std::endian::little>(value, dst);
221inline void store_le(T value,
void const *dst)
noexcept
223 store<std::endian::little>(value, dst);
226template<numeric T,
byte_like B>
227constexpr void store_be(T value, B
const *dst)
noexcept
229 store<std::endian::big>(value, dst);
233inline void store_be(T value,
void const *dst)
noexcept
235 store<std::endian::big>(value, dst);
239template<
typename T, std::endian E, std::
size_t A = alignof(T)>
241 using value_type = T;
242 constexpr static std::endian endian = E;
245 alignas(A) std::byte _value[
sizeof(T)];
247 [[nodiscard]]
constexpr value_type operator*()
const noexcept
249 return load<value_type, endian>(_value);
252 constexpr endian_buf_t& operator=(value_type x)
noexcept
254 store<endian>(x, _value);
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:308
DOXYGEN BUG.
Definition algorithm.hpp:13
Horizontal/Vertical alignment combination.
Definition alignment.hpp:231
Definition endian.hpp:240