Simplify endian_buffer specializations

This commit is contained in:
Peter Dimov
2019-04-27 20:11:41 +03:00
parent f77a318c37
commit 6b5792647c
2 changed files with 150 additions and 169 deletions

View File

@ -293,17 +293,17 @@ namespace endian
cover_operators<endian_arithmetic<order::big, T, n_bits>, T> cover_operators<endian_arithmetic<order::big, T, n_bits>, T>
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
typedef endian_buffer< order::big, T, n_bits, align::no > inherited;
public: public:
typedef T value_type; typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS # ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT: inherited( val )
{ {
detail::store_big_endian<T, n_bits/8>(this->m_value, val);
} }
# endif # endif
endian_arithmetic& operator=(T val) BOOST_NOEXCEPT endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
{ detail::store_big_endian<T, n_bits/8>(this->m_value, val); return *this; } { inherited::operator=( val ); return *this; }
operator value_type() const BOOST_NOEXCEPT { return this->value(); } operator value_type() const BOOST_NOEXCEPT { return this->value(); }
}; };
@ -314,17 +314,17 @@ namespace endian
cover_operators< endian_arithmetic< order::little, T, n_bits >, T > cover_operators< endian_arithmetic< order::little, T, n_bits >, T >
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
typedef endian_buffer< order::little, T, n_bits, align::no > inherited;
public: public:
typedef T value_type; typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS # ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT: inherited( val )
{ {
detail::store_little_endian<T, n_bits/8>(this->m_value, val);
} }
# endif # endif
endian_arithmetic& operator=(T val) BOOST_NOEXCEPT endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
{ detail::store_little_endian<T, n_bits/8>(this->m_value, val); return *this; } { inherited::operator=( val ); return *this; }
operator value_type() const BOOST_NOEXCEPT { return this->value(); } operator value_type() const BOOST_NOEXCEPT { return this->value(); }
}; };
@ -338,19 +338,19 @@ namespace endian
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
typedef endian_buffer< order::big, T, n_bits, align::yes > inherited;
public: public:
typedef T value_type; typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS # ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT: inherited( val )
{ {
this->m_value = ::boost::endian::native_to_big(val);
} }
# endif # endif
endian_arithmetic& operator=(T val) BOOST_NOEXCEPT endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
{ {
this->m_value = ::boost::endian::native_to_big(val); inherited::operator=( val );
return *this; return *this;
} }
operator value_type() const BOOST_NOEXCEPT { return this->value(); } operator value_type() const BOOST_NOEXCEPT { return this->value(); }
@ -364,18 +364,18 @@ namespace endian
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
typedef endian_buffer< order::little, T, n_bits, align::yes > inherited;
public: public:
typedef T value_type; typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS # ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT: inherited( val )
{ {
this->m_value = ::boost::endian::native_to_little(val);
} }
# endif # endif
endian_arithmetic& operator=(T val) BOOST_NOEXCEPT endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
{ {
this->m_value = ::boost::endian::native_to_little(val); inherited::operator=( val );
return *this; return *this;
} }
operator value_type() const BOOST_NOEXCEPT { return this->value(); } operator value_type() const BOOST_NOEXCEPT { return this->value(); }

View File

@ -31,15 +31,14 @@
# pragma pack(push, 1) # pragma pack(push, 1)
#endif #endif
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <boost/predef/other/endian.h>
#include <boost/endian/detail/endian_store.hpp> #include <boost/endian/detail/endian_store.hpp>
#include <boost/endian/detail/endian_load.hpp> #include <boost/endian/detail/endian_load.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/scoped_enum.hpp> #include <boost/core/scoped_enum.hpp>
#include <boost/predef/other/endian.h>
#include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <iosfwd> #include <iosfwd>
#include <climits> #include <climits>
#include <cstring> #include <cstring>
@ -211,171 +210,153 @@ namespace endian
//---------------------------------- end synopsis ------------------------------------// //---------------------------------- end synopsis ------------------------------------//
namespace detail
{
template <typename T, std::size_t n_bytes>
inline
T load_big_endian(const void* bytes) BOOST_NOEXCEPT
{
return endian::endian_load<T, n_bytes, order::big>( static_cast<unsigned char const*>( bytes ) );
}
template <typename T, std::size_t n_bytes>
inline
T load_little_endian(const void* bytes) BOOST_NOEXCEPT
{
return endian::endian_load<T, n_bytes, order::little>( static_cast<unsigned char const*>( bytes ) );
}
template <typename T, std::size_t n_bytes>
inline
void store_big_endian(void* bytes, T value) BOOST_NOEXCEPT
{
endian::endian_store<T, n_bytes, order::big>( value, static_cast<unsigned char*>( bytes ) );
}
template <typename T, std::size_t n_bytes>
inline
void store_little_endian(void* bytes, T value) BOOST_NOEXCEPT
{
endian::endian_store<T, n_bytes, order::little>( value, static_cast<unsigned char*>( bytes ) );
}
} // namespace detail
// endian_buffer class template specializations --------------------------------------// // endian_buffer class template specializations --------------------------------------//
// Specializations that represent unaligned bytes. // Specializations that represent unaligned bytes.
// Taking an integer type as a parameter provides a nice way to pass both // Taking an integer type as a parameter provides a nice way to pass both
// the size and signedness of the desired integer and get the appropriate // the size and signedness of the desired integer and get the appropriate
// corresponding integer type for the interface. // corresponding integer type for the interface.
// Q: Should endian_buffer supply "value_type operator value_type() const noexcept"? // Q: Should endian_buffer supply "value_type operator value_type() const noexcept"?
// A: No. The rationale for endian_buffers is to prevent high-cost hidden // A: No. The rationale for endian_buffers is to prevent high-cost hidden
// conversions. If an implicit conversion operator is supplied, hidden conversions // conversions. If an implicit conversion operator is supplied, hidden conversions
// can occur. // can occur.
// unaligned big endian_buffer specialization // unaligned endian_buffer specialization
template <typename T, std::size_t n_bits>
class endian_buffer< order::big, T, n_bits, align::no > template< BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits >
class endian_buffer<Order, T, n_bits, align::no>
{
private:
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
unsigned char value_[ n_bits / 8 ];
public:
typedef T value_type;
#ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer( T val ) BOOST_NOEXCEPT
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); endian::endian_store<T, n_bits / 8, Order>( val, value_ );
public: }
typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS #endif
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT endian_buffer& operator=( T val ) BOOST_NOEXCEPT
{ {
detail::store_big_endian<T, n_bits/8>(m_value, val); endian::endian_store<T, n_bits / 8, Order>( val, value_ );
} return *this;
# endif }
endian_buffer & operator=(T val) BOOST_NOEXCEPT
{ value_type value() const BOOST_NOEXCEPT
detail::store_big_endian<T, n_bits/8>(m_value, val); {
return *this; return endian::endian_load<T, n_bits / 8, Order>( value_ );
} }
value_type value() const BOOST_NOEXCEPT
{ char const * data() const BOOST_NOEXCEPT
return detail::load_big_endian<T, n_bits/8>(m_value); {
} return reinterpret_cast< char const* >( value_ );
const char* data() const BOOST_NOEXCEPT { return m_value; } }
protected: };
char m_value[n_bits/8];
// aligned specializations; only n_bits == 16/32/64 supported
// aligned endian_buffer specialization
template< BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits >
class endian_buffer<Order, T, n_bits, align::yes>
{
private:
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
union
{
unsigned char value_[ n_bits / 8 ];
T align_;
}; };
// unaligned little endian_buffer specialization public:
template <typename T, std::size_t n_bits>
class endian_buffer< order::little, T, n_bits, align::no > typedef T value_type;
#ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer( T val ) BOOST_NOEXCEPT
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); endian::endian_store<T, n_bits / 8, Order>( val, value_ );
public: }
typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
{
detail::store_little_endian<T, n_bits/8>(m_value, val);
}
# endif
endian_buffer & operator=(T val) BOOST_NOEXCEPT
{ detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
value_type value() const BOOST_NOEXCEPT
{
return detail::load_little_endian<T, n_bits/8>(m_value);
}
const char* data() const BOOST_NOEXCEPT { return m_value; }
protected:
char m_value[n_bits/8];
};
// align::yes specializations; only n_bits == 16/32/64 supported #endif
// aligned big endian_buffer specialization endian_buffer& operator=( T val ) BOOST_NOEXCEPT
template <typename T, std::size_t n_bits>
class endian_buffer<order::big, T, n_bits, align::yes>
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); endian::endian_store<T, n_bits / 8, Order>( val, value_ );
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); return *this;
public: }
typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_big(val);
}
# endif value_type value() const BOOST_NOEXCEPT
endian_buffer& operator=(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_big(val);
return *this;
}
//operator value_type() const BOOST_NOEXCEPT
//{
// return ::boost::endian::big_to_native(m_value);
//}
value_type value() const BOOST_NOEXCEPT
{
return ::boost::endian::big_to_native(m_value);
}
const char* data() const BOOST_NOEXCEPT
{return reinterpret_cast<const char*>(&m_value);}
protected:
T m_value;
};
// aligned little endian_buffer specialization
template <typename T, std::size_t n_bits>
class endian_buffer<order::little, T, n_bits, align::yes>
{ {
BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); return endian::endian_load<T, n_bits / 8, Order>( value_ );
BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); }
public:
typedef T value_type;
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_little(val);
}
# endif char const * data() const BOOST_NOEXCEPT
endian_buffer& operator=(T val) BOOST_NOEXCEPT {
{ return reinterpret_cast< char const* >( value_ );
m_value = ::boost::endian::native_to_little(val); }
return *this; };
}
value_type value() const BOOST_NOEXCEPT // aligned native endian_buffer specialization
{
return ::boost::endian::little_to_native(m_value); template< class T, std::size_t n_bits >
} class endian_buffer<order::native, T, n_bits, align::yes>
const char* data() const BOOST_NOEXCEPT {
{return reinterpret_cast<const char*>(&m_value);} private:
protected:
T m_value; BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
}; BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
T value_;
public:
typedef T value_type;
#ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer( T val ) BOOST_NOEXCEPT: value_( val )
{
}
#endif
endian_buffer& operator=( T val ) BOOST_NOEXCEPT
{
value_ = val;
return *this;
}
value_type value() const BOOST_NOEXCEPT
{
return value_;
}
char const * data() const BOOST_NOEXCEPT
{
return reinterpret_cast< char const* >( &value_ );
}
};
} // namespace endian } // namespace endian
} // namespace boost } // namespace boost