8#include "reflection.hpp"
10#include "../macros.hpp"
14hi_export_module(hikogui.utility.endian);
20hi_warning_ignore_msvc(26472);
22hi_export
namespace hi {
inline namespace v1 {
26template<std::
integral T>
29 if constexpr (std::endian::native == std::endian::little) {
32 return std::byteswap(x);
38template<std::
integral T>
41 if constexpr (std::endian::native == std::endian::big) {
44 return std::byteswap(x);
50template<std::
integral T>
53 if constexpr (std::endian::native == std::endian::little) {
56 return std::byteswap(x);
62template<std::
integral T>
65 if constexpr (std::endian::native == std::endian::big) {
68 return std::byteswap(x);
79template<std::
integral Out, std::endian Endian = std::endian::native,
typename In>
80[[nodiscard]]
constexpr Out
load(In
const *src)
noexcept
82 if constexpr (Endian != std::endian::native) {
83 return std::byteswap(unaligned_load<Out>(src));
85 return unaligned_load<Out>(src);
96template<std::
integral T, std::endian Endian = std::endian::native>
97[[nodiscard]]
inline T
load(
void const *src)
noexcept
99 auto value = unaligned_load<T>(src);
100 if constexpr (Endian != std::endian::native) {
101 value = std::byteswap(value);
112template<std::
integral T>
113[[nodiscard]]
constexpr T
load_le(T
const *src)
noexcept
115 return load<T, std::endian::little>(src);
124template<std::
integral T,
byte_like B>
125[[nodiscard]]
constexpr T
load_le(B
const *src)
noexcept
127 return load<T, std::endian::little>(src);
136template<std::
integral T>
137[[nodiscard]]
inline T
load_le(
void const *src)
noexcept
139 return load<T, std::endian::little>(src);
148template<std::
integral T>
149[[nodiscard]]
constexpr T
load_be(T
const *src)
noexcept
151 return load<T, std::endian::big>(src);
160template<std::
integral T,
byte_like B>
161[[nodiscard]]
constexpr T
load_be(B
const *src)
noexcept
163 return load<T, std::endian::big>(src);
172template<std::
integral T>
173[[nodiscard]]
inline T
load_be(
void const *src)
noexcept
175 return load<T, std::endian::big>(src);
193template<
unsigned int NumBits,
byte_like B>
194[[nodiscard]]
constexpr auto load_bits_be(B
const *src,
size_t bit_index)
noexcept
196 static_assert(NumBits <=
sizeof(
unsigned long long) * CHAR_BIT);
198 constexpr auto num_bits = NumBits;
199 constexpr auto num_bytes = (num_bits + CHAR_BIT - 1) / CHAR_BIT;
204 std::conditional_t<num_bytes <
sizeof(
unsigned short),
unsigned short,
205 std::conditional_t<num_bytes <
sizeof(
unsigned int),
unsigned int,
206 std::conditional_t<num_bytes <
sizeof(
unsigned long),
unsigned long,
unsigned long long>>>;
209 constexpr auto value_bits =
sizeof(value_type) * CHAR_BIT;
211 auto const byte_offset = bit_index / CHAR_BIT;
212 auto const bit_offset = bit_index % CHAR_BIT;
215 if constexpr (num_bits == CHAR_BIT) {
216 if (bit_offset == 0) {
217 return char_cast<value_type>(src[byte_offset]);
228 if constexpr (num_bytes ==
sizeof(value_type)) {
232 auto bits_done = value_bits - bit_offset;
233 if (bits_done < num_bits) {
234 auto rest = char_cast<value_type>(src[byte_offset +
sizeof(value_type)]);
235 rest >>= CHAR_BIT - bit_offset;
241 r >>= value_bits - num_bits;
245template<std::endian Endian = std::endian::native, std::
integral T,
byte_like B>
246constexpr void store(T value, B
const *dst)
noexcept
248 if constexpr (Endian != std::endian::native) {
249 value = std::byteswap(value);
251 unaligned_store<T>(value, dst);
254template<std::endian Endian = std::endian::native, std::
integral T>
255constexpr void store(T value,
void const *dst)
noexcept
257 if constexpr (Endian != std::endian::native) {
258 value = std::byteswap(value);
260 unaligned_store<T>(value, dst);
263template<std::
integral T,
byte_like B>
264constexpr void store_le(T value, B
const *dst)
noexcept
266 store<std::endian::little>(value, dst);
269template<std::
integral T>
270inline void store_le(T value,
void const *dst)
noexcept
272 store<std::endian::little>(value, dst);
275template<std::
integral T,
byte_like B>
276constexpr void store_be(T value, B
const *dst)
noexcept
278 store<std::endian::big>(value, dst);
281template<std::
integral T>
282inline void store_be(T value,
void const *dst)
noexcept
284 store<std::endian::big>(value, dst);
287template<
typename T, std::endian E, std::
size_t A = alignof(T)>
289 using value_type = T;
290 constexpr static std::endian endian = E;
293 alignas(A) std::byte _value[
sizeof(T)];
295 [[nodiscard]]
constexpr value_type operator*()
const noexcept
297 return load<value_type, endian>(_value);
300 constexpr endian_buf_t& operator=(value_type x)
noexcept
302 store<endian>(x, _value);
Functions for casting values between types savely.
The HikoGUI namespace.
Definition array_generic.hpp:20
constexpr T big_to_native(T x)
Convert an integral from big-to-native endian.
Definition endian.hpp:39
constexpr T native_to_little(T x)
Convert an integral from native-to-little endian.
Definition endian.hpp:51
constexpr T load_be(T const *src) noexcept
Load of a numeric value encoded in big-endian format.
Definition endian.hpp:149
constexpr T little_to_native(T x)
Convert an integral from little-to-native endian.
Definition endian.hpp:27
constexpr T load_le(T const *src) noexcept
Load of a numeric value encoded in little-endian format.
Definition endian.hpp:113
constexpr Out load(In const *src) noexcept
Unaligned Load of a numeric value from an array.
Definition endian.hpp:80
constexpr T native_to_big(T x)
Convert an integral from native-to-big endian.
Definition endian.hpp:63
constexpr auto load_bits_be(B const *src, size_t bit_index) noexcept
Unaligned load bits from a big-endian buffer at a bit-offset.
Definition endian.hpp:194
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Horizontal/Vertical alignment combination.
Definition alignment.hpp:244
Definition endian.hpp:288