1 #pragma once
2
3 #include <type_traits>
4 #include <byteswap.h>
5 #include <stdint.h>
6
7 static_assert((__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) ||
8 (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__),
9 "Unable to detect endianness");
10
11 enum class endian {
12 little = __ORDER_LITTLE_ENDIAN__,
13 big = __ORDER_BIG_ENDIAN__,
14 native = __BYTE_ORDER__
15 };
16
17 template<typename T>
byteswap(T value)18 constexpr T byteswap(T value) noexcept
19 {
20 static_assert(std::is_integral<T>(), "Type is not integral");
21 static_assert(sizeof(T) == 2 ||
22 sizeof(T) == 4 ||
23 sizeof(T) == 8,
24 "Illegal value size");
25
26 switch (sizeof(T)) {
27 case 2:
28 return bswap_16(value);
29 case 4:
30 return bswap_32(value);
31 case 8:
32 return bswap_64(value);
33 }
34 }
35
36 template<endian E, typename T>
write_endian(T * dst,T val)37 static void write_endian(T* dst, T val)
38 {
39 if constexpr (E != endian::native)
40 val = byteswap(val);
41
42 *dst = val;
43 }
44
write16le(uint16_t * dst,uint16_t val)45 [[maybe_unused]] static void write16le(uint16_t* dst, uint16_t val)
46 {
47 write_endian<endian::little, uint16_t>(dst, val);
48 }
49