12#include "concepts.hpp"
23#if HI_COMPILER == HI_CC_MSVC
33hi_warning_ignore_msvc(26472);
35namespace hi::inline
v1 {
37template<std::
unsigned_
integral T>
38[[nodiscard]] T byte_swap(T x)
noexcept
40#if HI_COMPILER == HI_CC_CLANG || HI_COMPILER == HI_CC_GCC
41 if constexpr (
sizeof(T) ==
sizeof(uint64_t)) {
42 return static_cast<T
>(__builtin_bswap64(
static_cast<uint64_t
>(x)));
43 }
else if constexpr (
sizeof(T) ==
sizeof(uint32_t)) {
44 return static_cast<T
>(__builtin_bswap32(
static_cast<uint32_t
>(x)));
45 }
else if constexpr (
sizeof(T) ==
sizeof(uint16_t)) {
46 return static_cast<T
>(__builtin_bswap16(
static_cast<uint16_t
>(x)));
50#elif HI_COMPILER == HI_CC_MSVC
51 if constexpr (
sizeof(T) ==
sizeof(uint64_t)) {
52 return static_cast<T
>(_byteswap_uint64(
static_cast<uint64_t
>(x)));
53 }
else if constexpr (
sizeof(T) ==
sizeof(
unsigned long)) {
54 return static_cast<T
>(_byteswap_ulong(
static_cast<unsigned long>(x)));
55 }
else if constexpr (
sizeof(T) ==
sizeof(
unsigned short)) {
56 return static_cast<T
>(_byteswap_ushort(
static_cast<unsigned short>(x)));
61#error "Byteswap not implemented for this compiler."
65template<std::
signed_
integral T>
66[[nodiscard]] T byte_swap(T x)
noexcept
68 return static_cast<T
>(byte_swap(
static_cast<std::make_unsigned_t<T>
>(x)));
71template<std::
floating_po
int T>
72[[nodiscard]] T byte_swap(T x)
noexcept
74 if constexpr (std::is_same_v<T, float>) {
75 auto utmp = std::bit_cast<uint32_t>(x);
76 utmp = byte_swap(utmp);
77 return std::bit_cast<float>(x);
78 }
else if constexpr (std::is_same_v<T, double>) {
79 auto utmp = std::bit_cast<uint64_t>(x);
80 utmp = byte_swap(utmp);
81 return std::bit_cast<double>(x);
87template<std::
integral T>
88[[nodiscard]] T little_to_native(T x)
90 if constexpr (std::endian::native == std::endian::little) {
97template<std::
integral T>
98[[nodiscard]] T big_to_native(T x)
100 if constexpr (std::endian::native == std::endian::big) {
107template<std::
integral T>
108[[nodiscard]] T native_to_little(T x)
110 if constexpr (std::endian::native == std::endian::little) {
117template<std::
integral T>
118[[nodiscard]] T native_to_big(T x)
120 if constexpr (std::endian::native == std::endian::big) {
127template<
typename T, std::endian E, std::
size_t A = alignof(T)>
129 alignas(A) std::byte _value[
sizeof(T)];
131 [[nodiscard]] T value()
const noexcept
136 return E == std::endian::native ? x : byte_swap(x);
141 if constexpr (E != std::endian::native) {
154 operator T()
const noexcept
201hi_force_inline T
load(
void const *src)
noexcept
203#if HI_COMPILER == HI_CC_MSVC
204 return *
reinterpret_cast<__unaligned T
const *
>(src);
206#error "missing implementation for load()"
213hi_force_inline T
load_le(
void const *src)
noexcept
215 return little_to_native(load<T>(src));
221hi_force_inline T
load_be(
void const *src)
noexcept
223 return big_to_native(load<T>(src));
231template<std::
unsigned_
integral T>
235 if constexpr (
sizeof(T) == 8) {
236 r = _mm_extract_epi64(_mm_loadu_si64(src), 0);
237 }
else if constexpr (
sizeof(T) == 4) {
238 r = _mm_extract_epi32(_mm_loadu_si32(src), 0);
239 }
else if constexpr (
sizeof(T) == 2) {
240 r = _mm_extract_epi16(_mm_loadu_si16(src), 0);
241 }
else if constexpr (
sizeof(T) == 1) {
242 r = *
reinterpret_cast<uint8_t
const *
>(src);
244 hi_static_no_default();
247 auto src_ =
reinterpret_cast<uint8_t
const *
>(src);
267template<std::
unsigned_
integral T>
268hi_force_inline
void unaligned_load_le(T& r,
void const *src,
size_t size,
size_t offset = 0) noexcept
270 hi_axiom(offset <
sizeof(T));
271 hi_axiom(size <=
sizeof(T));
272 hi_axiom(size + offset <=
sizeof(T));
274 auto src_ =
reinterpret_cast<uint8_t
const *
>(src);
276 hilet first = offset * CHAR_BIT;
277 hilet last = (first + size) * CHAR_BIT;
279 for (
auto i = first; i != last; i += CHAR_BIT) {
280 r |= wide_cast<T>(*src_++) << i;
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
DOXYGEN BUG.
Definition algorithm.hpp:15
hi_force_inline T load(void const *src) noexcept
Load an integer from unaligned memory in native byte-order.
Definition endian.hpp:201
hi_force_inline void unaligned_load_le(T &r, void const *src) noexcept
Load data from memory.
Definition endian.hpp:232
hi_force_inline T load_le(void const *src) noexcept
Load an integer from unaligned memory in little-endian byte-order.
Definition endian.hpp:213
hi_force_inline T load_be(void const *src) noexcept
Load an integer from unaligned memory in big-endian byte-order.
Definition endian.hpp:221
Definition endian.hpp:128