18#if HI_COMPILER == HI_CC_MSVC
28hi_warning_ignore_msvc(26472);
30namespace hi::inline
v1 {
34template<std::
integral T>
37 if constexpr (std::endian::native == std::endian::little) {
40 return std::byteswap(x);
46template<std::
integral T>
49 if constexpr (std::endian::native == std::endian::big) {
52 return std::byteswap(x);
58template<std::
integral T>
61 if constexpr (std::endian::native == std::endian::little) {
64 return std::byteswap(x);
70template<std::
integral T>
73 if constexpr (std::endian::native == std::endian::big) {
76 return std::byteswap(x);
87template<std::
integral T, std::endian Endian = std::endian::native>
88[[nodiscard]]
constexpr T
load(T
const *src)
noexcept
91 if constexpr (Endian != std::endian::native) {
92 value = std::byteswap(value);
104template<std::
integral T, std::endian Endian = std::endian::native,
byte_like B>
105[[nodiscard]]
constexpr T
load(B
const *src)
noexcept
107 auto value = unaligned_load<T>(src);
108 if constexpr (Endian != std::endian::native) {
109 value = std::byteswap(value);
121template<std::
integral T, std::endian Endian = std::endian::native>
122[[nodiscard]]
inline T
load(
void const *src)
noexcept
124 auto value = unaligned_load<T>(src);
125 if constexpr (Endian != std::endian::native) {
126 value = std::byteswap(value);
137template<std::
integral T>
138[[nodiscard]]
constexpr T
load_le(T
const *src)
noexcept
140 return load<T, std::endian::little>(src);
149template<std::
integral T,
byte_like B>
150[[nodiscard]]
constexpr T
load_le(B
const *src)
noexcept
152 return load<T, std::endian::little>(src);
161template<std::
integral T>
162[[nodiscard]]
inline T
load_le(
void const *src)
noexcept
164 return load<T, std::endian::little>(src);
173template<std::
integral T>
174[[nodiscard]]
constexpr T
load_be(T
const *src)
noexcept
176 return load<T, std::endian::big>(src);
185template<std::
integral T,
byte_like B>
186[[nodiscard]]
constexpr T
load_be(B
const *src)
noexcept
188 return load<T, std::endian::big>(src);
197template<std::
integral T>
198[[nodiscard]]
inline T
load_be(
void const *src)
noexcept
200 return load<T, std::endian::big>(src);
218template<
unsigned int NumBits,
byte_like B>
219[[nodiscard]]
constexpr auto load_bits_be(B
const *src,
size_t bit_index)
noexcept
221 static_assert(NumBits <=
sizeof(
unsigned long long) * CHAR_BIT);
223 constexpr auto num_bits = NumBits;
224 constexpr auto num_bytes = (num_bits + CHAR_BIT - 1) / CHAR_BIT;
229 std::conditional_t<num_bytes <
sizeof(
unsigned short),
unsigned short,
230 std::conditional_t<num_bytes <
sizeof(
unsigned int),
unsigned int,
231 std::conditional_t<num_bytes <
sizeof(
unsigned long),
unsigned long,
unsigned long long>>>;
234 constexpr auto value_bits =
sizeof(value_type) * CHAR_BIT;
236 hilet byte_offset = bit_index / CHAR_BIT;
237 hilet bit_offset = bit_index % CHAR_BIT;
240 if constexpr (num_bits == CHAR_BIT) {
241 if (bit_offset == 0) {
242 return char_cast<value_type>(src[byte_offset]);
253 if constexpr (num_bytes ==
sizeof(value_type)) {
257 auto bits_done = value_bits - bit_offset;
258 if (bits_done < num_bits) {
259 auto rest = char_cast<value_type>(src[byte_offset +
sizeof(value_type)]);
260 rest >>= CHAR_BIT - bit_offset;
266 r >>= value_bits - num_bits;
272template<std::endian Endian = std::endian::native, std::
integral T,
byte_like B>
273constexpr void store(T value, B
const *dst)
noexcept
275 if constexpr (Endian != std::endian::native) {
276 value = std::byteswap(value);
278 unaligned_store<T>(value, dst);
281template<std::endian Endian = std::endian::native, std::
integral T>
282constexpr void store(T value,
void const *dst)
noexcept
284 if constexpr (Endian != std::endian::native) {
285 value = std::byteswap(value);
287 unaligned_store<T>(value, dst);
290template<std::
integral T,
byte_like B>
291constexpr void store_le(T value, B
const *dst)
noexcept
293 store<std::endian::little>(value, dst);
296template<std::
integral T>
297inline void store_le(T value,
void const *dst)
noexcept
299 store<std::endian::little>(value, dst);
302template<std::
integral T,
byte_like B>
303constexpr void store_be(T value, B
const *dst)
noexcept
305 store<std::endian::big>(value, dst);
308template<std::
integral T>
309inline void store_be(T value,
void const *dst)
noexcept
311 store<std::endian::big>(value, dst);
315template<
typename T, std::endian E, std::
size_t A = alignof(T)>
317 using value_type = T;
318 constexpr static std::endian endian = E;
321 alignas(A) std::byte _value[
sizeof(T)];
323 [[nodiscard]]
constexpr value_type operator*()
const noexcept
325 return load<value_type, endian>(_value);
328 constexpr endian_buf_t& operator=(value_type x)
noexcept
330 store<endian>(x, _value);
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
constexpr T big_to_native(T x)
Convert an integral from big-to-native endian.
Definition endian.hpp:47
constexpr T little_to_native(T x)
Convert an integral from little-to-native endian.
Definition endian.hpp:35
constexpr T native_to_big(T x)
Convert an integral from native-to-big endian.
Definition endian.hpp:71
constexpr T load_le(T const *src) noexcept
Load of a numeric value encoded in little-endian format.
Definition endian.hpp:138
constexpr T native_to_little(T x)
Convert an integral from native-to-little endian.
Definition endian.hpp:59
constexpr T load_be(T const *src) noexcept
Load of a numeric value encoded in big-endian format.
Definition endian.hpp:174
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:219
constexpr T load(T const *src) noexcept
Load a numeric value from memory.
Definition endian.hpp:88
Definition endian.hpp:316