// conversion_test.cpp ---------------------------------------------------------------// // Copyright Beman Dawes 2010 // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt //--------------------------------------------------------------------------------------// #if defined(_MSC_VER) # pragma warning( disable: 4127 ) // conditional expression is constant # if _MSC_VER < 1500 # pragma warning( disable: 4267 ) // '+=': possible loss of data # endif #endif #include #include #include #include #include #include #include #include #include #include namespace be = boost::endian; using std::cout; using std::endl; using boost::int8_t; using boost::uint8_t; using boost::int16_t; using boost::uint16_t; using boost::int32_t; using boost::uint32_t; using boost::int64_t; using boost::uint64_t; template inline T std_endian_reverse(T x) BOOST_NOEXCEPT { T tmp(x); std::reverse( reinterpret_cast(&tmp), reinterpret_cast(&tmp) + sizeof(T) ); return tmp; } namespace { // values for tests static unsigned char const test_value_bytes[] = { 0xF1, 0x02, 0xE3, 0x04, 0xD5, 0x06, 0xC7, 0x08 }; template void native_value( T& x ) { BOOST_STATIC_ASSERT( boost::is_integral::value && sizeof( T ) <= 8 ); std::memcpy( &x, test_value_bytes, sizeof( x ) ); } template void little_value( T& x ) { BOOST_STATIC_ASSERT( boost::is_integral::value && sizeof( T ) <= 8 ); typedef typename boost::make_unsigned::type U; x = 0; for( std::size_t i = 0; i < sizeof( x ); ++i ) { x += static_cast( test_value_bytes[ i ] ) << ( 8 * i ); } } template void big_value( T& x ) { BOOST_STATIC_ASSERT( boost::is_integral::value && sizeof( T ) <= 8 ); typedef typename boost::make_unsigned::type U; x = 0; for( std::size_t i = 0; i < sizeof( x ); ++i ) { x += static_cast( test_value_bytes[ i ] ) << ( 8 * ( sizeof( x ) - i - 1 ) ); } } template void test() { T native; T big; T little; native_value(native); big_value(big); little_value(little); // validate the values used by the tests below if( be::order::native == be::order::big ) { BOOST_TEST_EQ(native, big); BOOST_TEST_EQ(::std_endian_reverse(native), little); } else { BOOST_TEST_EQ(::std_endian_reverse(native), big); BOOST_TEST_EQ(native, little); } // value-by-value tests // unconditional reverse BOOST_TEST_EQ(be::endian_reverse(big), little); BOOST_TEST_EQ(be::endian_reverse(little), big); // conditional reverse BOOST_TEST_EQ(be::native_to_big(native), big); BOOST_TEST_EQ(be::native_to_little(native), little); BOOST_TEST_EQ(be::big_to_native(big), native); BOOST_TEST_EQ(be::little_to_native(little), native); // generic conditional reverse BOOST_TEST_EQ((be::conditional_reverse(big)), big); BOOST_TEST_EQ((be::conditional_reverse(little)), little); BOOST_TEST_EQ((be::conditional_reverse(native)), native); BOOST_TEST_EQ((be::conditional_reverse(big)), little); BOOST_TEST_EQ((be::conditional_reverse(big)), native); BOOST_TEST_EQ((be::conditional_reverse(little)), big); BOOST_TEST_EQ((be::conditional_reverse(little)), native); BOOST_TEST_EQ((be::conditional_reverse(native)), big); BOOST_TEST_EQ((be::conditional_reverse(native)), little); // runtime conditional reverse BOOST_TEST_EQ((be::conditional_reverse(big, be::order::big, be::order::big)), big); BOOST_TEST_EQ((be::conditional_reverse(little, be::order::little, be::order::little)), little); BOOST_TEST_EQ((be::conditional_reverse(native, be::order::native, be::order::native)), native); BOOST_TEST_EQ((be::conditional_reverse(big, be::order::big, be::order::little)), little); BOOST_TEST_EQ((be::conditional_reverse(big, be::order::big, be::order::native)), native); BOOST_TEST_EQ((be::conditional_reverse(little, be::order::little, be::order::big)), big); BOOST_TEST_EQ((be::conditional_reverse(little, be::order::little, be::order::native)), native); BOOST_TEST_EQ((be::conditional_reverse(native, be::order::native, be::order::big)), big); BOOST_TEST_EQ((be::conditional_reverse(native, be::order::native, be::order::little)), little); // modify-in-place tests T x; // unconditional reverse x = big; be::endian_reverse_inplace(x); BOOST_TEST_EQ(x, little); x = little; be::endian_reverse_inplace(x); BOOST_TEST_EQ(x, big); // conditional reverse x = native; be::native_to_big_inplace(x); BOOST_TEST_EQ(x, big); x = native; be::native_to_little_inplace(x); BOOST_TEST_EQ(x, little); x = big; be::big_to_native_inplace(x); BOOST_TEST_EQ(x, native); x = little; be::little_to_native_inplace(x); BOOST_TEST_EQ(x, native); // generic conditional reverse x = big; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, big); x = little; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, little); x = native; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, native); x = big; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, little); x = big; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, native); x = little; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, big); x = little; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, native); x = native; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, big); x = native; be::conditional_reverse_inplace(x); BOOST_TEST_EQ(x, little); // runtime conditional reverse x = big; be::conditional_reverse_inplace(x, be::order::big, be::order::big); BOOST_TEST_EQ(x, big); x = little; be::conditional_reverse_inplace(x, be::order::little, be::order::little); BOOST_TEST_EQ(x, little); x = native; be::conditional_reverse_inplace(x, be::order::native, be::order::native); BOOST_TEST_EQ(x, native); x = big; be::conditional_reverse_inplace(x, be::order::big, be::order::little); BOOST_TEST_EQ(x, little); x = big; be::conditional_reverse_inplace(x, be::order::big, be::order::native); BOOST_TEST_EQ(x, native); x = little; be::conditional_reverse_inplace(x, be::order::little, be::order::big); BOOST_TEST_EQ(x, big); x = little; be::conditional_reverse_inplace(x, be::order::little, be::order::native); BOOST_TEST_EQ(x, native); x = native; be::conditional_reverse_inplace(x, be::order::native, be::order::big); BOOST_TEST_EQ(x, big); x = native; be::conditional_reverse_inplace(x, be::order::native, be::order::little); BOOST_TEST_EQ(x, little); } //--------------------------------------------------------------------------------------// template void udt_test() { UDT udt, tmp; int64_t big; int64_t little; int64_t native; big_value(big); little_value(little); native_value(native); udt.member1 = big; udt.member2 = little; udt.member3 = native; tmp = be::conditional_reverse(udt); BOOST_TEST_EQ(tmp.member1, be::endian_reverse(big)); BOOST_TEST_EQ(tmp.member2, be::endian_reverse(little)); BOOST_TEST_EQ(tmp.member3, be::endian_reverse(native)); be::conditional_reverse_inplace(udt); BOOST_TEST_EQ(udt.member1, be::endian_reverse(big)); BOOST_TEST_EQ(udt.member2, be::endian_reverse(little)); BOOST_TEST_EQ(udt.member3, be::endian_reverse(native)); udt.member1 = big; udt.member2 = little; udt.member3 = native; tmp.member1 = tmp.member2 = tmp.member3 = 0; tmp = be::conditional_reverse(udt); BOOST_TEST_EQ(tmp.member1, big); BOOST_TEST_EQ(tmp.member2, little); BOOST_TEST_EQ(tmp.member3, native); be::conditional_reverse_inplace(udt); BOOST_TEST_EQ(udt.member1, big); BOOST_TEST_EQ(udt.member2, little); BOOST_TEST_EQ(udt.member3, native); } } // unnamed namespace //--------------------------------------------------------------------------------------// // User-defined types namespace user { // UDT1 supplies both endian_reverse and endian_reverse_inplace struct UDT1 { int64_t member1; int64_t member2; int64_t member3; }; UDT1 endian_reverse(const UDT1& udt) BOOST_NOEXCEPT { UDT1 tmp; tmp.member1 = boost::endian::endian_reverse(udt.member1); tmp.member2 = boost::endian::endian_reverse(udt.member2); tmp.member3 = boost::endian::endian_reverse(udt.member3); return tmp; } void endian_reverse_inplace(UDT1& udt) BOOST_NOEXCEPT { boost::endian::endian_reverse_inplace(udt.member1); boost::endian::endian_reverse_inplace(udt.member2); boost::endian::endian_reverse_inplace(udt.member3); } // UDT2 supplies only endian_reverse struct UDT2 { int64_t member1; int64_t member2; int64_t member3; }; UDT2 endian_reverse(const UDT2& udt) BOOST_NOEXCEPT { UDT2 tmp; tmp.member1 = boost::endian::endian_reverse(udt.member1); tmp.member2 = boost::endian::endian_reverse(udt.member2); tmp.member3 = boost::endian::endian_reverse(udt.member3); return tmp; } // UDT3 supplies neither endian_reverse nor endian_reverse_inplace, // so udt_test() should fail to compile struct UDT3 { int64_t member1; int64_t member2; int64_t member3; }; } // namespace user //--------------------------------------------------------------------------------------// int cpp_main(int, char * []) { if( be::order::native == be::order::little ) { cout << "Little endian" << endl; } else if( be::order::native == be::order::big ) { cout << "Big endian" << endl; } else { cout << "Unknown endian" << endl; } cout << "byte swap intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG << endl; //std::cerr << std::hex; cout << "int8_t" << endl; test(); cout << "uint8_t" << endl; test(); 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 << "UDT 1" << endl; udt_test(); cout << "UDT 2" << endl; udt_test(); #ifdef BOOST_ENDIAN_COMPILE_FAIL cout << "UDT 3" << endl; udt_test(); // should fail to compile since has not endian_reverse() #endif return ::boost::report_errors(); } int main( int argc, char* argv[] ) { try { return cpp_main( argc, argv ); } catch( std::exception const & x ) { BOOST_ERROR( x.what() ); return boost::report_errors(); } } #include