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
201[[nodiscard]] hi_force_inline T
load(
void const *src)
noexcept
203 return load<T>(
reinterpret_cast<uint8_t
const *
>(src));
209hi_force_inline T
load_le(
void const *src)
noexcept
211 return little_to_native(load<T>(src));
217hi_force_inline T
load_be(
void const *src)
noexcept
219 return big_to_native(load<T>(src));
227template<std::
unsigned_
integral T>
231 if constexpr (
sizeof(T) == 8) {
232 r = _mm_extract_epi64(_mm_loadu_si64(src), 0);
233 }
else if constexpr (
sizeof(T) == 4) {
234 r = _mm_extract_epi32(_mm_loadu_si32(src), 0);
235 }
else if constexpr (
sizeof(T) == 2) {
236 r = _mm_extract_epi16(_mm_loadu_si16(src), 0);
237 }
else if constexpr (
sizeof(T) == 1) {
238 r = *
reinterpret_cast<uint8_t
const *
>(src);
243 auto src_ =
reinterpret_cast<uint8_t
const *
>(src);
263template<std::
unsigned_
integral T>
264hi_force_inline
void unaligned_load_le(T& r,
void const *src,
size_t size,
size_t offset = 0) noexcept
268 hi_axiom(size + offset <=
sizeof(T));
270 auto src_ =
reinterpret_cast<uint8_t
const *
>(src);
272 hilet first = offset * CHAR_BIT;
273 hilet last = (first + size) * CHAR_BIT;
275 for (
auto i = first; i != last; i += CHAR_BIT) {
276 r |= wide_cast<T>(*src_++) << i;
Utilities to assert and bound check.
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:181
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:148
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
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:228
hi_force_inline T load_le(void const *src) noexcept
Load an integer from unaligned memory in little-endian byte-order.
Definition endian.hpp:209
hi_force_inline T load_be(void const *src) noexcept
Load an integer from unaligned memory in big-endian byte-order.
Definition endian.hpp:217
Definition endian.hpp:128