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
@ -28,188 +51,193 @@ namespace beast {
@tparam T The type pointed to by span iterators @tparam T The type pointed to by span iterators
*/ */
template<class T> template< class T >
class span class span
{ {
T* data_ = nullptr; T* data_ = nullptr;
std::size_t size_ = 0; std::size_t size_ = 0;
public: public:
/// The type of value, including cv qualifiers /// The type of value, including cv qualifiers
using element_type = T; using element_type = T;
/// The type of value of each span element /// The type of value of each span element
using value_type = typename std::remove_const<T>::type; using value_type = typename std::remove_const< T >::type;
/// The type of integer used to index the span /// The type of integer used to index the span
using index_type = std::ptrdiff_t; using index_type = std::ptrdiff_t;
/// A pointer to a span element /// A pointer to a span element
using pointer = T*; using pointer = T*;
/// A reference to a span element /// A reference to a span element
using reference = T&; using reference = T&;
/// The iterator used by the container /// The iterator used by the container
using iterator = pointer; using iterator = pointer;
/// The const pointer used by the container /// The const pointer used by the container
using const_pointer = T const*; using const_pointer = T const*;
/// The const reference used by the container /// The const reference used by the container
using const_reference = T const&; using const_reference = T const&;
/// The const iterator used by the container /// The const iterator used by the container
using const_iterator = const_pointer; using const_iterator = const_pointer;
/// Constructor /// Constructor
span() = default; span() = default;
/// Constructor /// Constructor
span(span const&) = default; span( span const& ) = default;
/// Assignment /// Assignment
span& operator=(span const&) = default; span& operator=( span const& ) = default;
/** Constructor /** Constructor
@param data A pointer to the beginning of the range of elements @param data A pointer to the beginning of the range of elements
@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
@param container The container to construct from /** Constructor
*/
template<class ContiguousContainer
#if ! BOOST_BEAST_DOXYGEN
, class = typename std::enable_if<
detail::is_contiguous_container<
ContiguousContainer, T>::value>::type
#endif
>
explicit
span(ContiguousContainer&& container)
: data_(container.data())
, size_(container.size())
{
}
#if ! BOOST_BEAST_DOXYGEN @param container The container to construct from
template<class CharT, class Traits, class Allocator> */
explicit template< class ContiguousContainer,
span(std::basic_string<CharT, Traits, Allocator>& s) class = typename std::enable_if<
: data_(&s[0]) is_contiguous_container<
, size_(s.size()) ContiguousContainer, T >::value >::type
{ >
} explicit
span( ContiguousContainer&& container ) :
data_( container.data() ),
size_( container.size() )
{
}
template<class CharT, class Traits, class Allocator>
explicit
span(std::basic_string<CharT, Traits, Allocator> const& s)
: data_(s.data())
, size_(s.size())
{
}
#endif
/** Assignment template< class CharT, class Traits, class Allocator >
explicit
span( std::basic_string< CharT, Traits, Allocator >& s ) :
data_( &s[0] ),
size_( s.size() )
{
}
@param container The container to assign from
*/
template<class ContiguousContainer>
#if BOOST_BEAST_DOXYGEN
span&
#else
typename std::enable_if<detail::is_contiguous_container<
ContiguousContainer, T>::value,
span&>::type
#endif
operator=(ContiguousContainer&& container)
{
data_ = container.data();
size_ = container.size();
return *this;
}
#if ! BOOST_BEAST_DOXYGEN template< class CharT, class Traits, class Allocator >
template<class CharT, class Traits, class Allocator> explicit
span& span( std::basic_string< CharT, Traits, Allocator > const& s ) :
operator=(std::basic_string< data_( s.data() ),
CharT, Traits, Allocator>& s) size_( s.size() )
{ {
data_ = &s[0]; }
size_ = s.size();
return *this;
}
template<class CharT, class Traits, class Allocator>
span&
operator=(std::basic_string<
CharT, Traits, Allocator> const& s)
{
data_ = s.data();
size_ = s.size();
return *this;
}
#endif
/// Returns `true` if the span is empty /** Assignment
bool
empty() const
{
return size_ == 0;
}
/// Returns a pointer to the beginning of the span @param container The container to assign from
T* */
data() const template< class ContiguousContainer >
{ typename std::enable_if< is_contiguous_container<
return data_; ContiguousContainer, T >::value,
} span& >::type
operator=( ContiguousContainer&& container )
{
data_ = container.data();
size_ = container.size();
return( *this );
}
/// Returns the number of elements in the span
std::size_t
size() const
{
return size_;
}
/// Returns an iterator to the beginning of the span template< class CharT, class Traits, class Allocator >
const_iterator span&
begin() const operator=( std::basic_string<
{ CharT, Traits, Allocator >& s )
return data_; {
} data_ = &s[0];
size_ = s.size();
return( *this );
}
/// Returns an iterator to the beginning of the span
const_iterator
cbegin() const
{
return data_;
}
/// Returns an iterator to one past the end of the span template< class CharT, class Traits, class Allocator >
const_iterator span&
end() const operator=( std::basic_string<
{ CharT, Traits, Allocator > const& s )
return data_ + size_; {
} data_ = s.data();
size_ = s.size();
return( *this );
}
/// Returns an iterator to one past the end of the span
const_iterator
cend() const
{
return data_ + size_;
}
};
} // beast /// Returns `true` if the span is empty
} // boost bool
empty() const
{
return( size_ == 0 );
}
#endif
/// Returns a pointer to the beginning of the span
T*
data() const
{
return( data_ );
}
/// Returns the number of elements in the span
std::size_t
size() const
{
return( size_ );
}
/// Returns an iterator to the beginning of the span
iterator
begin() const
{
return( data_ );
}
/// Returns an iterator to the beginning of the span
const_iterator
cbegin() const
{
return( data_ );
}
/// Returns an iterator to one past the end of the span
iterator
end() const
{
return( data_ + size_ );
}
/// Returns an iterator to one past the end of the span
const_iterator
cend() const
{
return( data_ + size_ );
}
}; // class span
} // namespace base
} // namespace myx
#endif // ifndef MYX_BASE_SPAN_HPP_