|
9 | 9 | #include <cstddef> |
10 | 10 | #include <cstdint> |
11 | 11 | #include <cstring> |
| 12 | +#include <type_traits> |
12 | 13 |
|
13 | 14 | //! Endianness indicator |
14 | 15 | enum class Endian |
@@ -46,24 +47,39 @@ inline Endian host_endian() { return is_little_endian() ? Endian::Little : Endia |
46 | 47 | template <typename T> |
47 | 48 | inline T swap_bytes(T value) |
48 | 49 | { |
| 50 | + static_assert(std::is_trivially_copyable_v<T>, "swap_bytes requires trivially copyable types"); |
| 51 | + |
49 | 52 | if constexpr (sizeof(T) == 1) |
50 | 53 | { |
51 | 54 | return value; |
52 | 55 | } |
| 56 | + |
53 | 57 | else if constexpr (sizeof(T) == 2) |
54 | 58 | { |
55 | | - uint16_t swapped = byte_swap_16(*reinterpret_cast<uint16_t *>(&value)); |
56 | | - return *reinterpret_cast<T *>(&swapped); |
| 59 | + uint16_t tmp = 0; |
| 60 | + std::memcpy(&tmp, &value, sizeof(tmp)); |
| 61 | + tmp = byte_swap_16(tmp); |
| 62 | + T out; |
| 63 | + std::memcpy(&out, &tmp, sizeof(tmp)); |
| 64 | + return out; |
57 | 65 | } |
58 | 66 | else if constexpr (sizeof(T) == 4) |
59 | 67 | { |
60 | | - uint32_t swapped = byte_swap_32(*reinterpret_cast<uint32_t *>(&value)); |
61 | | - return *reinterpret_cast<T *>(&swapped); |
| 68 | + uint32_t tmp = 0; |
| 69 | + std::memcpy(&tmp, &value, sizeof(tmp)); |
| 70 | + tmp = byte_swap_32(tmp); |
| 71 | + T out; |
| 72 | + std::memcpy(&out, &tmp, sizeof(tmp)); |
| 73 | + return out; |
62 | 74 | } |
63 | 75 | else if constexpr (sizeof(T) == 8) |
64 | 76 | { |
65 | | - uint64_t swapped = byte_swap_64(*reinterpret_cast<uint64_t *>(&value)); |
66 | | - return *reinterpret_cast<T *>(&swapped); |
| 77 | + uint64_t tmp = 0; |
| 78 | + std::memcpy(&tmp, &value, sizeof(tmp)); |
| 79 | + tmp = byte_swap_64(tmp); |
| 80 | + T out; |
| 81 | + std::memcpy(&out, &tmp, sizeof(tmp)); |
| 82 | + return out; |
67 | 83 | } |
68 | 84 | else |
69 | 85 | { |
|
0 commit comments