endian: add float byteswap specialisation
This commit is contained in:
parent
aff4786409
commit
d8bb00c9c3
@ -495,6 +495,7 @@ if (TESTS)
|
|||||||
crypto/tea
|
crypto/tea
|
||||||
crypto/xtea
|
crypto/xtea
|
||||||
crypto/xxtea
|
crypto/xxtea
|
||||||
|
endian
|
||||||
exe
|
exe
|
||||||
extent
|
extent
|
||||||
fixed
|
fixed
|
||||||
|
33
endian.hpp
33
endian.hpp
@ -33,7 +33,7 @@ namespace util {
|
|||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T
|
constexpr T
|
||||||
bswap (T);
|
bswap (T) noexcept;
|
||||||
|
|
||||||
// CXX: Update using "if constexpr" when available. It doesn't seem to be
|
// CXX: Update using "if constexpr" when available. It doesn't seem to be
|
||||||
// worth the dicking about to use enable_if_t to differentiate the
|
// worth the dicking about to use enable_if_t to differentiate the
|
||||||
@ -42,7 +42,7 @@ namespace util {
|
|||||||
template <> \
|
template <> \
|
||||||
constexpr \
|
constexpr \
|
||||||
int##S##_t \
|
int##S##_t \
|
||||||
bswap (int##S##_t v) { \
|
bswap (int##S##_t v) noexcept { \
|
||||||
const union { \
|
const union { \
|
||||||
int##S##_t s; \
|
int##S##_t s; \
|
||||||
uint##S##_t u; \
|
uint##S##_t u; \
|
||||||
@ -55,12 +55,31 @@ namespace util {
|
|||||||
SIGNED_BSWAP(32)
|
SIGNED_BSWAP(32)
|
||||||
SIGNED_BSWAP(64)
|
SIGNED_BSWAP(64)
|
||||||
|
|
||||||
template <> constexpr int8_t bswap ( int8_t v) { return v; }
|
template <> constexpr int8_t bswap ( int8_t v) noexcept { return v; }
|
||||||
template <> constexpr uint8_t bswap (uint8_t v) { return v; }
|
template <> constexpr uint8_t bswap (uint8_t v) noexcept { return v; }
|
||||||
|
|
||||||
template <> constexpr uint16_t bswap (uint16_t v) { return __builtin_bswap16 (v); }
|
template <> constexpr uint16_t bswap (uint16_t v) noexcept { return __builtin_bswap16 (v); }
|
||||||
template <> constexpr uint32_t bswap (uint32_t v) { return __builtin_bswap32 (v); }
|
template <> constexpr uint32_t bswap (uint32_t v) noexcept { return __builtin_bswap32 (v); }
|
||||||
template <> constexpr uint64_t bswap (uint64_t v) { return __builtin_bswap64 (v); }
|
template <> constexpr uint64_t bswap (uint64_t v) noexcept { return __builtin_bswap64 (v); }
|
||||||
|
|
||||||
|
|
||||||
|
// use a type-punning union to punt the byte swapping operation to the
|
||||||
|
// unsigned integer code.
|
||||||
|
//
|
||||||
|
// this is debatably safe under production compilers like gcc + clang
|
||||||
|
// despite what the standard may say about unions.
|
||||||
|
template <>
|
||||||
|
constexpr float
|
||||||
|
bswap (float v) noexcept
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
float f;
|
||||||
|
uint32_t u;
|
||||||
|
} temp { .f = v };
|
||||||
|
|
||||||
|
temp.u = bswap (temp.u);
|
||||||
|
return temp.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
31
test/endian.cpp
Normal file
31
test/endian.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "tap.hpp"
|
||||||
|
|
||||||
|
#include "endian.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
util::TAP::logger tap;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t a = 0x12345678, b = 0x78563412;
|
||||||
|
tap.expect_eq (a, util::bswap (b), "u32 byteswap");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// try to byte swap the pattern for 1.0f
|
||||||
|
//
|
||||||
|
// it may not be the most robust test, but it'll catch the most
|
||||||
|
// egregious errors for the time being.
|
||||||
|
union {
|
||||||
|
uint32_t u;
|
||||||
|
float f;
|
||||||
|
} data { .u = 0x0000803f /* 0x3f800000 == 1.f */ };
|
||||||
|
|
||||||
|
tap.expect_eq (util::bswap (data.f), 1.f, "f32 byteswap");
|
||||||
|
};
|
||||||
|
|
||||||
|
return tap.status ();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user