7#include "architecture.hpp"
11#if TT_COMPILER == TT_CC_MSVC
18template<
typename T, std::enable_if_t<std::is_
integral_v<T> && std::is_
unsigned_v<T>,
int> = 0>
19[[nodiscard]] T byte_swap(T x)
noexcept
21#if TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
22 if constexpr (
sizeof(T) ==
sizeof(uint64_t)) {
23 return static_cast<T
>(__builtin_bswap64(
static_cast<uint64_t
>(x)));
24 }
else if constexpr (
sizeof(T) ==
sizeof(uint32_t)) {
25 return static_cast<T
>(__builtin_bswap32(
static_cast<uint32_t
>(x)));
26 }
else if constexpr (
sizeof(T) ==
sizeof(uint16_t)) {
27 return static_cast<T
>(__builtin_bswap16(
static_cast<uint16_t
>(x)));
31#elif TT_COMPILER == TT_CC_MSVC
32 if constexpr (
sizeof(T) ==
sizeof(uint64_t)) {
33 return static_cast<T
>(_byteswap_uint64(
static_cast<uint64_t
>(x)));
34 }
else if constexpr (
sizeof(T) ==
sizeof(
unsigned long)) {
35 return static_cast<T
>(_byteswap_ulong(
static_cast<unsigned long>(x)));
36 }
else if constexpr (
sizeof(T) ==
sizeof(
unsigned short)) {
37 return static_cast<T
>(_byteswap_ushort(
static_cast<unsigned short>(x)));
42#error "Byteswap not implemented for this compiler."
46template<
typename T, std::enable_if_t<std::is_
integral_v<T> && std::is_
signed_v<T>,
int> = 0>
47[[nodiscard]] T byte_swap(T x)
noexcept
49 return static_cast<T
>(byte_swap(
static_cast<std::make_unsigned_t<T>
>(x)));
52template<
typename T, std::enable_if_t<std::is_
floating_po
int_v<T>,T> = 0>
53[[nodiscard]] T byte_swap(T x)
noexcept
55 if constexpr (std::is_same_v<T, float>) {
56 auto utmp = std::bit_cast<uint32_t>(x);
57 utmp = byte_swap(utmp);
58 return std::bit_cast<float>(x);
59 }
else if constexpr (std::is_same_v<T, double>) {
60 auto utmp = std::bit_cast<uint64_t>(x);
61 utmp = byte_swap(utmp);
62 return std::bit_cast<double>(x);
68template<
typename T, std::enable_if_t<std::is_
integral_v<T>,
int> = 0>
69[[nodiscard]] T little_to_native(T x)
71 if constexpr (std::endian::native == std::endian::little) {
78template<
typename T, std::enable_if_t<std::is_
integral_v<T>,
int> = 0>
79[[nodiscard]] T big_to_native(T x)
81 if constexpr (std::endian::native == std::endian::big) {
88template<
typename T, std::enable_if_t<std::is_
integral_v<T>,
int> = 0>
89[[nodiscard]] T native_to_little(T x)
91 if constexpr (std::endian::native == std::endian::little) {
98template<
typename T, std::enable_if_t<std::is_
integral_v<T>,
int> = 0>
99[[nodiscard]] T native_to_big(T x)
101 if constexpr (std::endian::native == std::endian::big) {
108template<
typename T,std::endian E,
size_t A=alignof(T)>
110 alignas(A) std::byte _value[
sizeof(T)];
112 [[nodiscard]] T value()
const noexcept {
114 std::memcpy(&aligned_value, &_value[0],
sizeof(T));
116 if constexpr (E == std::endian::native) {
117 return aligned_value;
119 return byte_swap(aligned_value);
125 if constexpr (E == std::endian::native) {
128 aligned_value = byte_swap(x);
130 std::memcpy(&_value[0], &aligned_value,
sizeof(T));
Definition endian.hpp:109