13 inline constexpr
bool BIG = std::endian::native == std::endian::big;
14 inline constexpr
bool LITTLE = std::endian::native == std::endian::little;
15 static_assert(
BIG ||
LITTLE,
"mixed endian not supported");
18 [[nodiscard]]
static inline uint16_t byteswap16(uint16_t
x)
25 return ((
x & 0x00FF) << 8) | ((
x & 0xFF00) >> 8);
30 [[nodiscard]]
static inline uint32_t byteswap32(uint32_t
x)
32 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
35 return __builtin_bswap32(
x);
38 ((
x << 8) & 0x00ff0000) |
39 ((
x >> 8) & 0x0000ff00) |
45 [[nodiscard]]
static inline uint64_t byteswap64(uint64_t
x)
47 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
50 return __builtin_bswap64(
x);
52 return (uint64_t(byteswap32(
x >> 0)) << 32) |
53 (uint64_t(byteswap32(
x >> 32)) << 0);
58 [[nodiscard]]
static inline uint16_t byteswap(uint16_t
x) {
return byteswap16(
x); }
59 [[nodiscard]]
static inline uint32_t byteswap(uint32_t
x) {
return byteswap32(
x); }
60 [[nodiscard]]
static inline uint64_t byteswap(uint64_t
x) {
return byteswap64(
x); }
65 [[nodiscard]]
inline auto operator()(std::integral
auto t)
const {
return t; }
70 [[nodiscard]]
inline auto operator()(std::integral
auto t)
const {
return byteswap(
t); }
77 template<std::
integral T, std::invocable<T> Op>
class EndianT {
81 [[nodiscard]]
inline operator T()
const { Op op;
return op(t); }
122 static_assert(
sizeof(
B16) == 2,
"must have size 2");
123 static_assert(
sizeof(
L16) == 2,
"must have size 2");
124 static_assert(
sizeof(
B32) == 4,
"must have size 4");
125 static_assert(
sizeof(
L32) == 4,
"must have size 4");
126 static_assert(
sizeof(
B64) == 8,
"must have size 8");
127 static_assert(
sizeof(
L64) == 8,
"must have size 8");
128 static_assert(
alignof(
B16) <= 2,
"may have alignment 2");
129 static_assert(
alignof(
L16) <= 2,
"may have alignment 2");
130 static_assert(
alignof(
B32) <= 4,
"may have alignment 4");
131 static_assert(
alignof(
L32) <= 4,
"may have alignment 4");
132 static_assert(
alignof(
B64) <= 8,
"may have alignment 8");
133 static_assert(
alignof(
L64) <= 8,
"may have alignment 8");
139 *
reinterpret_cast<B16*
>(p) =
x;
143 *
reinterpret_cast<L16*
>(p) =
x;
147 *
reinterpret_cast<B32*
>(p) =
x;
151 *
reinterpret_cast<L32*
>(p) =
x;
154 [[nodiscard]]
inline uint16_t
readB16(
const void* p)
156 return *
reinterpret_cast<const B16*
>(p);
158 [[nodiscard]]
inline uint16_t
readL16(
const void* p)
160 return *
reinterpret_cast<const L16*
>(p);
162 [[nodiscard]]
inline uint32_t
readB32(
const void* p)
164 return *
reinterpret_cast<const B32*
>(p);
166 [[nodiscard]]
inline uint32_t
readL32(
const void* p)
168 return *
reinterpret_cast<const L32*
>(p);
178 template<
bool SWAP>
static ALWAYS_INLINE void write_UA(
void* p, std::integral
auto x)
180 if constexpr (SWAP)
x = byteswap(
x);
181 memcpy(p, &
x,
sizeof(
x));
185 write_UA<LITTLE>(p,
x);
193 assert(
x < 0x1000000);
194 auto* v =
static_cast<uint8_t*
>(p);
195 v[0] = (
x >> 0) & 0xff;
196 v[1] = (
x >> 8) & 0xff;
197 v[2] = (
x >> 16) & 0xff;
201 write_UA<LITTLE>(p,
x);
209 write_UA<LITTLE>(p,
x);
216 template<
bool SWAP, std::
integral T> [[nodiscard]]
static ALWAYS_INLINE T read_UA(
const void* p)
219 memcpy(&
x, p,
sizeof(
x));
220 if constexpr (SWAP)
x = byteswap(
x);
225 return read_UA<LITTLE, uint16_t>(p);
229 return read_UA<BIG, uint16_t>(p);
233 const auto* v =
static_cast<const uint8_t*
>(p);
234 return (v[0] << 0) | (v[1] << 8) | (v[2] << 16);
238 return read_UA<LITTLE, uint32_t>(p);
242 return read_UA<BIG, uint32_t>(p);
246 return read_UA<LITTLE, uint64_t>(p);
250 return read_UA<BIG, uint64_t>(p);
258 [[nodiscard]]
inline operator uint16_t()
const {
return read_UA_B16(x); }
266 [[nodiscard]]
inline operator uint16_t()
const {
return read_UA_L16(x); }
282 [[nodiscard]]
inline operator uint32_t()
const {
return read_UA_B32(x); }
290 [[nodiscard]]
inline operator uint32_t()
const {
return read_UA_L32(x); }
296 static_assert(
sizeof(UA_B16) == 2,
"must have size 2");
297 static_assert(
sizeof(UA_L16) == 2,
"must have size 2");
298 static_assert(
sizeof(UA_L24) == 3,
"must have size 3");
299 static_assert(
sizeof(UA_B32) == 4,
"must have size 4");
300 static_assert(
sizeof(UA_L32) == 4,
"must have size 4");
301 static_assert(
alignof(UA_B16) == 1,
"must have alignment 1");
302 static_assert(
alignof(UA_L16) == 1,
"must have alignment 1");
303 static_assert(
alignof(UA_L24) == 1,
"must have alignment 1");
304 static_assert(
alignof(UA_B32) == 1,
"must have alignment 1");
305 static_assert(
alignof(UA_L32) == 1,
"must have alignment 1");
316 template<>
struct Little<uint8_t > {
using type = uint8_t; };
319 template<
typename>
struct Big;
320 template<>
struct Big<uint8_t > {
using type = uint8_t; };
UA_B16 & operator=(uint16_t a)
UA_B32 & operator=(uint32_t a)
UA_L16 & operator=(uint16_t a)
UA_L24 & operator=(uint32_t a)
UA_L32 & operator=(uint32_t a)
uint16_t readB16(const void *p)
ALWAYS_INLINE uint32_t read_UA_L24(const void *p)
ALWAYS_INLINE uint16_t read_UA_B16(const void *p)
void writeB16(void *p, uint16_t x)
ALWAYS_INLINE void write_UA_B32(void *p, uint32_t x)
ALWAYS_INLINE void write_UA_B64(void *p, uint64_t x)
uint32_t readL32(const void *p)
ALWAYS_INLINE void write_UA_L24(void *p, uint32_t x)
ALWAYS_INLINE void write_UA_B16(void *p, uint16_t x)
void writeL32(void *p, uint32_t x)
ALWAYS_INLINE uint64_t read_UA_L64(const void *p)
ALWAYS_INLINE uint32_t read_UA_B32(const void *p)
void writeB32(void *p, uint32_t x)
ALWAYS_INLINE void write_UA_L64(void *p, uint64_t x)
ALWAYS_INLINE uint16_t read_UA_L16(const void *p)
ALWAYS_INLINE uint64_t read_UA_B64(const void *p)
EndianT< uint16_t, ConvBig< BIG > > B16
ALWAYS_INLINE void write_UA_L32(void *p, uint32_t x)
EndianT< uint32_t, ConvBig< BIG > > B32
ALWAYS_INLINE void write_UA_L16(void *p, uint16_t x)
EndianT< uint32_t, ConvLittle< BIG > > L32
uint16_t readL16(const void *p)
uint32_t readB32(const void *p)
EndianT< uint16_t, ConvLittle< BIG > > L16
ALWAYS_INLINE uint32_t read_UA_L32(const void *p)
void writeL16(void *p, uint16_t x)
constexpr KeyMatrixPosition x
Keyboard bindings.
auto operator()(std::integral auto t) const
auto operator()(std::integral auto t) const