WIP: Optimize binary conversion
This commit is contained in:
parent
7d6fc9721a
commit
871e06c690
|
@ -4,6 +4,16 @@
|
|||
#include "../global.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
// use std::bit_cast and std::byteswap if available as only GCC is able to optimize the custom bitshift code in all cases
|
||||
// note: Clang 15.0.0 is only able to optimize the bitshift code in getBytes() functions and MSVC 19.10 is not able to
|
||||
// optimize it at all. Unfortunately bit_cast and byteswap are only available in C++20 and 23 respectively so the
|
||||
// custom code needs to stay for compatibility.
|
||||
#if __cplusplus >= 202002L
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
// detect byte order according to __BYTE_ORDER__
|
||||
#if defined(__BYTE_ORDER__)
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
#error "Do not include binaryconversionprivate.h directly."
|
||||
#else
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// disable warnings about sign conversions when using GCC or Clang
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -18,10 +14,18 @@
|
|||
CPP_UTILITIES_EXPORT constexpr std::int16_t toInt16(const char *value)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_byteswap)
|
||||
return std::byteswap(std::bit_cast<std::int16_t>(value));
|
||||
#else
|
||||
return static_cast<std::int16_t>((static_cast<std::int16_t>(value[0]) << 8 & 0xFF00) | (static_cast<std::int16_t>(value[1]) & 0x00FF));
|
||||
#endif
|
||||
#else
|
||||
#if defined(__cpp_lib_bit_cast)
|
||||
return std::bit_cast<std::int16_t>(value);
|
||||
#else
|
||||
return static_cast<std::int16_t>((static_cast<std::int16_t>(value[1]) << 8 & 0xFF00) | (static_cast<std::int16_t>(value[0]) & 0x00FF));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -30,10 +34,18 @@ CPP_UTILITIES_EXPORT constexpr std::int16_t toInt16(const char *value)
|
|||
CPP_UTILITIES_EXPORT constexpr std::uint16_t toUInt16(const char *value)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_byteswap)
|
||||
return std::byteswap(std::bit_cast<std::uint16_t>(value));
|
||||
#else
|
||||
return static_cast<std::uint16_t>((static_cast<std::uint16_t>(value[0]) << 8 & 0xFF00) | (static_cast<std::uint16_t>(value[1]) & 0x00FF));
|
||||
#endif
|
||||
#else
|
||||
#if defined(__cpp_lib_bit_cast)
|
||||
return std::bit_cast<std::uint16_t>(value);
|
||||
#else
|
||||
return static_cast<std::uint16_t>((static_cast<std::uint16_t>(value[1]) << 8 & 0xFF00) | (static_cast<std::uint16_t>(value[0]) & 0x00FF));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -42,14 +54,22 @@ CPP_UTILITIES_EXPORT constexpr std::uint16_t toUInt16(const char *value)
|
|||
CPP_UTILITIES_EXPORT constexpr std::int32_t toInt32(const char *value)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_byteswap)
|
||||
return std::byteswap(std::bit_cast<std::int32_t>(value));
|
||||
#else
|
||||
return static_cast<std::int32_t>((static_cast<std::int32_t>(value[0]) << 24 & 0xFF000000)
|
||||
| (static_cast<std::int32_t>(value[1]) << 16 & 0x00FF0000) | (static_cast<std::int32_t>(value[2]) << 8 & 0x0000FF00)
|
||||
| (static_cast<std::int32_t>(value[3]) & 0x000000FF));
|
||||
#endif
|
||||
#else
|
||||
#if defined(__cpp_lib_bit_cast)
|
||||
return std::bit_cast<std::int32_t>(value);
|
||||
#else
|
||||
return static_cast<std::int32_t>((static_cast<std::int32_t>(value[3]) << 24 & 0xFF000000)
|
||||
| (static_cast<std::int32_t>(value[2]) << 16 & 0x00FF0000) | (static_cast<std::int32_t>(value[1]) << 8 & 0x0000FF00)
|
||||
| (static_cast<std::int32_t>(value[0]) & 0x000000FF));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -72,11 +92,32 @@ CPP_UTILITIES_EXPORT constexpr std::uint32_t toUInt24(const char *value)
|
|||
CPP_UTILITIES_EXPORT constexpr std::uint32_t toUInt32(const char *value)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
return (static_cast<std::uint32_t>(value[0]) << 24 & 0xFF000000) | (static_cast<std::uint32_t>(value[1]) << 16 & 0x00FF0000)
|
||||
| (static_cast<std::uint32_t>(value[2]) << 8 & 0x0000FF00) | (static_cast<std::uint32_t>(value[3]) & 0x000000FF);
|
||||
#if __cplusplus >= 202002L
|
||||
if (std::is_constant_evaluated()) {
|
||||
#endif
|
||||
return (static_cast<std::uint32_t>(value[0]) << 24 & 0xFF000000) | (static_cast<std::uint32_t>(value[1]) << 16 & 0x00FF0000)
|
||||
| (static_cast<std::uint32_t>(value[2]) << 8 & 0x0000FF00) | (static_cast<std::uint32_t>(value[3]) & 0x000000FF);
|
||||
#if __cplusplus >= 202002L
|
||||
} else {
|
||||
auto dst = std::uint32_t();
|
||||
std::memcpy(&dst, value, sizeof(dst));
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
return (static_cast<std::uint32_t>(value[3]) << 24 & 0xFF000000) | (static_cast<std::uint32_t>(value[2]) << 16 & 0x00FF0000)
|
||||
| (static_cast<std::uint32_t>(value[1]) << 8 & 0x0000FF00) | (static_cast<std::uint32_t>(value[0]) & 0x000000FF);
|
||||
#if __cplusplus >= 202002L
|
||||
if (std::is_constant_evaluated()) {
|
||||
#endif
|
||||
return (static_cast<std::uint32_t>(value[3]) << 24 & 0xFF000000) | (static_cast<std::uint32_t>(value[2]) << 16 & 0x00FF0000)
|
||||
| (static_cast<std::uint32_t>(value[1]) << 8 & 0x0000FF00) | (static_cast<std::uint32_t>(value[0]) & 0x000000FF);
|
||||
#if __cplusplus >= 202002L
|
||||
} else {
|
||||
|
||||
auto dst = std::uint32_t();
|
||||
std::memcpy(&dst, value, sizeof(dst));
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -86,16 +127,24 @@ CPP_UTILITIES_EXPORT constexpr std::uint32_t toUInt32(const char *value)
|
|||
CPP_UTILITIES_EXPORT constexpr std::int64_t toInt64(const char *value)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_byteswap)
|
||||
return std::byteswap(std::bit_cast<std::int64_t>(value));
|
||||
#else
|
||||
return (static_cast<std::int64_t>(value[0]) << 56 & 0xFF00000000000000) | (static_cast<std::int64_t>(value[1]) << 48 & 0x00FF000000000000)
|
||||
| (static_cast<std::int64_t>(value[2]) << 40 & 0x0000FF0000000000) | (static_cast<std::int64_t>(value[3]) << 32 & 0x000000FF00000000)
|
||||
| (static_cast<std::int64_t>(value[4]) << 24 & 0x00000000FF000000) | (static_cast<std::int64_t>(value[5]) << 16 & 0x0000000000FF0000)
|
||||
| (static_cast<std::int64_t>(value[6]) << 8 & 0x000000000000FF00) | (static_cast<std::int64_t>(value[7]) & 0x00000000000000FF);
|
||||
#endif
|
||||
#else
|
||||
#if defined(__cpp_lib_bit_cast)
|
||||
return std::bit_cast<std::int64_t>(value); // wrong, this would return pointer value
|
||||
#else
|
||||
return (static_cast<std::int64_t>(value[7]) << 56 & 0xFF00000000000000) | (static_cast<std::int64_t>(value[6]) << 48 & 0x00FF000000000000)
|
||||
| (static_cast<std::int64_t>(value[5]) << 40 & 0x0000FF0000000000) | (static_cast<std::int64_t>(value[4]) << 32 & 0x000000FF00000000)
|
||||
| (static_cast<std::int64_t>(value[3]) << 24 & 0x00000000FF000000) | (static_cast<std::int64_t>(value[2]) << 16 & 0x0000000000FF0000)
|
||||
| (static_cast<std::int64_t>(value[1]) << 8 & 0x000000000000FF00) | (static_cast<std::int64_t>(value[0]) & 0x00000000000000FF);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -104,16 +153,24 @@ CPP_UTILITIES_EXPORT constexpr std::int64_t toInt64(const char *value)
|
|||
CPP_UTILITIES_EXPORT constexpr std::uint64_t toUInt64(const char *value)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_byteswap)
|
||||
return std::byteswap(std::bit_cast<std::uint64_t>(value));
|
||||
#else
|
||||
return (static_cast<std::uint64_t>(value[0]) << 56 & 0xFF00000000000000) | (static_cast<std::uint64_t>(value[1]) << 48 & 0x00FF000000000000)
|
||||
| (static_cast<std::uint64_t>(value[2]) << 40 & 0x0000FF0000000000) | (static_cast<std::uint64_t>(value[3]) << 32 & 0x000000FF00000000)
|
||||
| (static_cast<std::uint64_t>(value[4]) << 24 & 0x00000000FF000000) | (static_cast<std::uint64_t>(value[5]) << 16 & 0x0000000000FF0000)
|
||||
| (static_cast<std::uint64_t>(value[6]) << 8 & 0x000000000000FF00) | (static_cast<std::uint64_t>(value[7]) & 0x00000000000000FF);
|
||||
#endif
|
||||
#else
|
||||
#if defined(__cpp_lib_bit_cast)
|
||||
return std::bit_cast<std::uint64_t>(value);
|
||||
#else
|
||||
return (static_cast<std::uint64_t>(value[7]) << 56 & 0xFF00000000000000) | (static_cast<std::uint64_t>(value[6]) << 48 & 0x00FF000000000000)
|
||||
| (static_cast<std::uint64_t>(value[5]) << 40 & 0x0000FF0000000000) | (static_cast<std::uint64_t>(value[4]) << 32 & 0x000000FF00000000)
|
||||
| (static_cast<std::uint64_t>(value[3]) << 24 & 0x00000000FF000000) | (static_cast<std::uint64_t>(value[2]) << 16 & 0x0000000000FF0000)
|
||||
| (static_cast<std::uint64_t>(value[1]) << 8 & 0x000000000000FF00) | (static_cast<std::uint64_t>(value[0]) & 0x00000000000000FF);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -142,11 +199,15 @@ CPP_UTILITIES_EXPORT inline double toFloat64(const char *value)
|
|||
CPP_UTILITIES_EXPORT inline void getBytes(std::int16_t value, char *outputbuffer)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_byteswap)
|
||||
value = std::byteswap(value);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#else
|
||||
outputbuffer[0] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value)&0xFF);
|
||||
#endif
|
||||
#else
|
||||
outputbuffer[1] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[0] = static_cast<char>((value)&0xFF);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -156,11 +217,15 @@ CPP_UTILITIES_EXPORT inline void getBytes(std::int16_t value, char *outputbuffer
|
|||
CPP_UTILITIES_EXPORT inline void getBytes(std::uint16_t value, char *outputbuffer)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_byteswap)
|
||||
value = std::byteswap(value);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#else
|
||||
outputbuffer[0] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value)&0xFF);
|
||||
#endif
|
||||
#else
|
||||
outputbuffer[1] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[0] = static_cast<char>((value)&0xFF);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -187,15 +252,17 @@ CPP_UTILITIES_EXPORT inline void getBytes24(std::uint32_t value, char *outputbuf
|
|||
CPP_UTILITIES_EXPORT inline void getBytes(std::int32_t value, char *outputbuffer)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_byteswap)
|
||||
value = std::byteswap(value);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#else
|
||||
outputbuffer[0] = static_cast<char>((value >> 24) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[3] = static_cast<char>((value)&0xFF);
|
||||
#endif
|
||||
#else
|
||||
outputbuffer[3] = static_cast<char>((value >> 24) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[0] = static_cast<char>((value)&0xFF);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -205,15 +272,17 @@ CPP_UTILITIES_EXPORT inline void getBytes(std::int32_t value, char *outputbuffer
|
|||
CPP_UTILITIES_EXPORT inline void getBytes(std::uint32_t value, char *outputbuffer)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_byteswap)
|
||||
value = std::byteswap(value);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#else
|
||||
outputbuffer[0] = static_cast<char>((value >> 24) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[3] = static_cast<char>((value)&0xFF);
|
||||
#endif
|
||||
#else
|
||||
outputbuffer[3] = static_cast<char>((value >> 24) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[0] = static_cast<char>((value)&0xFF);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -223,6 +292,10 @@ CPP_UTILITIES_EXPORT inline void getBytes(std::uint32_t value, char *outputbuffe
|
|||
CPP_UTILITIES_EXPORT inline void getBytes(std::int64_t value, char *outputbuffer)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_byteswap)
|
||||
value = std::byteswap(value);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#else
|
||||
outputbuffer[0] = static_cast<char>((value >> 56) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 48) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 40) & 0xFF);
|
||||
|
@ -231,15 +304,9 @@ CPP_UTILITIES_EXPORT inline void getBytes(std::int64_t value, char *outputbuffer
|
|||
outputbuffer[5] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[6] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[7] = static_cast<char>((value)&0xFF);
|
||||
#endif
|
||||
#else
|
||||
outputbuffer[7] = static_cast<char>((value >> 56) & 0xFF);
|
||||
outputbuffer[6] = static_cast<char>((value >> 48) & 0xFF);
|
||||
outputbuffer[5] = static_cast<char>((value >> 40) & 0xFF);
|
||||
outputbuffer[4] = static_cast<char>((value >> 32) & 0xFF);
|
||||
outputbuffer[3] = static_cast<char>((value >> 24) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[0] = static_cast<char>((value)&0xFF);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -249,6 +316,10 @@ CPP_UTILITIES_EXPORT inline void getBytes(std::int64_t value, char *outputbuffer
|
|||
CPP_UTILITIES_EXPORT inline void getBytes(std::uint64_t value, char *outputbuffer)
|
||||
{
|
||||
#if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0
|
||||
#if defined(__cpp_lib_byteswap)
|
||||
value = std::byteswap(value);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#else
|
||||
outputbuffer[0] = static_cast<char>((value >> 56) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 48) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 40) & 0xFF);
|
||||
|
@ -257,15 +328,9 @@ CPP_UTILITIES_EXPORT inline void getBytes(std::uint64_t value, char *outputbuffe
|
|||
outputbuffer[5] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[6] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[7] = static_cast<char>((value)&0xFF);
|
||||
#endif
|
||||
#else
|
||||
outputbuffer[7] = static_cast<char>((value >> 56) & 0xFF);
|
||||
outputbuffer[6] = static_cast<char>((value >> 48) & 0xFF);
|
||||
outputbuffer[5] = static_cast<char>((value >> 40) & 0xFF);
|
||||
outputbuffer[4] = static_cast<char>((value >> 32) & 0xFF);
|
||||
outputbuffer[3] = static_cast<char>((value >> 24) & 0xFF);
|
||||
outputbuffer[2] = static_cast<char>((value >> 16) & 0xFF);
|
||||
outputbuffer[1] = static_cast<char>((value >> 8) & 0xFF);
|
||||
outputbuffer[0] = static_cast<char>((value)&0xFF);
|
||||
std::memcpy(outputbuffer, &value, sizeof(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue