diff --git a/src/myx/base/CMakeLists.txt b/src/myx/base/CMakeLists.txt index 5388d60..fa6b9bd 100644 --- a/src/myx/base/CMakeLists.txt +++ b/src/myx/base/CMakeLists.txt @@ -10,6 +10,7 @@ set(TRGT_cpp set(TRGT_hpp ${CMAKE_CURRENT_SOURCE_DIR}/config.hpp ${CMAKE_CURRENT_SOURCE_DIR}/limits.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/span.hpp ${CMAKE_CURRENT_SOURCE_DIR}/endian_types.hpp ${CMAKE_CURRENT_SOURCE_DIR}/enum_bitmask_operations.hpp) diff --git a/src/myx/base/endian_types.hpp b/src/myx/base/endian_types.hpp index 7397033..9573522 100644 --- a/src/myx/base/endian_types.hpp +++ b/src/myx/base/endian_types.hpp @@ -3,6 +3,8 @@ #pragma once +#include "span.hpp" + #include #include #include @@ -11,10 +13,7 @@ #include #endif -// Both LittleEndianType and BigEndianType are manufactured primitives -// 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. +// Основа здесь: https://github.com/tatewake/endian-template/ namespace myx { @@ -24,44 +23,20 @@ template< typename T > class EndianTypesBase { protected: - #if _MSC_VER + #if defined ( _MSC_VER ) #pragma warning ( push ) #endif static T swapBytes( const T& b ) { T n; - switch ( sizeof( T ) ) - { - case 8: // 64-bit - ( 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 - + 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 ) ); + std::reverse_copy( sb.begin(), sb.end(), sn.begin() ); return( n ); } // swapBytes - #if _MSC_VER + #if defined( _MSC_VER ) #pragma warning ( pop ) #endif }; // class EndianTypesBase @@ -87,7 +62,7 @@ public: // 1. Set an OE from a PE // 2. Get a PE from an OE // Storage in - explicit LittleEndianType( const T& b ) : + LittleEndianType( const T& b ) : m_data( transform( b ) ) {} template < typename U > explicit LittleEndianType( U const& b ) : @@ -148,7 +123,7 @@ public: // 1. Set an OE from a PE // 2. Get a PE from an OE // Storage in - explicit BigEndianType( const T& b ) : + BigEndianType( const T& b ) : m_data( transform( b ) ) {} template < typename U > explicit BigEndianType( U const& b ) : diff --git a/src/myx/base/span.hpp b/src/myx/base/span.hpp index 55a1454..30e626f 100644 --- a/src/myx/base/span.hpp +++ b/src/myx/base/span.hpp @@ -7,18 +7,41 @@ // Official repository: https://github.com/boostorg/beast // -#ifndef BOOST_BEAST_CORE_SPAN_HPP -#define BOOST_BEAST_CORE_SPAN_HPP +#ifndef MYX_BASE_SPAN_HPP_ +#define MYX_BASE_SPAN_HPP_ -#include -#include #include #include #include #include -namespace boost { -namespace beast { +namespace myx { + +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 @@ -28,188 +51,193 @@ namespace beast { @tparam T The type pointed to by span iterators */ -template +template< class T > class span { - T* data_ = nullptr; - std::size_t size_ = 0; + T* data_ = nullptr; + std::size_t size_ = 0; public: - /// The type of value, including cv qualifiers - using element_type = T; + /// The type of value, including cv qualifiers + using element_type = T; - /// The type of value of each span element - using value_type = typename std::remove_const::type; + /// The type of value of each span element + using value_type = typename std::remove_const< T >::type; - /// The type of integer used to index the span - using index_type = std::ptrdiff_t; + /// The type of integer used to index the span + using index_type = std::ptrdiff_t; - /// A pointer to a span element - using pointer = T*; + /// A pointer to a span element + using pointer = T*; - /// A reference to a span element - using reference = T&; + /// A reference to a span element + using reference = T&; - /// The iterator used by the container - using iterator = pointer; + /// The iterator used by the container + using iterator = pointer; - /// The const pointer used by the container - using const_pointer = T const*; + /// The const pointer used by the container + using const_pointer = T const*; - /// The const reference used by the container - using const_reference = T const&; + /// The const reference used by the container + using const_reference = T const&; - /// The const iterator used by the container - using const_iterator = const_pointer; + /// The const iterator used by the container + using const_iterator = const_pointer; - /// Constructor - span() = default; + /// Constructor + span() = default; - /// Constructor - span(span const&) = default; + /// Constructor + span( span const& ) = default; - /// Assignment - span& operator=(span const&) = default; + /// Assignment + 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` - */ - span(T* data, std::size_t size) - : data_(data), size_(size) - { - } + @param size The number of elements pointed to by `data` + */ + span( T* data, std::size_t size ) : + data_( data ), + size_( size ) + { + } - /** Constructor - @param container The container to construct from - */ - template::value>::type -#endif - > - explicit - span(ContiguousContainer&& container) - : data_(container.data()) - , size_(container.size()) - { - } + /** Constructor -#if ! BOOST_BEAST_DOXYGEN - template - explicit - span(std::basic_string& s) - : data_(&s[0]) - , size_(s.size()) - { - } + @param container The container to construct from + */ + template< class ContiguousContainer, + class = typename std::enable_if< + is_contiguous_container< + ContiguousContainer, T >::value >::type + > + explicit + span( ContiguousContainer&& container ) : + data_( container.data() ), + size_( container.size() ) + { + } - template - explicit - span(std::basic_string 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 -#if BOOST_BEAST_DOXYGEN - span& -#else - typename std::enable_if::value, - span&>::type -#endif - operator=(ContiguousContainer&& container) - { - data_ = container.data(); - size_ = container.size(); - return *this; - } -#if ! BOOST_BEAST_DOXYGEN - template - span& - operator=(std::basic_string< - CharT, Traits, Allocator>& s) - { - data_ = &s[0]; - size_ = s.size(); - return *this; - } + template< class CharT, class Traits, class Allocator > + explicit + span( std::basic_string< CharT, Traits, Allocator > const& s ) : + data_( s.data() ), + size_( s.size() ) + { + } - template - 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 - bool - empty() const - { - return size_ == 0; - } + /** Assignment - /// Returns a pointer to the beginning of the span - T* - data() const - { - return data_; - } + @param container The container to assign from + */ + template< class ContiguousContainer > + typename std::enable_if< is_contiguous_container< + 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 - const_iterator - begin() const - { - return data_; - } + template< class CharT, class Traits, class Allocator > + span& + operator=( std::basic_string< + CharT, Traits, Allocator >& s ) + { + 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 - const_iterator - end() const - { - return data_ + size_; - } + 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 ); + } - /// Returns an iterator to one past the end of the span - const_iterator - cend() const - { - return data_ + size_; - } -}; -} // beast -} // boost + /// Returns `true` if the span is empty + 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_