mal-packet-weaver
C++20 packet serialization/deserialization library.
Loading...
Searching...
No Matches
endianness.hpp
Go to the documentation of this file.
1#pragma once
2#include <emmintrin.h>
3#include <immintrin.h>
4#include <smmintrin.h>
5#include <tmmintrin.h>
6
7#include <bit>
8
9#include "../library-pch.hpp"
10
11
18{
23 constexpr bool is_big_endian() { return std::endian::native == std::endian::big; }
24
29 constexpr bool is_little_endian() { return std::endian::native == std::endian::little; }
30
36 constexpr bool kIsBigEndian = is_big_endian();
37
44
50 static_assert(kIsBigEndian || kIsLittleEndian, "Unknown endianness");
51
55 enum class CompilerType : uint32_t
56 {
57 kUnknown = 1 << 0,
58 kGCC = 1 << 1,
59 kMSVC = 1 << 2,
60 kICC = 1 << 3
61 };
62
67 constexpr uint32_t compiler_type()
68 {
69 uint32_t result = 0;
70#define MAL_TOOLKIT_DETAIL_ENDIANNES_ICC 0
71#define MAL_TOOLKIT_DETAIL_ENDIANNES_GCC 0
72#define MAL_TOOLKIT_DETAIL_ENDIANNES_MSVC 0
73#if defined(__INTEL_COMPILER) || defined(__ICC)
74 result |= uint32_t(CompilerType::kICC);
75#define MAL_TOOLKIT_DETAIL_ENDIANNES_ICC 1
76#elif defined(__GNUC__)
77 result |= uint32_t(CompilerType::kGCC);
78#define MAL_TOOLKIT_DETAIL_ENDIANNES_GCC 1
79#elif defined(_MSC_VER)
80 result |= uint32_t(CompilerType::kMSVC);
81#define MAL_TOOLKIT_DETAIL_ENDIANNES_MSVC 1
82#endif
83 return result;
84 }
85
89 constexpr uint32_t kCompilerType = compiler_type();
90
95 constexpr bool is_compiler_icc() { return (kCompilerType & uint32_t(CompilerType::kICC)) != 0; }
96
101 constexpr bool is_compiler_gcc() { return (kCompilerType & uint32_t(CompilerType::kGCC)) != 0; }
102
107 constexpr bool is_compiler_msvc() { return (kCompilerType & uint32_t(CompilerType::kMSVC)) != 0; }
108
114 inline uint16_t betole16(uint16_t x)
115 {
116 if constexpr (kIsLittleEndian)
117 {
118 return ((x & 0xFF00u) >> 8u) | ((x & 0x00FFu) << 8u);
119 }
120#if MAL_TOOLKIT_DETAIL_ENDIANNES_ICC
121 return _bswap16(x);
122#elif MAL_TOOLKIT_DETAIL_ENDIANNES_GCC
123 return __builtin_bswap16(x);
124#elif MAL_TOOLKIT_DETAIL_ENDIANNES_MSVC
125 return _byteswap_ushort(x);
126#else
127 return ((x & 0xFF00u) >> 8u) | ((x & 0x00FFu) << 8u);
128#endif
129 }
130
136 inline uint32_t betole32(uint32_t x)
137 {
138 if constexpr (kIsLittleEndian)
139 {
140 return ((x & 0xFF000000u) >> 24u) | ((x & 0x00FF0000u) >> 8u) | ((x & 0x0000FF00u) << 8u) |
141 ((x & 0x000000FFu) << 24u);
142 }
143#if MAL_TOOLKIT_DETAIL_ENDIANNES_ICC
144 return _bswap(x);
145#elif MAL_TOOLKIT_DETAIL_ENDIANNES_GCC
146 return __builtin_bswap32(x);
147#elif MAL_TOOLKIT_DETAIL_ENDIANNES_MSVC
148 return _byteswap_ulong(x);
149#else
150 return ((x & 0xFF000000u) >> 24u) | ((x & 0x00FF0000u) >> 8u) | ((x & 0x0000FF00u) << 8u) |
151 ((x & 0x000000FFu) << 24u);
152#endif
153 }
154
160 uint64_t betole64(uint64_t x)
161 {
162 if constexpr (kIsLittleEndian)
163 {
164 return ((x & 0xFF00000000000000u) >> 56u) | ((x & 0x00FF000000000000u) >> 40u) |
165 ((x & 0x0000FF0000000000u) >> 24u) | ((x & 0x000000FF00000000u) >> 8u) |
166 ((x & 0x00000000FF000000u) << 8u) | ((x & 0x0000000000FF0000u) << 24u) |
167 ((x & 0x000000000000FF00u) << 40u) | ((x & 0x00000000000000FFu) << 56u);
168 }
169#if MAL_TOOLKIT_DETAIL_ENDIANNES_ICC
170 return _bswap64(x);
171#elif MAL_TOOLKIT_DETAIL_ENDIANNES_GCC
172 return __builtin_bswap64(x);
173#elif MAL_TOOLKIT_DETAIL_ENDIANNES_MSVC
174 return _byteswap_uint64(x);
175#else
176 return ((x & 0xFF00000000000000u) >> 56u) | ((x & 0x00FF000000000000u) >> 40u) |
177 ((x & 0x0000FF0000000000u) >> 24u) | ((x & 0x000000FF00000000u) >> 8u) |
178 ((x & 0x00000000FF000000u) << 8u) | ((x & 0x0000000000FF0000u) << 24u) |
179 ((x & 0x000000000000FF00u) << 40u) | ((x & 0x00000000000000FFu) << 56u);
180#endif
181 }
182
188 __m128i betole128(__m128i x)
189 {
190 if constexpr (kIsLittleEndian)
191 {
192 return x;
193 }
194
195 const __m128i shuffle = _mm_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f);
196 return _mm_shuffle_epi8(x, shuffle);
197 }
198
204 __m256i betole256(__m256i x)
205 {
206 if constexpr (kIsLittleEndian)
207 {
208 return x;
209 }
210 const __m256i shuffle =
211 _mm256_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f);
212 return _mm256_shuffle_epi8(x, shuffle);
213 }
214} // namespace mal_toolkit::endianness
Precompiled header (PCH) file for common headers used across the library.
__m128i betole128(__m128i x)
Converts a 128-bit value between big-endian and little-endian using SSE2 intrinsics.
uint16_t betole16(uint16_t x)
Converts a 16-bit value between big-endian and little-endian.
uint64_t betole64(uint64_t x)
Converts a 64-bit value between big-endian and little-endian.
constexpr bool kIsBigEndian
Represents the determined endianness of the system.
constexpr uint32_t compiler_type()
Determines the compiler type used to compile the code.
constexpr bool is_compiler_gcc()
Checks if the code was compiled with GCC (GNU Compiler Collection).
constexpr bool is_compiler_msvc()
Checks if the code was compiled with MSVC (Microsoft Visual C++).
CompilerType
Ensures that the determined endianness is valid.
constexpr bool is_little_endian()
Determines if the system's native endianness is little-endian.
constexpr bool is_big_endian()
Determines if the system's native endianness is big-endian.
constexpr uint32_t kCompilerType
Indicates the compiler type used for the code.
constexpr bool kIsLittleEndian
Represents the determined endianness of the system.
uint32_t betole32(uint32_t x)
Converts a 32-bit value between big-endian and little-endian.
__m256i betole256(__m256i x)
Converts a 256-bit value between big-endian and little-endian using AVX2 intrinsics.
constexpr bool is_compiler_icc()
Checks if the code was compiled with ICC (Intel C++ Compiler).