HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
endian.hpp
1// Copyright 2019 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/os_detect.hpp"
7#include "TTauri/Foundation/memory.hpp"
8
9#if TT_COMPILER == TT_CC_MSVC
10#include <stdlib.h>
11#endif
12
13namespace tt {
14
15enum class Endian {
16 Little,
17 Big,
18 Native,
19};
20
21#if TT_PROCESSOR == TT_CPU_X64 || TT_PROCESSOR == TT_CPU_ARM
22constexpr Endian endian = Endian::Little;
23#else
24#error "Endian not configured for this processor."
25#endif
26
27template<typename T>
28[[nodiscard]] tt_force_inline std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>,T>
29byte_swap(T x) noexcept
30{
31#if TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
32 if constexpr (sizeof(T) == sizeof(uint64_t)) {
33 return static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(x)));
34 } else if constexpr (sizeof(T) == sizeof(uint32_t)) {
35 return static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(x)));
36 } else if constexpr (sizeof(T) == sizeof(uint16_t)) {
37 return static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(x)));
38 } else {
39 tt_no_default;
40 }
41#elif TT_COMPILER == TT_CC_MSVC
42 if constexpr (sizeof(T) == sizeof(uint64_t)) {
43 return static_cast<T>(_byteswap_uint64(static_cast<uint64_t>(x)));
44 } else if constexpr (sizeof(T) == sizeof(unsigned long)) {
45 return static_cast<T>(_byteswap_ulong(static_cast<unsigned long>(x)));
46 } else if constexpr (sizeof(T) == sizeof(unsigned short)) {
47 return static_cast<T>(_byteswap_ushort(static_cast<unsigned short>(x)));
48 } else {
49 tt_no_default;
50 }
51#else
52#error "Byteswap not implemented for this compiler."
53#endif
54}
55
56template<typename T>
57[[nodiscard]] tt_force_inline std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>,T>
58byte_swap(T x) noexcept
59{
60 return static_cast<T>(byte_swap(static_cast<std::make_unsigned_t<T>>(x)));
61}
62
63template<typename T>
64[[nodiscard]] tt_force_inline std::enable_if_t<std::is_floating_point_v<T>,T>
65byte_swap(T x) noexcept
66{
67 if constexpr (std::is_same_v<T, float>) {
68 auto utmp = bit_cast<uint32_t>(x);
69 utmp = byte_swap(utmp);
70 return bit_cast<float>(x);
71 } else if constexpr (std::is_same_v<T, double>) {
72 auto utmp = bit_cast<uint64_t>(x);
73 utmp = byte_swap(utmp);
74 return bit_cast<double>(x);
75 } else {
76 tt_no_default;
77 }
78}
79
80template<typename T>
81[[nodiscard]] tt_force_inline std::enable_if_t<std::is_integral_v<T>,T>
82little_to_native(T x)
83{
84 if constexpr (endian == Endian::Little) {
85 return x;
86 } else {
87 return byte_swap(x);
88 }
89}
90
91template<typename T>
92[[nodiscard]] tt_force_inline std::enable_if_t<std::is_integral_v<T>,T>
93big_to_native(T x)
94{
95 if constexpr (endian == Endian::Big) {
96 return x;
97 } else {
98 return byte_swap(x);
99 }
100}
101
102template<typename T>
103[[nodiscard]] tt_force_inline std::enable_if_t<std::is_integral_v<T>,T>
104native_to_little(T x)
105{
106 if constexpr (endian == Endian::Little) {
107 return x;
108 } else {
109 return byte_swap(x);
110 }
111}
112
113template<typename T>
114[[nodiscard]] tt_force_inline std::enable_if_t<std::is_integral_v<T>,T>
115native_to_big(T x)
116{
117 if constexpr (endian == Endian::Big) {
118 return x;
119 } else {
120 return byte_swap(x);
121 }
122}
123
124template<typename T,Endian E,size_t A=alignof(T)>
126 alignas(A) std::byte _value[sizeof(T)];
127
128 [[nodiscard]] tt_force_inline T value() const noexcept {
129 T aligned_value;
130 std::memcpy(&aligned_value, &_value[0], sizeof(T));
131
132 if constexpr (E == endian || E == Endian::Native) {
133 return aligned_value;
134 } else {
135 return byte_swap(aligned_value);
136 }
137 }
138
139 tt_force_inline endian_buf_t &operator=(T x) noexcept {
140 T aligned_value;
141 if constexpr (E == endian || E == Endian::Native) {
142 aligned_value = x;
143 } else {
144 aligned_value = byte_swap(x);
145 }
146 std::memcpy(&_value[0], &aligned_value, sizeof(T));
147 return *this;
148 }
149};
150
169
188
189
190}
191
Definition endian.hpp:125
T memcpy(T... args)