#ifndef BOOST_ENDIAN_DETAIL_ENDIAN_LOAD_HPP_INCLUDED #define BOOST_ENDIAN_DETAIL_ENDIAN_LOAD_HPP_INCLUDED // Copyright 2019 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt #include #include #include #include #include #include #include #include #include #include namespace boost { namespace endian { namespace detail { template struct endian_load_impl { }; } // namespace detail // Requires: // // sizeof(T) must be 1, 2, 4, or 8 // 1 <= N <= sizeof(T) // T is TriviallyCopyable // if N < sizeof(T), T is integral or enum template inline T endian_load( unsigned char const * p ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8 ); BOOST_STATIC_ASSERT( N >= 1 && N <= sizeof(T) ); return detail::endian_load_impl()( p ); } namespace detail { // same endianness, same size template struct endian_load_impl { inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( is_trivially_copyable::value ); T t; std::memcpy( &t, p, N ); return t; } }; // same size, reverse endianness template struct endian_load_impl { inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( is_trivially_copyable::value ); typename integral_by_size::type tmp; std::memcpy( &tmp, p, N ); endian_reverse_inplace( tmp ); T t; std::memcpy( &t, &tmp, N ); return t; } }; // expanding load 1 -> 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 { inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( is_integral::value || is_enum::value ); unsigned char tmp[ 4 ]; tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2]; tmp[3] = boost::is_signed::value && ( p[2] & 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[ 4 ]; tmp[0] = boost::is_signed::value && ( p[0] & 0x80 )? 0xFF: 0x00; tmp[1] = p[0]; tmp[2] = p[1]; tmp[3] = p[2]; return boost::endian::endian_load( tmp ); } }; // expanding load 1 -> 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 { 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[4] & 0x80 )? 0xFF: 0x00; tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2]; tmp[3] = p[3]; tmp[4] = p[4]; 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] = p[0]; tmp[4] = p[1]; tmp[5] = p[2]; tmp[6] = p[3]; tmp[7] = p[4]; return boost::endian::endian_load( tmp ); } }; // expanding load 6 -> 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[5] & 0x80 )? 0xFF: 0x00; tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2]; tmp[3] = p[3]; tmp[4] = p[4]; tmp[5] = p[5]; 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] = p[0]; tmp[3] = p[1]; tmp[4] = p[2]; tmp[5] = p[3]; tmp[6] = p[4]; tmp[7] = p[5]; return boost::endian::endian_load( tmp ); } }; // expanding load 7 -> 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[6] & 0x80 )? 0xFF: 0x00; tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2]; tmp[3] = p[3]; tmp[4] = p[4]; tmp[5] = p[5]; tmp[6] = p[6]; 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] = p[0]; tmp[2] = p[1]; tmp[3] = p[2]; tmp[4] = p[3]; tmp[5] = p[4]; tmp[6] = p[5]; tmp[7] = p[6]; return boost::endian::endian_load( tmp ); } }; } // namespace detail } // namespace endian } // namespace boost #endif // BOOST_ENDIAN_DETAIL_ENDIAN_LOAD_HPP_INCLUDED