1 #ifndef _BITCPY_COMMON_H_ 8 #define _BITCPY_COMMON_H_ 12 #include <type_traits> 17 #if !defined(configBITCPY_COMMON_DISABLE_ATOMIC_FWD_DECL) && !defined(_GLIBCXX_ATOMIC) && !defined(atomic) && !defined(__APPLE__) 20 template <
typename _Tp>
26 #ifndef CONSTEXPR_ABOVE_CPP11 27 #if defined(configBITCPY_DISABLE_CONSTEXPR) || !defined(__cplusplus) || (__cplusplus < 201402L) 28 #define BITCPY_CONSTEXPR_SUPPORTED 0 30 #define CONSTEXPR_ABOVE_CPP11 33 #define BITCPY_CONSTEXPR_SUPPORTED 1 35 #define CONSTEXPR_ABOVE_CPP11 constexpr 42 #ifndef CONSTEXPR_ABOVE_CPP11_AND_NON_LITERAL_STORAGE 43 #if defined(configBITCPY_DISABLE_CONSTEXPR_NON_LIT) || !defined(__cplusplus) || (__cplusplus < 201402L) || defined(__APPLE__) 44 #define BITCPY_CONSTEXPR_NON_LITERAL_STORAGE_SUPPORTED 0 46 #define CONSTEXPR_ABOVE_CPP11_AND_NON_LITERAL_STORAGE 49 #define BITCPY_CONSTEXPR_NON_LITERAL_STORAGE_SUPPORTED 1 51 #define CONSTEXPR_ABOVE_CPP11_AND_NON_LITERAL_STORAGE constexpr 56 #ifdef __SIZEOF_INT128__ 57 #define BITCPY_INT128_CONDITIONAL_DEFINE(...) __VA_ARGS__ 59 #define BITCPY_INT128_CONDITIONAL_DEFINE_C(...) __VA_ARGS__ static_assert(true, "") 62 #define BITCPY_INT128_CONDITIONAL_DEFINE(...) 64 #define BITCPY_INT128_CONDITIONAL_DEFINE_C(...) static_assert(true, "") 76 static constexpr
float version = 1.0;
86 return std::forward<T>(x);
93 struct is_std_atomic : std::false_type
97 struct is_std_atomic<std::atomic<T>> : std::true_type
100 template <
typename T>
101 using requires_unsigned_type =
typename std::enable_if<
102 BITCPY_INT128_CONDITIONAL_DEFINE(
103 std::is_same<T, __uint128_t>::value ||)(!std::is_same<T, char>::value && std::is_integral<T>::value && !std::is_same<T, bool>::value && !std::is_signed<T>::value) ||
104 (std::is_same<T, char>::value && std::is_same<char, uint8_t>::value),
106 template <
typename T>
107 using requires_bool_type =
typename std::enable_if<
108 std::is_same<T, bool>::value,
110 template <
typename T>
111 using requires_non_bool_type =
typename std::enable_if<
112 !std::is_same<T, bool>::value,
114 template <
typename T>
115 using requires_signed_type =
typename std::enable_if<
116 BITCPY_INT128_CONDITIONAL_DEFINE(std::is_same<T, __int128_t>::value ||)(!std::is_same<T, char>::value && std::is_integral<T>::value && !std::is_same<T, bool>::value && std::is_signed<T>::value) ||
117 (std::is_same<T, char>::value && !std::is_same<char, uint8_t>::value),
119 template <
typename T>
120 using requires_large_non_integral_type =
typename std::enable_if<
122 BITCPY_INT128_CONDITIONAL_DEFINE(!std::is_same<T, __uint128_t>::value &&
123 !std::is_same<T, __int128_t>::value &&) !is_sized_pointer<T>::value,
125 template <
typename T>
126 using requires_small_non_integral_type =
typename std::enable_if<
128 BITCPY_INT128_CONDITIONAL_DEFINE(!std::is_same<T, __uint128_t>::value &&
129 !std::is_same<T, __int128_t>::value &&) !std::is_integral<T>::value &&
130 !std::is_same<T, bool>::value &&
131 !is_std_atomic<T>::value &&
132 !is_sized_pointer<T>::value,
134 template <
typename T>
135 using requires_pointer_type =
typename std::enable_if<
136 std::is_pointer<T>::value,
138 template <
typename T>
139 using requires_not_a_pointer_type =
typename std::enable_if<
140 !std::is_pointer<T>::value,
144 struct unsigned_type_sizeof
148 struct unsigned_type_sizeof<1>
150 using type = uint8_t;
153 struct unsigned_type_sizeof<2>
155 using type = uint16_t;
158 struct unsigned_type_sizeof<4>
160 using type = uint32_t;
163 struct unsigned_type_sizeof<8>
165 using type = uint64_t;
167 BITCPY_INT128_CONDITIONAL_DEFINE_C(
169 struct unsigned_type_sizeof<16> {
170 using type = __uint128_t;
172 template <
typename T>
173 __attribute__((
const))
const typename unsigned_type_sizeof<sizeof(T)>::type &reinterpret_as_unsigned(
const T &value) noexcept
175 return *
reinterpret_cast<const typename unsigned_type_sizeof<sizeof(T)>::type *
>(&value);
177 template <
typename T>
178 __attribute__((
const))
const volatile typename unsigned_type_sizeof<sizeof(T)>::type &reinterpret_as_unsigned(
const volatile T &value) noexcept
180 return *
reinterpret_cast<const volatile typename unsigned_type_sizeof<sizeof(T)>::type *
>(&value);
182 template <
typename T>
183 __attribute__((
const))
volatile typename unsigned_type_sizeof<sizeof(T)>::type &reinterpret_as_unsigned(
volatile T &value) noexcept
185 return *
reinterpret_cast<volatile typename unsigned_type_sizeof<sizeof(T)>::type *
>(&value);
187 template <
typename T>
188 __attribute__((
const))
typename unsigned_type_sizeof<sizeof(T)>::type &reinterpret_as_unsigned(T &value) noexcept
190 return *
reinterpret_cast<typename unsigned_type_sizeof<sizeof(T)>::type *
>(&value);
192 template <
typename T>
193 __attribute__((pure)) constexpr T bitmask(
const size_t onecount) noexcept
195 using Tunsigned =
typename std::make_unsigned<T>::type;
196 return static_cast<T
>((
static_cast<Tunsigned
>(~static_cast<Tunsigned>(0u)) >> ((
sizeof(Tunsigned) * 8u) - onecount)) *
static_cast<Tunsigned
>(onecount != 0));
198 BITCPY_INT128_CONDITIONAL_DEFINE_C(
200 __attribute__((pure)) constexpr __int128_t bitmask<__int128_t>(
const size_t onecount) noexcept {
201 using Tunsigned = __uint128_t;
202 return static_cast<Tunsigned
>(-(onecount != 0)) & (
static_cast<Tunsigned
>(-1) >> ((
sizeof(Tunsigned) * 8u) - onecount));
204 __attribute__((pure)) constexpr __uint128_t bitmask<__uint128_t>(
const size_t onecount) noexcept {
205 using Tunsigned = __uint128_t;
206 return static_cast<Tunsigned
>(-(onecount != 0)) & (
static_cast<Tunsigned
>(-1) >> ((
sizeof(Tunsigned) * 8u) - onecount));
208 template <
typename T, requires_
signed_type<T> * =
nullptr>
211 if (bits >=
sizeof(T) * 8u || bits == 0u)
213 const T m =
static_cast<T
>(1u) << (bits - 1u);
215 x = ((x & bitmask<T>(bits)) ^ m) - m;
217 template <
typename T>
218 struct default_bitsize
220 static constexpr
size_t value =
sizeof(T) * 8u;
223 struct default_bitsize<bool>
225 static constexpr
size_t value = 1u;
228 template <
typename T,
typename T2>
231 static_assert(
sizeof(T) == 0,
232 "Use big_endian_memcpy_unsigned instead. Either you tried to use a " 233 "signed type which is not supported, or a type larger than 128bits");
248 return static_cast<uint16_t
>(data[0]) << 8 | static_cast<uint16_t>(data[1]);
253 return (static_cast<uint32_t>(data[0]) << 24) |
254 (
static_cast<uint32_t
>(data[1]) << 16) |
255 (
static_cast<uint32_t
>(data[2]) << 8) |
256 static_cast<uint16_t
>(data[3]);
261 return (static_cast<uint64_t>(data[0]) << 56) |
262 (
static_cast<uint64_t
>(data[1]) << 48) |
263 (
static_cast<uint64_t
>(data[2]) << 40) |
264 (
static_cast<uint64_t
>(data[3]) << 32) |
265 (
static_cast<uint64_t
>(data[4]) << 24) |
266 (
static_cast<uint64_t
>(data[5]) << 16) |
267 (
static_cast<uint64_t
>(data[6]) << 8) |
268 static_cast<uint64_t
>(data[7]);
278 return static_cast<uint8_t
>(data[0] >> 8);
288 return (static_cast<uint32_t>(data[0]) << 16) |
static_cast<uint32_t
>(data[1]);
293 return (static_cast<uint64_t>(data[0]) << 48) |
294 (
static_cast<uint64_t
>(data[1]) << 32) |
295 (
static_cast<uint64_t
>(data[2]) << 16) |
296 static_cast<uint64_t
>(data[3]);
306 return static_cast<uint8_t
>(data[0] >> 24);
311 return static_cast<uint16_t
>(data[0] >> 16);
321 return (static_cast<uint64_t>(data[0]) << 32) |
322 static_cast<uint64_t
>(data[1]);
332 return static_cast<uint8_t
>(data[0] >> 56);
337 return static_cast<uint16_t
>(data[0] >> 48);
342 return static_cast<uint32_t
>(data[0] >> 32);
350 BITCPY_INT128_CONDITIONAL_DEFINE_C(
355 return (static_cast<__uint128_t>(big_endian_memcpy<uint64_t, T2>(data)) << 64) | static_cast<__uint128_t>(big_endian_memcpy<uint64_t, T2>(&data[8 /
sizeof(T2)]));
361 return (static_cast<__uint128_t>(big_endian_memcpy<uint64_t, T2>(data)) << 64) |
static_cast<__uint128_t
>(big_endian_memcpy<uint64_t, T2>(&data[8 /
sizeof(T2)]));
367 return (static_cast<__uint128_t>(big_endian_memcpy<uint64_t, T2>(data)) << 64) |
static_cast<__uint128_t
>(big_endian_memcpy<uint64_t, T2>(&data[8 /
sizeof(T2)]));
373 return (static_cast<__uint128_t>(big_endian_memcpy<uint64_t, T2>(data)) << 64) |
static_cast<__uint128_t
>(big_endian_memcpy<uint64_t, T2>(&data[8 /
sizeof(T2)]));
383 return static_cast<uint64_t
>(data[0] >> 64);
388 return static_cast<uint32_t
>(data[0] >> 96);
393 return static_cast<uint16_t
>(data[0] >> 112);
398 return static_cast<uint8_t
>(data[0] >> 120);
403 template <
typename T,
typename T2>
406 return big_endian_memcpy<
407 typename detail::unsigned_type_sizeof<sizeof(T)>::type,
408 typename detail::unsigned_type_sizeof<sizeof(T2)>::type>(v);
412 #endif // _BITCPY_COMMON_H_ CppSerdes library information.
Definition: bitcpy_common.h:73
CppSerdes library namespace.
Definition: bitcpy_common.h:69
constexpr T bit_length(T &&x) noexcept
Does nothing but annotate a passed value as a bit length, used for writting clearer code...
Definition: bitcpy_common.h:84
Definition: bitcpy_common.h:18
Defines sized_pointer, similar to std::array but with with size as a runtime constant.
#define CONSTEXPR_ABOVE_CPP11
resolves automatically to "constexpr" if C++14 or greater
Definition: bitcpy_common.h:31