endian_types использует span

This commit is contained in:
Andrei Astafev 2020-05-15 19:03:14 +03:00
parent dfaa03647f
commit 24cb2afb8e
3 changed files with 195 additions and 191 deletions

View File

@ -10,6 +10,7 @@ set(TRGT_cpp
set(TRGT_hpp set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/config.hpp ${CMAKE_CURRENT_SOURCE_DIR}/config.hpp
${CMAKE_CURRENT_SOURCE_DIR}/limits.hpp ${CMAKE_CURRENT_SOURCE_DIR}/limits.hpp
${CMAKE_CURRENT_SOURCE_DIR}/span.hpp
${CMAKE_CURRENT_SOURCE_DIR}/endian_types.hpp ${CMAKE_CURRENT_SOURCE_DIR}/endian_types.hpp
${CMAKE_CURRENT_SOURCE_DIR}/enum_bitmask_operations.hpp) ${CMAKE_CURRENT_SOURCE_DIR}/enum_bitmask_operations.hpp)

View File

@ -3,6 +3,8 @@
#pragma once #pragma once
#include "span.hpp"
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
@ -11,10 +13,7 @@
#include <QDebug> #include <QDebug>
#endif #endif
// Both LittleEndianType and BigEndianType are manufactured primitives // Основа здесь: https://github.com/tatewake/endian-template/
// that are essentially immutable except for the assignment operators.
// All math logic happens outside of the class in the native format
// and an internal set/swap method is used to store the data.
namespace myx { namespace myx {
@ -24,44 +23,20 @@ template< typename T >
class EndianTypesBase class EndianTypesBase
{ {
protected: protected:
#if _MSC_VER #if defined ( _MSC_VER )
#pragma warning ( push ) #pragma warning ( push )
#endif #endif
static T swapBytes( const T& b ) static T swapBytes( const T& b )
{ {
T n; T n;
switch ( sizeof( T ) ) myx::base::span< uint8_t > sn( reinterpret_cast< uint8_t* >( &n ), sizeof( T ) );
{ myx::base::span< const uint8_t > sb( reinterpret_cast< const uint8_t* >( &b ), sizeof( T ) );
case 8: // 64-bit std::reverse_copy( sb.begin(), sb.end(), sn.begin() );
( reinterpret_cast< uint8_t* >( &n ) )[0] = ( reinterpret_cast< const uint8_t* >( &b ) )[7];
( reinterpret_cast< uint8_t* >( &n ) )[1] = ( reinterpret_cast< const uint8_t* >( &b ) )[6];
( reinterpret_cast< uint8_t* >( &n ) )[2] = ( reinterpret_cast< const uint8_t* >( &b ) )[5];
( reinterpret_cast< uint8_t* >( &n ) )[3] = ( reinterpret_cast< const uint8_t* >( &b ) )[4];
( reinterpret_cast< uint8_t* >( &n ) )[4] = ( reinterpret_cast< const uint8_t* >( &b ) )[3];
( reinterpret_cast< uint8_t* >( &n ) )[5] = ( reinterpret_cast< const uint8_t* >( &b ) )[2];
( reinterpret_cast< uint8_t* >( &n ) )[6] = ( reinterpret_cast< const uint8_t* >( &b ) )[1];
( reinterpret_cast< uint8_t* >( &n ) )[7] = ( reinterpret_cast< const uint8_t* >( &b ) )[0];
break;
case 4: // 32-bit
( reinterpret_cast< uint8_t* >( &n ) )[0] = ( reinterpret_cast< const uint8_t* >( &b ) )[3];
( reinterpret_cast< uint8_t* >( &n ) )[1] = ( reinterpret_cast< const uint8_t* >( &b ) )[2];
( reinterpret_cast< uint8_t* >( &n ) )[2] = ( reinterpret_cast< const uint8_t* >( &b ) )[1];
( reinterpret_cast< uint8_t* >( &n ) )[3] = ( reinterpret_cast< const uint8_t* >( &b ) )[0];
break;
case 2: // 16-bit
( reinterpret_cast< uint8_t* >( &n ) )[0] = ( reinterpret_cast< const uint8_t* >( &b ) )[1];
( reinterpret_cast< uint8_t* >( &n ) )[1] = ( reinterpret_cast< const uint8_t* >( &b ) )[0];
break;
default:
assert( 0 ); // Endian swap is only defined for 2, 4, and 8-byte types
break;
} // switch
return( n ); return( n );
} // swapBytes } // swapBytes
#if _MSC_VER #if defined( _MSC_VER )
#pragma warning ( pop ) #pragma warning ( pop )
#endif #endif
}; // class EndianTypesBase }; // class EndianTypesBase
@ -87,7 +62,7 @@ public:
// 1. Set an OE from a PE // 1. Set an OE from a PE
// 2. Get a PE from an OE // 2. Get a PE from an OE
// Storage in // Storage in
explicit LittleEndianType( const T& b ) : LittleEndianType( const T& b ) :
m_data( transform( b ) ) m_data( transform( b ) )
{} {}
template < typename U > explicit LittleEndianType( U const& b ) : template < typename U > explicit LittleEndianType( U const& b ) :
@ -148,7 +123,7 @@ public:
// 1. Set an OE from a PE // 1. Set an OE from a PE
// 2. Get a PE from an OE // 2. Get a PE from an OE
// Storage in // Storage in
explicit BigEndianType( const T& b ) : BigEndianType( const T& b ) :
m_data( transform( b ) ) m_data( transform( b ) )
{} {}
template < typename U > explicit BigEndianType( U const& b ) : template < typename U > explicit BigEndianType( U const& b ) :

View File

@ -7,18 +7,41 @@
// Official repository: https://github.com/boostorg/beast // Official repository: https://github.com/boostorg/beast
// //
#ifndef BOOST_BEAST_CORE_SPAN_HPP #ifndef MYX_BASE_SPAN_HPP_
#define BOOST_BEAST_CORE_SPAN_HPP #define MYX_BASE_SPAN_HPP_
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
namespace boost { namespace myx {
namespace beast {
namespace base {
template< typename ... Ts > struct make_void { typedef void type;};
template< typename ... Ts > using void_t = typename make_void< Ts... >::type;
template< class T, class E, class = void >
struct is_contiguous_container : std::false_type {};
template< class T, class E >
struct is_contiguous_container< T, E, void_t<
decltype(
std::declval< std::size_t& >() = std::declval< T const& >().size(),
std::declval< E*& >() = std::declval< T& >().data() ),
typename std::enable_if<
std::is_same<
typename std::remove_cv< E >::type,
typename std::remove_cv<
typename std::remove_pointer<
decltype( std::declval< T& >().data() )
>::type
>::type
>::value
>::type > > : std::true_type
{};
/** A range of bytes expressed as a ContiguousContainer /** A range of bytes expressed as a ContiguousContainer
@ -77,67 +100,64 @@ public:
@param size The number of elements pointed to by `data` @param size The number of elements pointed to by `data`
*/ */
span(T* data, std::size_t size) span( T* data, std::size_t size ) :
: data_(data), size_(size) data_( data ),
size_( size )
{ {
} }
/** Constructor /** Constructor
@param container The container to construct from @param container The container to construct from
*/ */
template<class ContiguousContainer template< class ContiguousContainer,
#if ! BOOST_BEAST_DOXYGEN class = typename std::enable_if<
, class = typename std::enable_if< is_contiguous_container<
detail::is_contiguous_container<
ContiguousContainer, T >::value >::type ContiguousContainer, T >::value >::type
#endif
> >
explicit explicit
span(ContiguousContainer&& container) span( ContiguousContainer&& container ) :
: data_(container.data()) data_( container.data() ),
, size_(container.size()) size_( container.size() )
{ {
} }
#if ! BOOST_BEAST_DOXYGEN
template<class CharT, class Traits, class Allocator>
explicit
span(std::basic_string<CharT, Traits, Allocator>& s)
: data_(&s[0])
, size_(s.size())
{
}
template< class CharT, class Traits, class Allocator > template< class CharT, class Traits, class Allocator >
explicit explicit
span(std::basic_string<CharT, Traits, Allocator> const& s) span( std::basic_string< CharT, Traits, Allocator >& s ) :
: data_(s.data()) data_( &s[0] ),
, size_(s.size()) size_( s.size() )
{ {
} }
#endif
template< class CharT, class Traits, class Allocator >
explicit
span( std::basic_string< CharT, Traits, Allocator > const& s ) :
data_( s.data() ),
size_( s.size() )
{
}
/** Assignment /** Assignment
@param container The container to assign from @param container The container to assign from
*/ */
template< class ContiguousContainer > template< class ContiguousContainer >
#if BOOST_BEAST_DOXYGEN typename std::enable_if< is_contiguous_container<
span&
#else
typename std::enable_if<detail::is_contiguous_container<
ContiguousContainer, T >::value, ContiguousContainer, T >::value,
span& >::type span& >::type
#endif
operator=( ContiguousContainer&& container ) operator=( ContiguousContainer&& container )
{ {
data_ = container.data(); data_ = container.data();
size_ = container.size(); size_ = container.size();
return *this; return( *this );
} }
#if ! BOOST_BEAST_DOXYGEN
template< class CharT, class Traits, class Allocator > template< class CharT, class Traits, class Allocator >
span& span&
operator=( std::basic_string< operator=( std::basic_string<
@ -145,9 +165,10 @@ public:
{ {
data_ = &s[0]; data_ = &s[0];
size_ = s.size(); size_ = s.size();
return *this; return( *this );
} }
template< class CharT, class Traits, class Allocator > template< class CharT, class Traits, class Allocator >
span& span&
operator=( std::basic_string< operator=( std::basic_string<
@ -155,61 +176,68 @@ public:
{ {
data_ = s.data(); data_ = s.data();
size_ = s.size(); size_ = s.size();
return *this; return( *this );
} }
#endif
/// Returns `true` if the span is empty /// Returns `true` if the span is empty
bool bool
empty() const empty() const
{ {
return size_ == 0; return( size_ == 0 );
} }
/// Returns a pointer to the beginning of the span /// Returns a pointer to the beginning of the span
T* T*
data() const data() const
{ {
return data_; return( data_ );
} }
/// Returns the number of elements in the span /// Returns the number of elements in the span
std::size_t std::size_t
size() const size() const
{ {
return size_; return( size_ );
} }
/// Returns an iterator to the beginning of the span /// Returns an iterator to the beginning of the span
const_iterator iterator
begin() const begin() const
{ {
return data_; return( data_ );
} }
/// Returns an iterator to the beginning of the span /// Returns an iterator to the beginning of the span
const_iterator const_iterator
cbegin() const cbegin() const
{ {
return data_; return( data_ );
} }
/// Returns an iterator to one past the end of the span /// Returns an iterator to one past the end of the span
const_iterator iterator
end() const end() const
{ {
return data_ + size_; return( data_ + size_ );
} }
/// Returns an iterator to one past the end of the span /// Returns an iterator to one past the end of the span
const_iterator const_iterator
cend() const cend() const
{ {
return data_ + size_; return( data_ + size_ );
} }
}; }; // class span
} // beast } // namespace base
} // boost
#endif } // namespace myx
#endif // ifndef MYX_BASE_SPAN_HPP_