Replace serial byteswap macros with constexpr function
This allows taking the input by-value instead of by-reference, while still protecting against unwanted type conversion. Add some basic static_assert tests that the swapped values are correct.
This commit is contained in:
parent
71b4c11f8c
commit
cf2c7bbe80
|
@ -489,50 +489,53 @@ public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
message(Args &&... args) -> message<Args && ...>;
|
message(Args &&... args) -> message<Args && ...>;
|
||||||
|
|
||||||
#define SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_BUILTIN(HBITS,BITS) \
|
template <typename T>
|
||||||
static constexpr uint##BITS##_t bswap(const uint##BITS##_t &u) \
|
static constexpr T bswap(const T u)
|
||||||
{ \
|
|
||||||
return __builtin_bswap##BITS(u); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_EXPLICIT(HBITS,BITS) \
|
|
||||||
static constexpr uint##BITS##_t bswap(const uint##BITS##_t &u) \
|
|
||||||
{ \
|
|
||||||
return (static_cast<uint##BITS##_t>(bswap(static_cast<uint##HBITS##_t>(u))) << HBITS) | \
|
|
||||||
static_cast<uint##BITS##_t>(bswap(static_cast<uint##HBITS##_t>(u >> HBITS))); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SERIAL_DEFINE_SIZE_SPECIFIC_BSWAP(HBITS,BITS) \
|
|
||||||
SERIAL_DEFINE_SIZE_SPECIFIC_USWAP(HBITS,BITS); \
|
|
||||||
static constexpr int##BITS##_t bswap(const int##BITS##_t &i) \
|
|
||||||
{ \
|
|
||||||
return bswap(static_cast<uint##BITS##_t>(i)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr uint8_t bswap(const uint8_t &u)
|
|
||||||
{
|
{
|
||||||
return u;
|
if constexpr (std::is_same<T, int8_t>::value || std::is_same<T, uint8_t>::value)
|
||||||
}
|
/* Swapping a byte-sized value is a no-op. This is permitted here so
|
||||||
|
* that callers can swap without checking the size of the value.
|
||||||
static constexpr int8_t bswap(const int8_t &u)
|
*/
|
||||||
{
|
return u;
|
||||||
return u;
|
if constexpr (std::is_same<T, int16_t>::value || std::is_same<T, uint16_t>::value)
|
||||||
}
|
{
|
||||||
|
|
||||||
#ifdef DXX_HAVE_BUILTIN_BSWAP
|
#ifdef DXX_HAVE_BUILTIN_BSWAP
|
||||||
#define SERIAL_DEFINE_SIZE_SPECIFIC_USWAP SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_BUILTIN
|
return __builtin_bswap16(u);
|
||||||
#else
|
#else
|
||||||
#define SERIAL_DEFINE_SIZE_SPECIFIC_USWAP SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_EXPLICIT
|
return (static_cast<T>(static_cast<uint8_t>(u)) << 8) | static_cast<T>(static_cast<uint8_t>(u >> 8));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
if constexpr (std::is_same<T, int32_t>::value || std::is_same<T, uint32_t>::value)
|
||||||
|
{
|
||||||
|
#ifdef DXX_HAVE_BUILTIN_BSWAP
|
||||||
|
return __builtin_bswap32(u);
|
||||||
|
#else
|
||||||
|
return (static_cast<T>(bswap(static_cast<uint16_t>(u))) << 16) | static_cast<T>(bswap(static_cast<uint16_t>(u >> 16)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if constexpr (std::is_same<T, int64_t>::value || std::is_same<T, uint64_t>::value)
|
||||||
|
{
|
||||||
|
#ifdef DXX_HAVE_BUILTIN_BSWAP
|
||||||
|
return __builtin_bswap64(u);
|
||||||
|
#else
|
||||||
|
return (static_cast<T>(bswap(static_cast<uint32_t>(u))) << 32) | static_cast<T>(bswap(static_cast<uint32_t>(u >> 32)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* Unsupported type. Fall off the end of the function and trigger a
|
||||||
|
* compile error due to the missing `return` statement.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
SERIAL_DEFINE_SIZE_SPECIFIC_BSWAP(8, 16);
|
assert_equal(bswap(static_cast<uint8_t>(1)), 1, "");
|
||||||
SERIAL_DEFINE_SIZE_SPECIFIC_BSWAP(16, 32);
|
|
||||||
SERIAL_DEFINE_SIZE_SPECIFIC_BSWAP(32, 64);
|
|
||||||
|
|
||||||
#undef SERIAL_DEFINE_SIZE_SPECIFIC_BSWAP
|
assert_equal(bswap(static_cast<uint16_t>(0x12)), 0x1200, "");
|
||||||
#undef SERIAL_DEFINE_SIZE_SPECIFIC_USWAP
|
assert_equal(bswap(static_cast<uint16_t>(0x92)), 0x9200, "");
|
||||||
#undef SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_BUILTIN
|
assert_equal(bswap(static_cast<uint16_t>(0x9200)), 0x92, "");
|
||||||
#undef SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_EXPLICIT
|
assert_equal(bswap(static_cast<uint16_t>(0x102)), 0x201, "");
|
||||||
|
|
||||||
|
assert_equal(bswap(static_cast<uint32_t>(0x102)), 0x2010000, "");
|
||||||
|
|
||||||
|
assert_equal(bswap(static_cast<uint64_t>(0x102)), 0x201000000000000ull, "");
|
||||||
|
|
||||||
namespace reader {
|
namespace reader {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue