From 78c096e20a0ce97ebdc1911e9a40fd0dd087e1ad Mon Sep 17 00:00:00 2001 From: Martchus Date: Tue, 23 Feb 2016 19:27:46 +0100 Subject: [PATCH] added functions to swap the byte order --- conversion/binaryconversion.h | 92 ++++++++++++++++++++++++++++------- tests/conversiontests.cpp | 20 ++++++++ 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/conversion/binaryconversion.h b/conversion/binaryconversion.h index b6c0a52..aca5e1a 100644 --- a/conversion/binaryconversion.h +++ b/conversion/binaryconversion.h @@ -5,14 +5,22 @@ #include "../application/global.h" -#if defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) +#ifdef __BYTE_ORDER__ # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true +# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN # elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__ -# define CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false +# define CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN # elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false +# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN # endif +#endif +#ifdef __FLOAT_WORD_ORDER__ # if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__ # define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN # elif __FLOAT_WORD_ORDER__ == __ORDER_PDP_ENDIAN__ @@ -20,14 +28,30 @@ # elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__ # define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN # endif -#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) || defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) || defined(_WIN32_WCE) || defined(WINAPI_FAMILY) -# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN -#elif defined(__MIPSEB__) || defined(__s390__) || defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN) -# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN +#endif +#if defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) #else -# error "Unable to determine byte order!" +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) || defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) || defined(_WIN32_WCE) || defined(WINAPI_FAMILY) +# ifndef __BYTE_ORDER__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false +# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN +# endif +# ifndef __FLOAT_WORD_ORDER__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN +# endif +# elif defined(__MIPSEB__) || defined(__s390__) || defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN) +# ifndef __BYTE_ORDER__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true +# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN +# endif +# ifndef __FLOAT_WORD_ORDER__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN +# endif +# else +# error "Unable to determine byte order!" +# endif #endif #if defined(CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN) @@ -82,7 +106,7 @@ namespace LE { /*! * \brief Returns the 8.8 fixed point representation converted from the specified 32-bit floating point number. */ -LIB_EXPORT inline uint16 toFixed8(float32 float32value) +LIB_EXPORT constexpr uint16 toFixed8(float32 float32value) { return static_cast(float32value * 256.0f); } @@ -90,7 +114,7 @@ LIB_EXPORT inline uint16 toFixed8(float32 float32value) /*! * \brief Returns a 32-bit floating point number converted from the specified 8.8 fixed point representation. */ -LIB_EXPORT inline float32 toFloat32(uint16 fixed8value) +LIB_EXPORT constexpr float32 toFloat32(uint16 fixed8value) { return static_cast(fixed8value) / 256.0f; } @@ -98,7 +122,7 @@ LIB_EXPORT inline float32 toFloat32(uint16 fixed8value) /*! * \brief Returns the 16.16 fixed point representation converted from the specified 32-bit floating point number. */ -LIB_EXPORT inline uint32 toFixed16(float32 float32value) +LIB_EXPORT constexpr uint32 toFixed16(float32 float32value) { return static_cast(float32value * 65536.0f); } @@ -106,7 +130,7 @@ LIB_EXPORT inline uint32 toFixed16(float32 float32value) /*! * \brief Returns a 32-bit floating point number converted from the specified 16.16 fixed point representation. */ -LIB_EXPORT inline float32 toFloat32(uint32 fixed16value) +LIB_EXPORT constexpr float32 toFloat32(uint32 fixed16value) { return static_cast(fixed16value) / 65536.0f; } @@ -116,7 +140,7 @@ LIB_EXPORT inline float32 toFloat32(uint32 fixed16value) * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. * \sa ID3 tag version 2.4.0 - Main Structure */ -LIB_EXPORT inline uint32 toSynchsafeInt(uint32 normalInt) +LIB_EXPORT constexpr uint32 toSynchsafeInt(uint32 normalInt) { return ((normalInt & 0x0000007fu) ) | ((normalInt & 0x00003f80u) << 1) @@ -129,7 +153,7 @@ LIB_EXPORT inline uint32 toSynchsafeInt(uint32 normalInt) * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. * \sa ID3 tag version 2.4.0 - Main Structure */ -LIB_EXPORT inline uint32 toNormalInt(uint32 synchsafeInt) +LIB_EXPORT constexpr uint32 toNormalInt(uint32 synchsafeInt) { return ((synchsafeInt & 0x0000007fu) ) | ((synchsafeInt & 0x00007f00u) >> 1) @@ -137,6 +161,40 @@ LIB_EXPORT inline uint32 toNormalInt(uint32 synchsafeInt) | ((synchsafeInt & 0x7f000000u) >> 3); } +/*! + * \brief Swaps the byte order of the specified 16-bit unsigned integer. + */ +LIB_EXPORT constexpr uint16 swapOrder(uint16 value) +{ + return (value >> 8) | (value << 8); +} + +/*! + * \brief Swaps the byte order of the specified 32-bit unsigned integer. + */ +LIB_EXPORT constexpr uint32 swapOrder(uint32 value) +{ + return (value >> 24) + | ((value & 0x00FF0000) >> 8) + | ((value & 0x0000FF00) << 8) + | (value << 24); +} + +/*! + * \brief Swaps the byte order of the specified 64-bit unsigned integer. + */ +LIB_EXPORT constexpr uint64 swapOrder(uint64 value) +{ + return(value >> (7 * 8)) + | ((value & 0x00FF000000000000) >> (5 * 8)) + | ((value & 0x0000FF0000000000) >> (3 * 8)) + | ((value & 0x000000FF00000000) >> (1 * 8)) + | ((value & 0x00000000FF000000) << (1 * 8)) + | ((value & 0x0000000000FF0000) << (3 * 8)) + | ((value & 0x000000000000FF00) << (5 * 8)) + | ((value) << (7 * 8)); +} + } #endif // CONVERSION_UTILITIES_CONVERT_H diff --git a/tests/conversiontests.cpp b/tests/conversiontests.cpp index 7e4241d..d4ea0aa 100644 --- a/tests/conversiontests.cpp +++ b/tests/conversiontests.cpp @@ -19,6 +19,7 @@ class ConversionTests : public TestFixture CPPUNIT_TEST_SUITE(ConversionTests); CPPUNIT_TEST(testEndianness); CPPUNIT_TEST(testBinaryConversions); + CPPUNIT_TEST(testSwapOrderFunctions); CPPUNIT_TEST(testStringConversions); CPPUNIT_TEST_SUITE_END(); @@ -30,6 +31,7 @@ public: void testEndianness(); void testBinaryConversions(); + void testSwapOrderFunctions(); void testStringConversions(); private: @@ -58,8 +60,16 @@ void ConversionTests::testEndianness() char characters[4]; } test = {0x01020304}; #if defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN) + // test whether macro definitions are consistent + CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == true); + CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == false); + // test whether byte order assumption is correct CPPUNIT_ASSERT_MESSAGE("Byte order assumption (big-endian) is wrong", test.characters[0] == 0x01); #elif defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN) + // test whether macro definitions are consistent + CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == false); + CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == true); + // test whether byte order assumption is correct CPPUNIT_ASSERT_MESSAGE("Byte order assumption (little-endian) is wrong", test.characters[0] == 0x04); #else CPPUNIT_FAIL("There is not valid byte order assumption"); @@ -133,6 +143,16 @@ void ConversionTests::testBinaryConversions() } } +/*! + * \brief Tests swap order functions. + */ +void ConversionTests::testSwapOrderFunctions() +{ + CPPUNIT_ASSERT(swapOrder(static_cast(0x7825)) == 0x2578); + CPPUNIT_ASSERT(swapOrder(static_cast(0x12345678)) == 0x78563412); + CPPUNIT_ASSERT(swapOrder(static_cast(0x1122334455667788)) == 0x8877665544332211); +} + /*! * \brief Tests most important string conversions. */