diff --git a/include/boost/endian/converters.hpp b/include/boost/endian/converters.hpp index 112fd2a..2931d74 100644 --- a/include/boost/endian/converters.hpp +++ b/include/boost/endian/converters.hpp @@ -38,28 +38,28 @@ namespace endian // reverse_bytes overloads for floating point types as requested by Vicente // Botet and others. - // TODO: Track progress of Floating-Point Typedefs Having Specified Widths proposal (N3626) + // TODO: Track progress of Floating-Point Typedefs Having Specified Widths proposal (N3626) inline float reverse_bytes(float x) BOOST_NOEXCEPT; - //inline double reverse_bytes(double x) BOOST_NOEXCEPT; + inline double reverse_bytes(double x) BOOST_NOEXCEPT; // general reverse_bytes function template to meet requests for UDT support by Vicente // Botet and others. template inline T reverse_bytes(T x) BOOST_NOEXCEPT; // convert little to big or visa versa - // reverse bytes if native endian order is not big + // reverse bytes unless native endianness is big template - inline T big(T x) BOOST_NOEXCEPT; + inline T big(T x) BOOST_NOEXCEPT; // alternate names: reverse_bytes_unless_big, reverse_unless_big // Return: x if native endian order is big, otherwise reverse_bytes(x) - // reverse bytes if native endian order is not little + // reverse bytes unless native endianness is little template - inline T little(T x) BOOST_NOEXCEPT; + inline T little(T x) BOOST_NOEXCEPT; // alternate names: reverse_bytes_unless_little, reverse_unless_little // Return: x if native endian order is little, otherwise reverse_bytes(x); // compile-time generic byte order conversion template - /*inline*/ T convert_bytes(T from) BOOST_NOEXCEPT; + T convert_bytes(T from) BOOST_NOEXCEPT; // runtime actual byte-order determination inline BOOST_SCOPED_ENUM(order) actual_order(BOOST_SCOPED_ENUM(order) o) BOOST_NOEXCEPT; @@ -159,22 +159,23 @@ namespace endian return *(const float*)&tmp; } - //inline double reverse_bytes(double x) BOOST_NOEXCEPT - //{ - // BOOST_STATIC_ASSERT_MSG(sizeof(double) == sizeof(uint64_t), - // "boost::endian only supprts sizeof(double) == 8; please report error to boost mailing list"); - //} + inline double reverse_bytes(double x) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(sizeof(double) == sizeof(uint64_t), + "boost::endian only supprts sizeof(double) == 8; please report error to boost mailing list"); + uint64_t tmp = reverse_bytes(*(const uint64_t*)&x); + return *(const double*)&tmp; + } // general reverse_bytes function template implementation approach using std::reverse // suggested by Mathias Gaunard template inline T reverse_bytes(T x) BOOST_NOEXCEPT { - T tmp; + T tmp(x); std::reverse( - reinterpret_cast(&x), - reinterpret_cast(&x) + sizeof(T), - reinterpret_cast(&tmp)); + reinterpret_cast(&tmp), + reinterpret_cast(&tmp) + sizeof(T)); return tmp; } diff --git a/test/converter_test.cpp b/test/converter_test.cpp index b349c65..5e2b559 100644 --- a/test/converter_test.cpp +++ b/test/converter_test.cpp @@ -15,13 +15,15 @@ #include namespace be = boost::endian; +using std::cout; +using std::endl; namespace { void test_reverse_bytes() { - std::cout << "test_reverse_bytes...\n"; + cout << "test_reverse_bytes...\n"; boost::int64_t i64 = 0x0102030405060708LL; BOOST_TEST_EQ(be::reverse_bytes(i64), 0x0807060504030201LL); @@ -58,8 +60,16 @@ namespace boost::uint16_t ui16 = 0x0102; BOOST_TEST_EQ(be::reverse_bytes(ui16), 0x0201); BOOST_TEST_EQ(be::reverse_bytes(be::reverse_bytes(ui16)), ui16); + + BOOST_TEST_NE(be::reverse_bytes(1.0F), 1.0F); + BOOST_TEST_EQ(be::reverse_bytes(be::reverse_bytes(1.0F)), 1.0F); + BOOST_TEST_EQ(be::reverse_bytes(1.0F), be::reverse_bytes(1.0F)); + + BOOST_TEST_NE(be::reverse_bytes(1.0), 1.0); + BOOST_TEST_EQ(be::reverse_bytes(be::reverse_bytes(1.0)), 1.0); + BOOST_TEST_EQ(be::reverse_bytes(1.0), be::reverse_bytes(1.0)); - std::cout << " test_reverse_bytes complete\n"; + cout << " test_reverse_bytes complete\n"; } const boost::int64_t ni64 = 0x0102030405060708LL; @@ -89,6 +99,15 @@ namespace const boost::int16_t li16 = 0x0102; # endif + const boost::int16_t ni16hi = static_cast(0xf1f2U); +# ifdef BOOST_BIG_ENDIAN + const boost::int16_t bi16hi = static_cast(0xf1f2U); + const boost::int16_t li16hi = static_cast(0xf2f1U); +# else + const boost::int16_t bi16hi = static_cast(0xf2f1U); + const boost::int16_t li16hi = static_cast(0xf1f2U); +# endif + const boost::uint64_t nui64 = 0x0102030405060708ULL; # ifdef BOOST_BIG_ENDIAN const boost::uint64_t bui64 = 0x0102030405060708ULL; @@ -116,9 +135,103 @@ namespace const boost::uint16_t lui16 = 0x0102; # endif + // values for tests + + void native_value(int16_t& x) {x = static_cast(0xF102U);} + void native_value(uint16_t& x) {x = static_cast(0xF102U);} +# ifdef BOOST_BIG_ENDIAN + void big_value(int16_t& x) {x = static_cast(0xF102U);} + void big_value(uint16_t& x) {x = static_cast(0xF102U);} + void little_value(int16_t& x) {x = static_cast(0x02F1U);} + void little_value(uint16_t& x) {x = static_cast(0x02F1U);} +# else + void big_value(int16_t& x) {x = static_cast(0x02F1U);} + void big_value(uint16_t& x) {x = static_cast(0x02F1U);} + void little_value(int16_t& x) {x = static_cast(0xF102U);} + void little_value(uint16_t& x) {x = static_cast(0xF102U);} +# endif + + void native_value(int32_t& x) {x = static_cast(0xF1E21304UL);} + void native_value(uint32_t& x) {x = static_cast(0xF1E21304UL);} +# ifdef BOOST_BIG_ENDIAN + void big_value(int32_t& x) {x = static_cast(0xF1E21304UL);} + void big_value(uint32_t& x) {x = static_cast(0xF1E21304UL);} + void little_value(int32_t& x) {x = static_cast(0x0413E2F1UL);} + void little_value(uint32_t& x) {x = static_cast(0x0413E2F1UL);} +# else + void big_value(int32_t& x) {x = static_cast(0x0413E2F1UL);} + void big_value(uint32_t& x) {x = static_cast(0x0413E2F1UL);} + void little_value(int32_t& x) {x = static_cast(0xF1E21304UL);} + void little_value(uint32_t& x) {x = static_cast(0xF1E21304UL);} +# endif + + void native_value(int64_t& x) {x = static_cast(0xF1E2D3C444231201ULL);} + void native_value(uint64_t& x) {x = static_cast(0xF1E2D3C444231201ULL);} +# ifdef BOOST_BIG_ENDIAN + void big_value(int64_t& x) {x = static_cast(0xF1E2D3C444231201ULL);} + void big_value(uint64_t& x) {x = static_cast(0xF1E2D3C444231201ULL);} + void little_value(int64_t& x) {x = static_cast(0x01122344C4D3E2F1ULL);} + void little_value(uint64_t& x) {x = static_cast(0x01122344C4D3E2F1ULL);} +# else + void big_value(int64_t& x) {x = static_cast(0x01122344C4D3E2F1ULL);} + void big_value(uint64_t& x) {x = static_cast(0x01122344C4D3E2F1ULL);} + void little_value(int64_t& x) {x = static_cast(0xF1E2D3C444231201ULL);} + void little_value(uint64_t& x) {x = static_cast(0xF1E2D3C444231201ULL);} +# endif + + void native_value(float& x) {x = static_cast(0xF1E21304UL);} + void native_value(double& x) {x = static_cast(0xF1E21304UL);} +# ifdef BOOST_BIG_ENDIAN + void big_value(float& x) {x = static_cast(0xF1E21304UL);} + void big_value(double& x) {x = static_cast(0xF1E21304UL);} + void little_value(float& x) {x = static_cast(0x0413E2F1UL);} + void little_value(double& x) {x = static_cast(0x0413E2F1UL);} +# else + void big_value(float& x) {x = static_cast(0x0413E2F1UL);} + void big_value(double& x) {x = static_cast(0x0413E2F1UL);} + void little_value(float& x) {x = static_cast(0xF1E21304UL);} + void little_value(double& x) {x = static_cast(0xF1E21304UL);} +# endif + + + template + void test() + { + T native; + T big; + T little; + native_value(native); + big_value(big); + little_value(little); + + BOOST_TEST_EQ(be::reverse_bytes(big), little); + BOOST_TEST_EQ(be::reverse_bytes(little), big); + BOOST_TEST_EQ(be::reverse_bytes(big), little); + BOOST_TEST_EQ(be::reverse_bytes(little), big); +# ifdef BOOST_BIG_ENDIAN + BOOST_TEST_EQ(be::reverse_bytes(native), little); + BOOST_TEST_EQ(be::reverse_bytes(native), little); + BOOST_TEST_EQ(be::big(big), big); + BOOST_TEST_EQ(be::big(big), big); + BOOST_TEST_EQ(be::big(little), little); + BOOST_TEST_EQ(be::big(little), little); + BOOST_TEST_EQ(be::big(native), little); + BOOST_TEST_EQ(be::big(native), little); +# else + BOOST_TEST_EQ(be::reverse_bytes(native), big); + BOOST_TEST_EQ(be::reverse_bytes(native), big); + BOOST_TEST_EQ(be::big(big), little); + BOOST_TEST_EQ(be::big(big), little); + BOOST_TEST_EQ(be::big(little), big); + BOOST_TEST_EQ(be::big(little), big); + BOOST_TEST_EQ(be::big(native), big); + BOOST_TEST_EQ(be::big(native), big); +# endif + } + void test_conditional_reverse_bytes() { - std::cout << "test_conditional_reverse_bytes...\n"; + cout << "test_conditional_reverse_bytes...\n"; BOOST_TEST_EQ(be::big(ni64), bi64); BOOST_TEST_EQ(be::big(ni32), bi32); @@ -147,13 +260,12 @@ namespace BOOST_TEST_EQ(be::little(be::little(nui64)), nui64); BOOST_TEST_EQ(be::little(be::little(nui32)), nui32); BOOST_TEST_EQ(be::little(be::little(nui16)), nui16); - std::cout << " test_conditional_reverse_bytes complete\n"; - + cout << " test_conditional_reverse_bytes complete\n"; } void test_compile_time_convert_bytes() { - std::cout << "test_compile_time_convert_bytes...\n"; + cout << "test_compile_time_convert_bytes...\n"; BOOST_TEST_EQ((be::convert_bytes(bi16)), bi16); BOOST_TEST_EQ((be::convert_bytes(li16)), li16); @@ -221,12 +333,12 @@ namespace BOOST_TEST_EQ((be::convert_bytes(nui64)), bui64); BOOST_TEST_EQ((be::convert_bytes(nui64)), nui64); - std::cout << " test_compile_time_convert_bytes complete\n"; + cout << " test_compile_time_convert_bytes complete\n"; } void test_runtime_convert_bytes() { - std::cout << "test_runtime_convert_bytes...\n"; + cout << "test_runtime_convert_bytes...\n"; BOOST_TEST_EQ((be::convert_bytes(bi16, be::order::big, be::order::big)), bi16); BOOST_TEST_EQ((be::convert_bytes(li16, be::order::little, be::order::little)), li16); @@ -294,7 +406,7 @@ namespace BOOST_TEST_EQ((be::convert_bytes(nui64, be::order::native, be::order::big)), bui64); BOOST_TEST_EQ((be::convert_bytes(nui64, be::order::native, be::order::little)), nui64); - std::cout << " test_runtime_convert_bytes complete\n"; + cout << " test_runtime_convert_bytes complete\n"; } } // unnamed namespace @@ -307,8 +419,22 @@ int cpp_main(int, char * []) test_compile_time_convert_bytes(); test_runtime_convert_bytes(); - BOOST_TEST(be::reverse_bytes(1.0F) != 1.0F); - BOOST_TEST(be::reverse_bytes(be::reverse_bytes(1.0F)) == 1.0F); + cout << "int16_t" << endl; + test(); + cout << "uint16_t" << endl; + test(); + cout << "int32_t" << endl; + test(); + cout << "uint32_t" << endl; + test(); + cout << "int64_t" << endl; + test(); + cout << "uint64_t" << endl; + test(); + cout << "float" << endl; + test(); + cout << "double" << endl; + test(); return ::boost::report_errors(); }