HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
endian.hpp
1// Copyright Take Vos 2019-2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "os_detect.hpp"
8#include "memory.hpp"
9#include "assert.hpp"
10
11#if TT_COMPILER == TT_CC_MSVC
12#include <stdlib.h>
13#endif
14#include <bit>
15
16namespace tt {
17
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
20{
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)));
28 } else {
29 tt_no_default();
30 }
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)));
38 } else {
39 tt_no_default();
40 }
41#else
42#error "Byteswap not implemented for this compiler."
43#endif
44}
45
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
48{
49 return static_cast<T>(byte_swap(static_cast<std::make_unsigned_t<T>>(x)));
50}
51
52template<typename T, std::enable_if_t<std::is_floating_point_v<T>,T> = 0>
53[[nodiscard]] T byte_swap(T x) noexcept
54{
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);
63 } else {
64 tt_no_default();
65 }
66}
67
68template<typename T, std::enable_if_t<std::is_integral_v<T>,int> = 0>
69[[nodiscard]] T little_to_native(T x)
70{
71 if constexpr (std::endian::native == std::endian::little) {
72 return x;
73 } else {
74 return byte_swap(x);
75 }
76}
77
78template<typename T, std::enable_if_t<std::is_integral_v<T>,int> = 0>
79[[nodiscard]] T big_to_native(T x)
80{
81 if constexpr (std::endian::native == std::endian::big) {
82 return x;
83 } else {
84 return byte_swap(x);
85 }
86}
87
88template<typename T, std::enable_if_t<std::is_integral_v<T>,int> = 0>
89[[nodiscard]] T native_to_little(T x)
90{
91 if constexpr (std::endian::native == std::endian::little) {
92 return x;
93 } else {
94 return byte_swap(x);
95 }
96}
97
98template<typename T, std::enable_if_t<std::is_integral_v<T>,int> = 0>
99[[nodiscard]] T native_to_big(T x)
100{
101 if constexpr (std::endian::native == std::endian::big) {
102 return x;
103 } else {
104 return byte_swap(x);
105 }
106}
107
108template<typename T,std::endian E,size_t A=alignof(T)>
110 alignas(A) std::byte _value[sizeof(T)];
111
112 [[nodiscard]] T value() const noexcept {
113 T aligned_value;
114 std::memcpy(&aligned_value, &_value[0], sizeof(T));
115
116 if constexpr (E == std::endian::native) {
117 return aligned_value;
118 } else {
119 return byte_swap(aligned_value);
120 }
121 }
122
123 endian_buf_t &operator=(T x) noexcept {
124 T aligned_value;
125 if constexpr (E == std::endian::native) {
126 aligned_value = x;
127 } else {
128 aligned_value = byte_swap(x);
129 }
130 std::memcpy(&_value[0], &aligned_value, sizeof(T));
131 return *this;
132 }
133};
134
153
172
173
174}
175
Definition endian.hpp:109
T memcpy(T... args)