From 79c3add90707b9975dbadb64d58ca270f42a307b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 30 Apr 2019 23:53:39 +0300 Subject: [PATCH] Support any expanding loads in endian_load --- include/boost/endian/detail/endian_load.hpp | 312 ++++++++++++++++++++ test/endian_load_test.cpp | 146 ++++++++- 2 files changed, 457 insertions(+), 1 deletion(-) diff --git a/include/boost/endian/detail/endian_load.hpp b/include/boost/endian/detail/endian_load.hpp index 069e0ef..8e8a3f7 100644 --- a/include/boost/endian/detail/endian_load.hpp +++ b/include/boost/endian/detail/endian_load.hpp @@ -79,6 +79,118 @@ template 2 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 2 ]; + + tmp[0] = p[0]; + tmp[1] = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 2 ]; + + tmp[0] = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + tmp[1] = p[0]; + + return boost::endian::endian_load( tmp ); + } +}; + +// expanding load 1 -> 4 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 4 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = p[0]; + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = fill; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 4 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = fill; + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = p[0]; + + return boost::endian::endian_load( tmp ); + } +}; + +// expanding load 2 -> 4 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 4 ]; + + unsigned char fill = boost::is_signed::value && ( p[1] & 0x80 )? 0xFF: 0x00; + + tmp[0] = p[0]; + tmp[1] = p[1]; + tmp[2] = fill; + tmp[3] = fill; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 4 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = fill; + tmp[1] = fill; + tmp[2] = p[0]; + tmp[3] = p[1]; + + return boost::endian::endian_load( tmp ); + } +}; + // expanding load 3 -> 4 template struct endian_load_impl @@ -115,6 +227,206 @@ template struct endian_load_impl 8 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = p[0]; + + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = fill; + tmp[4] = fill; + tmp[5] = fill; + tmp[6] = fill; + tmp[7] = fill; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = fill; + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = fill; + tmp[4] = fill; + tmp[5] = fill; + tmp[6] = fill; + + tmp[7] = p[0]; + + return boost::endian::endian_load( tmp ); + } +}; + +// expanding load 2 -> 8 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[1] & 0x80 )? 0xFF: 0x00; + + tmp[0] = p[0]; + tmp[1] = p[1]; + + tmp[2] = fill; + tmp[3] = fill; + tmp[4] = fill; + tmp[5] = fill; + tmp[6] = fill; + tmp[7] = fill; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = fill; + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = fill; + tmp[4] = fill; + tmp[5] = fill; + + tmp[6] = p[0]; + tmp[7] = p[1]; + + return boost::endian::endian_load( tmp ); + } +}; + +// expanding load 3 -> 8 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[2] & 0x80 )? 0xFF: 0x00; + + tmp[0] = p[0]; + tmp[1] = p[1]; + tmp[2] = p[2]; + + tmp[3] = fill; + tmp[4] = fill; + tmp[5] = fill; + tmp[6] = fill; + tmp[7] = fill; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = fill; + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = fill; + tmp[4] = fill; + + tmp[5] = p[0]; + tmp[6] = p[1]; + tmp[7] = p[2]; + + return boost::endian::endian_load( tmp ); + } +}; + +// expanding load 4 -> 8 + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[3] & 0x80 )? 0xFF: 0x00; + + tmp[0] = p[0]; + tmp[1] = p[1]; + tmp[2] = p[2]; + tmp[3] = p[3]; + + tmp[4] = fill; + tmp[5] = fill; + tmp[6] = fill; + tmp[7] = fill; + + return boost::endian::endian_load( tmp ); + } +}; + +template struct endian_load_impl +{ + inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); + + unsigned char tmp[ 8 ]; + + unsigned char fill = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; + + tmp[0] = fill; + tmp[1] = fill; + tmp[2] = fill; + tmp[3] = fill; + + tmp[4] = p[0]; + tmp[5] = p[1]; + tmp[6] = p[2]; + tmp[7] = p[3]; + + return boost::endian::endian_load( tmp ); + } +}; + // expanding load 5 -> 8 template struct endian_load_impl diff --git a/test/endian_load_test.cpp b/test/endian_load_test.cpp index aebff9f..6593824 100644 --- a/test/endian_load_test.cpp +++ b/test/endian_load_test.cpp @@ -3,7 +3,7 @@ // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include @@ -14,48 +14,120 @@ int main() { unsigned char v[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + // 1 -> 1 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + // 1 -> 2 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + + // 2 -> 2 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102 ); + // 1 -> 4 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + + // 2 -> 4 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0201 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0201 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102 ); + + // 3 -> 4 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x010203 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x010203 ); + // 4 -> 4 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x04030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x04030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01020304 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01020304 ); + // 1 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01 ); + + // 2 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0201 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0201 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102 ); + + // 3 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x030201 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x030201 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x010203 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x010203 ); + + // 4 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x04030201 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x04030201 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01020304 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01020304 ); + + // 5 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102030405 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0102030405 ); + // 6 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x060504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x060504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x010203040506 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x010203040506 ); + // 7 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x07060504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x07060504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01020304050607 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x01020304050607 ); + // 8 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0807060504030201 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0x0807060504030201 ); @@ -66,48 +138,120 @@ int main() { unsigned char v[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8 }; + // 1 -> 1 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + // 1 -> 2 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + + // 2 -> 2 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3343 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3598 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2 ); + // 1 -> 4 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + + // 2 -> 4 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3343 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF2F1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3598 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2 ); + + // 3 -> 4 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -789775 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), -920845 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3 ); + // 4 -> 4 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF4F3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF4F3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3F4 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3F4 ); + // 1 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1 ); + + // 2 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3343 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF2F1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3598 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2 ); + + // 3 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -789775 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF3F2F1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -920845 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3 ); + + // 4 -> 8 + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -185339151 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF4F3F2F1 ); + + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -235736076 ); + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3F4 ); + + // 5 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -43135012111 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF5F4F3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), -60348435211 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3F4F5 ); + // 6 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -9938739662095 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF6F5F4F3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), -15449199413770 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3F4F5F6 ); + // 7 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), -2261738553347343 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF7F6F5F4F3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), -3954995049924873 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF1F2F3F4F5F6F7 ); + // 8 -> 8 + BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF8F7F6F5F4F3F2F1 ); BOOST_TEST_EQ( (boost::endian::endian_load( v )), 0xF8F7F6F5F4F3F2F1 );