Identify and static-assert the requirements of endian_load/endian_store

This commit is contained in:
Peter Dimov
2019-03-13 01:44:29 +02:00
parent 95178e3cfb
commit de33887009
3 changed files with 97 additions and 0 deletions

View File

@ -7,8 +7,12 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/endian/detail/integral_by_size.hpp>
#include <boost/endian/detail/is_trivially_copyable.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
#include <cstring>
@ -26,6 +30,12 @@ template<class T, std::size_t N1, BOOST_SCOPED_ENUM(order) O1, std::size_t N2, B
} // namespace detail
// Requires:
//
// 1 <= N <= sizeof(T) <= 8
// T is TriviallyCopyable
// if N < sizeof(T), T is integral or enum
template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) Order>
inline T endian_load( unsigned char const * p ) BOOST_NOEXCEPT
{
@ -41,6 +51,8 @@ template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O> struct endian_load_
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
T t;
std::memcpy( &t, p, N );
return t;
@ -53,6 +65,8 @@ template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O1, BOOST_SCOPED_ENUM(
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
typename integral_by_size<N>::type tmp;
std::memcpy( &tmp, p, N );
@ -70,6 +84,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 4 ];
tmp[0] = p[0];
@ -85,6 +101,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 4 ];
tmp[0] = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
@ -102,6 +120,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
unsigned char fill = boost::is_signed<T>::value && ( p[4] & 0x80 )? 0xFF: 0x00;
@ -124,6 +144,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
@ -148,6 +170,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
unsigned char fill = boost::is_signed<T>::value && ( p[5] & 0x80 )? 0xFF: 0x00;
@ -170,6 +194,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
@ -194,6 +220,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
unsigned char fill = boost::is_signed<T>::value && ( p[6] & 0x80 )? 0xFF: 0x00;
@ -216,6 +244,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8,
{
inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;

View File

@ -7,7 +7,9 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/endian/detail/integral_by_size.hpp>
#include <boost/endian/detail/is_trivially_copyable.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
#include <cstring>
@ -25,6 +27,12 @@ template<class T, std::size_t N1, BOOST_SCOPED_ENUM(order) O1, std::size_t N2, B
} // namespace detail
// Requires:
//
// 1 <= N <= sizeof(T) <= 8
// T is TriviallyCopyable
// if N < sizeof(T), T is integral or enum
template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) Order>
inline void endian_store( T const & v, unsigned char * p ) BOOST_NOEXCEPT
{
@ -40,6 +48,8 @@ template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O> struct endian_store
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
std::memcpy( p, &v, N );
}
};
@ -50,6 +60,8 @@ template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O1, BOOST_SCOPED_ENUM(
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
typename integral_by_size<N>::type tmp;
std::memcpy( &tmp, &v, N );
@ -65,6 +77,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 4 ];
endian::endian_store<T, 4, order::little>( v, tmp );
@ -78,6 +92,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 4 ];
endian::endian_store<T, 4, order::big>( v, tmp );
@ -93,6 +109,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
endian::endian_store<T, 8, order::little>( v, tmp );
@ -108,6 +126,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
endian::endian_store<T, 8, order::big>( v, tmp );
@ -125,6 +145,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
endian::endian_store<T, 8, order::little>( v, tmp );
@ -141,6 +163,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
endian::endian_store<T, 8, order::big>( v, tmp );
@ -159,6 +183,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
endian::endian_store<T, 8, order::little>( v, tmp );
@ -176,6 +202,8 @@ template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8,
{
inline void operator()( T const & v, unsigned char * p ) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
unsigned char tmp[ 8 ];
endian::endian_store<T, 8, order::big>( v, tmp );

View File

@ -0,0 +1,39 @@
#ifndef BOOST_ENDIAN_DETAIL_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED
#define BOOST_ENDIAN_DETAIL_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED
// Copyright 2019 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
# include <type_traits>
#endif
namespace boost
{
namespace endian
{
namespace detail
{
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
using std::is_trivially_copyable;
#else
template<class T> struct is_trivially_copyable: boost::integral_constant<bool,
boost::has_trivial_copy<T>::value && boost::has_trivial_assign<T>::value> {};
#endif
} // namespace detail
} // namespace endian
} // namespace boost
#endif // BOOST_ENDIAN_DETAIL_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED