/******************************************************************************/ /* ARRAYS - INLINE CODE *******************************************************/ /******************************************************************************/ #ifndef _H_EBCL_INLINE_ARRAYS #define _H_EBCL_INLINE_ARRAYS #include namespace ebcl { /*= T_Array ==================================================================*/ template< typename T > inline T_Array< T >::T_Array( ) noexcept : T_Array( DEFAULT_GROWTH( ) ) { } template< typename T > inline T_Array< T >::T_Array( const uint32_t growth ) noexcept : data_( nullptr ) , capacity_( 0 ) , size_( 0 ) , growth_( growth ) { assert( growth > 0 ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T >::T_Array( T_Array< T > const& source ) noexcept : capacity_( source.capacity_ ) , size_( source.size_ ) , growth_( source.growth_ ) { if ( capacity_ != 0 ) { data_ = ( T* )::operator new ( capacity_ * sizeof( T ) ); if ( std::is_class< T >( ) ) { for ( uint32_t i = 0 ; i < size_ ; i ++ ) { ::new ( ( char* ) &( data_[ i ] ) ) T( source[ i ] ); } } else { memcpy( data_ , source.data_ , source.size_ * sizeof( T ) ); } } else { data_ = nullptr; } } template< typename T > inline T_Array< T >& T_Array< T >::operator= ( T_Array< T > const& other ) noexcept { free( ); capacity_ = other.capacity_; data_ = ( T* )::operator new ( sizeof( T ) * capacity_ ); size_ = other.size_; growth_ = other.growth_; if ( std::is_class< T >( ) ) { for ( uint32_t i = 0 ; i < size_ ; i ++ ) { ::new ( ( char* ) &( data_[ i ] ) )T( other[ i ] ); } } else if ( size_ ) { memcpy( data_ , other.data_ , size_ * sizeof( T ) ); } return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T >::T_Array( T_Array< T >&& source ) noexcept : T_Array( 1 ) { swap( *this , source ); source.clear( ); } template< typename T > inline T_Array< T >& T_Array< T >::operator=( T_Array< T >&& other ) noexcept { swap( *this , other ); other.clear( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline void swap( T_Array< T >& lhs , T_Array< T >& rhs ) noexcept { using std::swap; swap( lhs.data_ , rhs.data_ ); swap( lhs.capacity_ , rhs.capacity_ ); swap( lhs.size_ , rhs.size_ ); swap( lhs.growth_ , rhs.growth_ ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T >::~T_Array( ) { free( ); } template< typename T > inline T_Array< T >& T_Array< T >::clear( ) noexcept { if ( std::is_class< T >( ) ) { for ( uint32_t i = 0 ; i < size_ ; i ++ ) { data_[ i ].~T( ); } } size_ = 0; return *this; } template< typename T > inline T_Array< T >& T_Array< T >::free( ) noexcept { clear( ); ::operator delete ( (void*) data_ ); data_ = nullptr; capacity_ = 0; return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline uint32_t T_Array< T >::capacity( ) const noexcept { return capacity_; } template< typename T > inline uint32_t T_Array< T >::size( ) const noexcept { return size_; } template< typename T > inline uint32_t T_Array< T >::growth( ) const noexcept { return growth_; } template< typename T > inline bool T_Array< T >::empty( ) const noexcept { return size_ != 0; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T >& T_Array< T >::ensureCapacity( const uint32_t capacity ) noexcept { if ( capacity_ < capacity ) { const uint32_t mod( capacity % growth_ ); const uint32_t nCap( capacity + ( mod == 0 ? 0 : ( growth_ - mod ) ) ); T* const nData = ( T* )::operator new ( sizeof( T ) * nCap ); if ( std::is_class< T >( ) ) { for ( uint32_t i = 0 ; i < size_ ; i ++ ) { ::new ( reinterpret_cast< char* >( &nData[ i ] ) ) T( std::move( data_[ i ] ) ); data_[ i ].~T( ); } } else { memcpy( nData , data_ , size_ * sizeof( T ) ); } ::operator delete ( (void*) data_ ); capacity_ = nCap; data_ = nData; } return *this; } template< typename T > template< typename Q , typename > inline T_Array< T >& T_Array< T >::resize( const uint32_t size ) { if ( size > size_ ) { ensureCapacity( size ); for ( auto i = size_ ; i < size_ ; i ++ ) { ::new ( reinterpret_cast< char* >( &data_[ i ] ) ) T( ); } } size_ = size; return *this; } template< typename T > template< typename Q , typename > inline T_Array< T >& T_Array< T >::resize( const uint32_t size , T const& value ) { if ( size > size_ ) { ensureCapacity( size ); for ( auto i = size_ ; i < size_ ; i ++ ) { ::new ( reinterpret_cast< char* >( &data_[ i ] ) ) T( value ); } } size_ = size; return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline T& T_Array< T >::operator[] ( const uint32_t index ) noexcept { assert( index < size_ ); return data_[ index ]; } template< typename T > inline T const& T_Array< T >::operator[] ( const uint32_t index ) const noexcept { assert( index < size_ ); return data_[ index ]; } template< typename T > inline T& T_Array< T >::last( ) noexcept { assert( !empty( ) ); return data_[ size_ - 1 ]; } template< typename T > inline T const& T_Array< T >::last( ) const noexcept { assert( !empty( ) ); return data_[ size_ - 1 ]; } /*----------------------------------------------------------------------------*/ template< typename T > inline int32_t T_Array< T >::indexOf( T const& item ) const noexcept { for ( uint32_t i = 0 ; i < size_ ; i ++ ) { if ( data_[ i ] == item ) { return i; } } return -1; } template< typename T > inline bool T_Array< T >::contains( T const& item ) const noexcept { return indexOf( item ) != -1; } /*----------------------------------------------------------------------------*/ template< typename T > inline uint32_t T_Array< T >::add( T const& item ) noexcept { ensureCapacity( size_ + 1 ); ::new ( ( char* ) &( data_[ size_ ] ) ) T( item ); return size_ ++; } template< typename T > inline uint32_t T_Array< T >::add( T&& item ) noexcept { ensureCapacity( size_ + 1 ); ::new ( ( char* ) &( data_[ size_ ] ) ) T( std::move( item ) ); return size_ ++; } /*----------------------------------------------------------------------------*/ template< typename T > template< typename... Args > inline T& T_Array< T >::addNew( Args&& ... args ) { ensureCapacity( size_ + 1 ); ::new ( ( char* ) &( data_[ size_ ] ) ) T( std::forward< Args >( args ) ... ); return data_[ size_ ++ ]; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T >& T_Array< T >::addAll( T_Array< T > const& other ) noexcept { ensureCapacity( size_ + other.size_ ); if ( std::is_class< T >( ) ) { for ( uint32_t i = 0 ; i < other.size_ ; i ++ ) { ::new ( ( char* ) &( data_[ size_ + i ] ) ) T( other.data_[ i ] ); } } else if ( other.size_ ) { memcpy( data_ + size_ , other.data_ , sizeof( T ) * other.size_ ); } size_ += other.size_; return *this; } template< typename T > inline T_Array< T >& T_Array< T >::addAll( T_Array< T >&& other ) noexcept { ensureCapacity( size_ + other.size_ ); if ( std::is_class< T >( ) ) { for ( uint32_t i = 0 ; i < other.size_ ; i ++ ) { ::new ( ( char* ) &( data_[ size_ + i ] ) ) T( std::move( other.data_[ i ] ) ); } } else if ( other.size_ ) { memcpy( data_ + size_ , other.data_ , sizeof( T ) * other.size_ ); } size_ += other.size_; other.size_ = 0; return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T >& T_Array< T >::operator<< ( T const& item ) noexcept { add( item ); return *this; } template< typename T > inline T_Array< T >& T_Array< T >::operator<< ( T&& item ) noexcept { add( std::move( item ) ); return *this; } template< typename T > inline T_Array< T >& T_Array< T >::operator<< ( T_Array< T > const& other ) noexcept { addAll( other ); return *this; } template< typename T > inline T_Array< T >& T_Array< T >::operator<< ( T_Array< T >&& other ) noexcept { addAll( std::move( other ) ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_Array< T >::insert( const uint32_t index , T const& item ) noexcept { if ( std::is_class< T >( ) ) { using std::swap; const auto last( add( item ) ); for ( uint32_t i = index ; i < last ; i ++ ) { swap( data_[ i ] , data_[ last ] ); } } else { ensureCapacity( size_ + 1 ); if ( index < size_ ) { memmove( &data_[ index + 1 ] , &data_[ index ] , sizeof( T ) * ( size_ - index ) ); } data_[ index ] = item; size_ ++; } } template< typename T > inline void T_Array< T >::insert( const uint32_t index , T&& item ) noexcept { if ( std::is_class< T >( ) ) { using std::swap; const auto last( add( std::move( item ) ) ); for ( uint32_t i = index ; i < last ; i ++ ) { swap( data_[ i ] , data_[ last ] ); } } else { insert( index , (T const&) item ); } } template< typename T > template< typename... Args > inline T& T_Array< T >::insertNew( const uint32_t index , Args&& ... args ) { using std::swap; addNew( std::forward< Args >( args ) ... ); const auto last( size_ - 1 ); for ( uint32_t i = index ; i < last ; i ++ ) { swap( data_[ i ] , data_[ last ] ); } return data_[ index ]; } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_Array< T >::remove( const uint32_t index ) noexcept { assert( index < size_ ); if ( index != size_ - 1 ) { if ( std::is_class< T >( ) ) { for ( auto i = index ; i < size_ - 1 ; i ++ ) { data_[ i ] = std::move( data_[ i + 1 ] ); } } else { memmove( &data_[ index ] , &data_[ index + 1 ] , ( size_ - ( index + 1 ) ) * sizeof( T ) ); } } data_[ size_ - 1 ].~T( ); size_ --; } template< typename T > inline void T_Array< T >::removeSwap( const uint32_t index ) noexcept { assert( index < size_ ); if ( index != size_ - 1 ) { data_[ index ] = std::move( data_[ size_ - 1 ] ); } data_[ size_ - 1 ].~T( ); size_ --; } template< typename T > inline void T_Array< T >::removeLast( ) noexcept { assert( size_ ); data_[ size_ - 1 ].~T( ); size_ --; } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_Array< T >::sort( F_Comparator< T > cmp ) noexcept { sort( 0 , size_ , std::move( cmp ) ); } template< typename T > inline void T_Array< T >::sort( const uint32_t first , const uint32_t items , F_Comparator< T > cmp ) noexcept { if ( items != 0 ) { assert( first < size_ ); assert( first + items <= size_ ); Sort( &data_[ first ] , items , std::move( cmp ) ); } } /*----------------------------------------------------------------------------*/ template< typename T > inline T_Array< T > T_Array< T >::copyRange( const uint32_t first , const uint32_t last ) const noexcept { if ( first >= size_ || last < first ) { return T_Array< T >( 1 ); } // FIXME use memcpy when !std::is_class< T > const auto l( std::min( last , size_ - 1 ) ); T_Array< T > output( growth_ ); output.ensureCapacity( l - first + 1 ); for ( uint32_t i = first ; i <= l ; i ++ ) { output.add( data_[ i ] ); } return output; } template< typename T > inline T_Array< T > T_Array< T >::moveRange( const uint32_t first , const uint32_t last ) noexcept { if ( first >= size_ || last < first ) { return T_Array< T >( 1 ); } // FIXME use memcpy when !std::is_class< T > const auto l( std::min( last , size_ - 1 ) ); T_Array< T > output( growth_ ); output.ensureCapacity( l - first + 1 ); for ( uint32_t i = first ; i <= l ; i ++ ) { output.add( std::move( data_[ i ] ) ); } return output; } /*----------------------------------------------------------------------------*/ #define M_ITER_( NAME ) typename T_Array< T >::T_ ##NAME template< typename T > inline M_ITER_( ConstIterator ) T_Array< T >::begin( ) const noexcept { return T_ConstIterator( *this , 0 ); } template< typename T > inline M_ITER_( ConstIterator ) T_Array< T >::end( ) const noexcept { return T_ConstIterator( *this , size_ ); } template< typename T > inline M_ITER_( Iterator ) T_Array< T >::begin( ) noexcept { return T_Iterator( *this , 0 ); } template< typename T > inline M_ITER_( Iterator ) T_Array< T >::end( ) noexcept { return T_Iterator( *this , size_ ); } template< typename T > inline M_ITER_( ConstReverseIterator ) T_Array< T >::rbegin( ) const noexcept { return T_ConstReverseIterator( *this , 0 ); } template< typename T > inline M_ITER_( ConstReverseIterator ) T_Array< T >::rend( ) const noexcept { return T_ConstReverseIterator( *this , size_ ); } template< typename T > inline M_ITER_( ReverseIterator ) T_Array< T >::rbegin( ) noexcept { return T_ReverseIterator( *this , size_ - 1 ); } template< typename T > inline M_ITER_( ReverseIterator ) T_Array< T >::rend( ) noexcept { return T_ReverseIterator( *this , -1 ); } template< typename T > inline M_ITER_( ConstIterator ) T_Array< T >::cbegin( ) const noexcept { return T_ConstIterator( *this , 0 ); } template< typename T > inline M_ITER_( ConstIterator ) T_Array< T >::cend( ) const noexcept { return T_ConstIterator( *this , size_ ); } template< typename T > inline M_ITER_( ConstReverseIterator ) T_Array< T >::crbegin( ) const noexcept { return T_ConstReverseIterator( *this , 0 ); } template< typename T > inline M_ITER_( ConstReverseIterator ) T_Array< T >::crend( ) const noexcept { return T_ConstReverseIterator( *this , size_ ); } #undef M_ITER_ /*= T_Array::T_Iterator_ =====================================================*/ #define M_HDR_ template< typename T > template< ptrdiff_t D > #define M_CNAME_ T_Array< T >::T_Iterator_< D > #define M_CNAME_T_ typename T_Array< T >::template T_Iterator_< D > /*----------------------------------------------------------------------------*/ M_HDR_ inline M_CNAME_::T_Iterator_( T_Array< T >& array , const ptrdiff_t pos ) noexcept : array_( &array ) , pos_( pos ) { } M_HDR_ inline M_CNAME_::T_Iterator_( ) noexcept : array_( nullptr ) , pos_( 0 ) { } M_HDR_ inline M_CNAME_::T_Iterator_( T_Iterator_ const& other ) noexcept : array_( other.array_ ) , pos_( other.pos_ ) { } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator=( T_Iterator_ const& other ) noexcept { array_ = other.array_; pos_ = other.pos_; return *this; } /*----------------------------------------------------------------------------*/ template< typename T , ptrdiff_t D> inline void swap( M_CNAME_T_& lhs , M_CNAME_T_& rhs ) noexcept { std::swap( lhs.array_ , rhs.array_ ); std::swap( lhs.pos_ , rhs.pos_ ); } /*----------------------------------------------------------------------------*/ M_HDR_ inline bool M_CNAME_::operator==( T_Iterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ == other.pos_; } M_HDR_ inline bool M_CNAME_::operator!=( T_Iterator_ const& other ) const noexcept { return array_ != other.array_ || pos_ != other.pos_; } /*----------------------------------------------------------------------------*/ M_HDR_ inline bool M_CNAME_::operator <( T_Iterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ < other.pos_; } M_HDR_ inline bool M_CNAME_::operator<=( T_Iterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ <= other.pos_; } M_HDR_ inline bool M_CNAME_::operator >( T_Iterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ > other.pos_; } M_HDR_ inline bool M_CNAME_::operator>=( T_Iterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ >= other.pos_; } /*----------------------------------------------------------------------------*/ M_HDR_ inline T& M_CNAME_::operator*( ) const noexcept { assert( valid( ) ); return (*array_)[ pos_ ]; } M_HDR_ inline T* M_CNAME_::operator->( ) const noexcept { assert( valid( ) ); return &((*array_)[ pos_ ]); } M_HDR_ inline T& M_CNAME_::operator[]( const ptrdiff_t pos ) const noexcept { const auto idx( pos + pos_ ); assert( array_ && idx >= 0 && idx < array_->size( ) ); return (*array_)[ idx ]; } /*----------------------------------------------------------------------------*/ M_HDR_ inline M_CNAME_T_& M_CNAME_::operator++ () noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ + D ) ); return *this; } M_HDR_ inline M_CNAME_T_ M_CNAME_::operator++ (int) noexcept { assert( array_ ); auto copy( *this ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ + D ) ); return copy; } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator-- () noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ - D ) ); return *this; } M_HDR_ inline M_CNAME_T_ M_CNAME_::operator-- (int) noexcept { assert( array_ ); auto copy( *this ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ - D ) ); return copy; } /*----------------------------------------------------------------------------*/ M_HDR_ inline M_CNAME_T_ M_CNAME_::operator +( const ptrdiff_t value ) const noexcept { auto copy( *this ); copy += value; return copy; } M_HDR_ inline M_CNAME_T_ M_CNAME_::operator -( const ptrdiff_t value ) const noexcept { auto copy( *this ); copy -= value; return copy; } M_HDR_ inline ptrdiff_t M_CNAME_::operator -( M_CNAME_T_ const& other ) const noexcept { assert( array_ && array_ == other.array_ ); return pos_ - other.pos_; } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator +=( const ptrdiff_t value ) noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ + value * D ) ); return *this; } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator -=( const ptrdiff_t value ) noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ - value * D ) ); return *this; } /*----------------------------------------------------------------------------*/ M_HDR_ inline bool M_CNAME_::valid( ) const noexcept { return array_ && pos_ >= 0 && pos_ < array_->size( ); } M_HDR_ inline T_Array< T >* M_CNAME_::target( ) const noexcept { return array_; } M_HDR_ inline ptrdiff_t M_CNAME_::pos( ) const noexcept { return pos_; } /*----------------------------------------------------------------------------*/ #undef M_HDR_ #undef M_CNAME_ #undef M_CNAME_T_ /*= T_Array::T_ConstIterator_ ================================================*/ #define M_HDR_ template< typename T > template< ptrdiff_t D > #define M_CNAME_ T_Array< T >::T_ConstIterator_< D > #define M_CNAME_T_ typename T_Array< T >::template T_ConstIterator_< D > /*----------------------------------------------------------------------------*/ M_HDR_ inline M_CNAME_::T_ConstIterator_( T_Array< T > const& array , const ptrdiff_t pos ) noexcept : array_( &array ) , pos_( pos ) { } M_HDR_ inline M_CNAME_::T_ConstIterator_( ) noexcept : array_( nullptr ) , pos_( 0 ) { } M_HDR_ inline M_CNAME_::T_ConstIterator_( T_ConstIterator_ const& other ) noexcept : array_( other.array_ ) , pos_( other.pos_ ) { } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator=( T_ConstIterator_ const& other ) noexcept { array_ = other.array_; pos_ = other.pos_; return *this; } /*----------------------------------------------------------------------------*/ template< typename T , ptrdiff_t D> inline void swap( M_CNAME_T_& lhs , M_CNAME_T_& rhs ) noexcept { std::swap( lhs.array_ , rhs.array_ ); std::swap( lhs.pos_ , rhs.pos_ ); } /*----------------------------------------------------------------------------*/ M_HDR_ inline bool M_CNAME_::operator==( T_ConstIterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ == other.pos_; } M_HDR_ inline bool M_CNAME_::operator!=( T_ConstIterator_ const& other ) const noexcept { return array_ != other.array_ || pos_ != other.pos_; } /*----------------------------------------------------------------------------*/ M_HDR_ inline bool M_CNAME_::operator <( T_ConstIterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ < other.pos_; } M_HDR_ inline bool M_CNAME_::operator<=( T_ConstIterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ <= other.pos_; } M_HDR_ inline bool M_CNAME_::operator >( T_ConstIterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ > other.pos_; } M_HDR_ inline bool M_CNAME_::operator>=( T_ConstIterator_ const& other ) const noexcept { return array_ == other.array_ && pos_ >= other.pos_; } /*----------------------------------------------------------------------------*/ M_HDR_ inline T const& M_CNAME_::operator*( ) const noexcept { assert( valid( ) ); return (*array_)[ pos_ ]; } M_HDR_ inline T const* M_CNAME_::operator->( ) const noexcept { assert( valid( ) ); return &((*array_)[ pos_ ]); } M_HDR_ inline T const& M_CNAME_::operator[]( const ptrdiff_t pos ) const noexcept { const auto idx( pos + pos_ ); assert( array_ && idx >= 0 && idx < array_->size( ) ); return (*array_)[ idx ]; } /*----------------------------------------------------------------------------*/ M_HDR_ inline M_CNAME_T_& M_CNAME_::operator++ () noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ + D ) ); return *this; } M_HDR_ inline M_CNAME_T_ M_CNAME_::operator++ (int) noexcept { assert( array_ ); auto copy( *this ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ + D ) ); return copy; } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator-- () noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ - D ) ); return *this; } M_HDR_ inline M_CNAME_T_ M_CNAME_::operator-- (int) noexcept { assert( array_ ); auto copy( *this ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ - D ) ); return copy; } /*----------------------------------------------------------------------------*/ M_HDR_ inline M_CNAME_T_ M_CNAME_::operator +( const ptrdiff_t value ) const noexcept { auto copy( *this ); copy += value; return copy; } M_HDR_ inline M_CNAME_T_ M_CNAME_::operator -( const ptrdiff_t value ) const noexcept { auto copy( *this ); copy -= value; return copy; } M_HDR_ inline ptrdiff_t M_CNAME_::operator -( M_CNAME_T_ const& other ) const noexcept { assert( array_ && array_ == other.array_ ); return pos_ - other.pos_; } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator +=( const ptrdiff_t value ) noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ + value * D ) ); return *this; } M_HDR_ inline M_CNAME_T_& M_CNAME_::operator -=( const ptrdiff_t value ) noexcept { assert( array_ ); pos_ = std::min( ptrdiff_t( array_->size( ) ) , std::max( ptrdiff_t( -1 ) , pos_ - value * D ) ); return *this; } /*----------------------------------------------------------------------------*/ M_HDR_ inline bool M_CNAME_::valid( ) const noexcept { return array_ && pos_ >= 0 && pos_ < array_->size( ); } M_HDR_ inline T_Array< T >* M_CNAME_::target( ) const noexcept { return array_; } M_HDR_ inline ptrdiff_t M_CNAME_::pos( ) const noexcept { return pos_; } /*----------------------------------------------------------------------------*/ #undef M_HDR_ #undef M_CNAME_ #undef M_CNAME_T_ /*= T_StaticArray ============================================================*/ template< typename T , uint32_t S > inline T_StaticArray< T , S >::T_StaticArray( ) noexcept : size_( 0 ) { } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline T_StaticArray< T , S >::T_StaticArray( T_Self const& source ) noexcept : size_( source.size_ ) { if ( std::is_class< T >( ) ) { for ( auto i = 0u ; i < size_ ; i ++ ) { ::new ( (char*) &storage_[ i ] ) T( source[ i ] ); } } else { std::memcpy( &storage_ , &source.storage_ , size_ * sizeof( T_Storage_ ) ); } } template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::operator= ( T_Self const& source ) noexcept { clear( ); size_ = source.size_; if ( std::is_class< T >( ) ) { for ( auto i = 0u ; i < size_ ; i ++ ) { ::new ( (char*) &storage_[ i ] ) T( source[ i ] ); } } else { std::memcpy( &storage_ , &source.storage_ , size_ * sizeof( T_Storage_ ) ); } return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline T_StaticArray< T , S >::T_StaticArray( T_Self&& source ) noexcept : size_( source.size_ ) { if ( std::is_class< T >( ) ) { for ( auto i = 0u ; i < size_ ; i ++ ) { ::new ( (char*) &storage_[ i ] ) T( std::move( source[ i ] ) ); } } else { std::memcpy( &storage_ , &source.storage_ , size_ * sizeof( T_Storage_ ) ); } source.clear( ); } template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::operator= ( T_Self&& source ) noexcept { clear( ); size_ = source.size_; if ( std::is_class< T >( ) ) { for ( auto i = 0u ; i < size_ ; i ++ ) { ::new ( (char*) &storage_[ i ] ) T( std::move( source[ i ] ) ); } } else { std::memcpy( &storage_ , &source.storage_ , size_ * sizeof( T_Storage_ ) ); } source.clear( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline T_StaticArray< T , S >::~T_StaticArray( ) noexcept { clear( ); } template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::clear( ) noexcept { for ( auto i = 0u ; i < size_ ; i ++ ) { reinterpret_cast< T* >( &storage_[ i ] )->T::~T( ); } size_ = 0; return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > void swap( T_StaticArray< T , S >& lhs , T_StaticArray< T , S >& rhs ) noexcept { using T_ = T_StaticArray< T , S >; if ( lhs.size( ) && rhs.size( ) ) { T_ temp( std::move( rhs ) ); rhs = std::move( lhs ); lhs = std::move( temp ); } else if ( lhs.size( ) || rhs.size( ) ) { T_& empty( lhs.size( ) ? rhs : lhs ); T_& notEmpty( lhs.size( ) ? lhs : rhs ); empty = std::move( notEmpty ); } } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline constexpr uint32_t T_StaticArray< T , S >::capacity( ) const noexcept { return S; } template< typename T , uint32_t S > inline uint32_t T_StaticArray< T , S >::size( ) const noexcept { return size_; } template< typename T , uint32_t S > inline bool T_StaticArray< T , S >::empty( ) const noexcept { return size_ != 0; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline T& T_StaticArray< T , S >::operator[] ( const uint32_t index ) noexcept { assert( index < size_ ); return *reinterpret_cast< T* >( &storage_[ index ] ); } template< typename T , uint32_t S > inline T const& T_StaticArray< T , S >::operator[] ( const uint32_t index ) const noexcept { assert( index < size_ ); return *reinterpret_cast< T const* >( &storage_[ index ] ); } template< typename T , uint32_t S > inline T& T_StaticArray< T , S >::last( ) noexcept { assert( !empty( ) ); return *reinterpret_cast< T* >( &storage_[ size_ - 1 ] ); } template< typename T , uint32_t S > inline T const& T_StaticArray< T , S >::last( ) const noexcept { assert( !empty( ) ); return *reinterpret_cast< T const* >( &storage_[ size_ - 1 ] ); } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline int32_t T_StaticArray< T , S >::indexOf( T const& item ) const noexcept { for ( auto i = 0u ; i < size_ ; i ++ ) { if ( (*this)[ i ] == item ) { return i; } } return -1; } template< typename T , uint32_t S > inline bool T_StaticArray< T , S >::contains( T const& item ) const noexcept { return indexOf( item ) != -1; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline uint32_t T_StaticArray< T , S >::add( T&& item ) noexcept { assert( size_ < S ); const auto index( size_ ++ ); ::new ( (char*) &storage_[ index ] ) T( std::move( item ) ); return index; } template< typename T , uint32_t S > inline uint32_t T_StaticArray< T , S >::add( T const& item ) noexcept { assert( size_ < S ); const auto index( size_ ++ ); ::new ( (char*) &storage_[ index ] ) T( item ); return index; } template< typename T , uint32_t S > template< typename... Args > inline T& T_StaticArray< T , S >::addNew( Args&& ... args ) { assert( size_ < S ); const auto index( size_ ++ ); ::new ( (char*) &storage_[ index ] ) T( std::forward< Args >( args ) ... ); return (*this)[ index ]; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > T_StaticArray< T , S >& T_StaticArray< T , S >::addAll( T_Self const& other ) noexcept { assert( size_ + other.size_ <= S ); if ( std::is_class< T >( ) ) { for ( auto i = 0u ; i < other.size_ ; i ++ , size_ ++ ) { ::new ( (char*) &storage_[ size_ ] ) T( other[ i ] ); } } else { memcpy( &storage_[ size_ ] , &other.storage_[ 0 ] , other.size_ * sizeof( T_Storage_ ) ); size_ += other.size_; } return *this; } template< typename T , uint32_t S > T_StaticArray< T , S >& T_StaticArray< T , S >::addAll( T_Self&& other ) noexcept { assert( size_ + other.size_ <= S ); if ( std::is_class< T >( ) ) { for ( auto i = 0u ; i < other.size_ ; i ++ , size_ ++ ) { ::new ( (char*) &storage_[ size_ ] ) T( std::move( other[ i ] ) ); } } else { memcpy( &storage_[ size_ ] , &other.storage_[ 0 ] , other.size_ * sizeof( T_Storage_ ) ); size_ += other.size_; } other.clear( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::operator<< ( T const& item ) noexcept { add( item ); return *this; } template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::operator<< ( T&& item ) noexcept { add( std::move( item ) ); return *this; } template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::operator<< ( T_Self const& other ) noexcept { addAll( other ); return *this; } template< typename T , uint32_t S > inline T_StaticArray< T , S >& T_StaticArray< T , S >::operator<< ( T_Self&& other ) noexcept { addAll( std::move( other ) ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline void T_StaticArray< T , S >::insert( const uint32_t index , T&& item ) noexcept { assert( size_ < S ); if ( std::is_class< T >( ) ) { const auto last( add( std::move( item ) ) ); for ( uint32_t i = index ; i < last ; i ++ ) { using std::swap; swap( (*this)[ i ] , (*this)[ last ] ); } } else { insert( index , (T const&) item ); } } template< typename T , uint32_t S > inline void T_StaticArray< T , S >::insert( const uint32_t index , T const& item ) noexcept { assert( size_ < S ); if ( std::is_class< T >( ) ) { const auto last( add( item ) ); for ( uint32_t i = index ; i < last ; i ++ ) { using std::swap; swap( (*this)[ i ] , (*this)[ last ] ); } } else { if ( index < size_ ) { memmove( &storage_[ index + 1 ] , &storage_[ index ] , sizeof( T_Storage_ ) * ( size_ - index ) ); } *reinterpret_cast< T* >( &storage_[ index ] ) = item; size_ ++; } } template< typename T , uint32_t S > template< typename... Args > inline T& T_StaticArray< T , S >::insertNew( const uint32_t index , Args&& ... args ) { addNew( std::forward< Args >( args ) ... ); const auto last( size_ - 1 ); for ( uint32_t i = index ; i < last ; i ++ ) { swap( (*this)[ i ] , (*this)[ last ] ); } return (*this)[ index ]; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline void T_StaticArray< T , S >::remove( const uint32_t index ) noexcept { assert( index < size_ ); if ( index != size_ - 1 ) { if ( std::is_class< T >( ) ) { for ( auto i = index ; i < size_ - 1 ; i ++ ) { (*this)[ i ] = std::move( (*this)[ i + 1 ] ); } } else { memmove( &storage_[ index ] , &storage_[ index + 1 ] , ( size_ - ( index + 1 ) ) * sizeof( T_Storage_ ) ); } } (*this)[ size_ - 1 ].~T( ); size_ --; } template< typename T , uint32_t S > inline void T_StaticArray< T , S >::removeSwap( const uint32_t index ) noexcept { assert( index < size_ ); if ( index != size_ - 1 ) { (*this)[ index ] = std::move( (*this)[ size_ - 1 ] ); } (*this)[ size_ - 1 ].~T( ); size_ --; } template< typename T , uint32_t S > inline void T_StaticArray< T , S >::removeLast( ) noexcept { assert( size_ ); (*this)[ size_ - 1 ].~T( ); size_ --; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline void T_StaticArray< T , S >::sort( const F_Comparator< T > cmp ) noexcept { sort( 0 , size_ , cmp ); } template< typename T , uint32_t S > inline void T_StaticArray< T , S >::sort( const uint32_t first , const uint32_t items , const F_Comparator< T > cmp ) noexcept { if ( items != 0 ) { assert( first < size_ ); assert( first + items <= size_ ); Sort( &(*this)[ first ] , items , cmp ); } } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S > inline T_StaticArray< T , S > T_StaticArray< T , S >::copyRange( const uint32_t first , const uint32_t last ) const noexcept { if ( first >= size_ || last < first ) { return T_StaticArray< T , S >( ); } const auto l( std::min( last , size_ - 1 ) ); T_StaticArray< T , S > output; // FIXME use memcpy when !std::is_class< T > for ( uint32_t i = first ; i <= l ; i ++ ) { output.add( (*this)[ i ] ); } return output; } template< typename T , uint32_t S > inline T_StaticArray< T , S > T_StaticArray< T , S >::moveRange( const uint32_t first , const uint32_t last ) noexcept { if ( first >= size_ || last < first ) { return T_StaticArray< T , S >( ); } const auto l( std::min( last , size_ - 1 ) ); T_StaticArray< T , S > output; for ( uint32_t i = first ; i <= l ; i ++ ) { output.add( std::move( (*this)[ i ] ) ); } return output; } /*= T_MultiArray ============================================================-*/ template< typename T > inline void swap( T_MultiArray< T >& lhs , T_MultiArray< T >& rhs ) { using std::swap; swap( lhs.meta_ , rhs.meta_ ); swap( lhs.values_ , rhs.values_ ); } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_MultiArray< T >::next( ) { const auto sz( meta_.size( ) ); const auto first( ( sz == 0 ) ? 0 : ( meta_[ sz - 2 ] + meta_[ sz - 1 ] ) ); meta_ << first << 0; } template< typename T > inline void T_MultiArray< T >::add( T value ) { if ( meta_.size( ) == 0 ) { meta_ << 0 << 1; } else { meta_[ meta_.size( ) - 1 ] ++; } values_ << value; } template< typename T > template< typename Q , typename... Args , typename > inline Q& T_MultiArray< T >::addNew( Args&& ... args ) { if ( meta_.size( ) == 0 ) { meta_ << 0 << 1; } else { meta_[ meta_.size( ) - 1 ] ++; } return values_.addNew( std::forward< Args >( args ) ... ); } template< typename T > inline void T_MultiArray< T >::copyFrom( T_Array< T > const& source ) { values_.addAll( source ); if ( meta_.size( ) == 0 ) { meta_ << 0 << source.size( ); } else { meta_[ meta_.size( ) - 1 ] += source.size( ); } } /*----------------------------------------------------------------------------*/ template< typename T > inline uint32_t T_MultiArray< T >::size( ) const { return meta_.size( ) >> 1; } template< typename T > inline uint32_t T_MultiArray< T >::firstOf( uint32_t item ) const { return meta_[ item * 2 ]; } template< typename T > inline uint32_t T_MultiArray< T >::sizeOf( uint32_t item ) const { return meta_[ item * 2 + 1 ]; } /*----------------------------------------------------------------------------*/ template< typename T > inline T const& T_MultiArray< T >::get( uint32_t item , uint32_t sub ) const { assert( sub < meta_[ item * 2 + 1 ] ); return values_[ meta_[ item * 2 ] + sub ]; } template< typename T > inline T& T_MultiArray< T >::get( uint32_t item , uint32_t sub ) { assert( sub < meta_[ item * 2 + 1 ] ); return values_[ meta_[ item * 2 ] + sub ]; } /*----------------------------------------------------------------------------*/ template< typename T > inline T const& T_MultiArray< T >::operator[] ( uint32_t index ) const { return values_[ index ]; } template< typename T > inline T& T_MultiArray< T >::operator[] ( uint32_t index ) { return values_[ index ]; } /*----------------------------------------------------------------------------*/ template< typename T > inline bool T_MultiArray< T >::contains( uint32_t index , T const& value ) const { const auto first( firstOf( index ) ); const auto end( first + sizeOf( index ) ); for ( uint32_t i = first ; i < end ; i ++ ) { if ( values_[ i ] == value ) { return true; } } return false; } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_MultiArray< T >::clear( ) { meta_.clear( ); values_.clear( ); } template< typename T > inline void T_MultiArray< T >::free( ) { meta_.free( ); values_.free( ); } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_MultiArray< T >::copyFrom( uint32_t index ) { copyFrom( *this , index ); } template< typename T > inline void T_MultiArray< T >::copyFrom( T_MultiArray< T > const& other , uint32_t index ) { const auto size( other.sizeOf( index ) ); if ( size == 0 ) { return; } const auto first( other.firstOf( index ) ); T const* ptr( &( other[ first ] ) ); for ( uint32_t i = 0 ; i < size ; i ++ , ptr ++ ) { values_ << *ptr; } if ( meta_.size( ) == 0 ) { meta_ << 0 << size; } else { meta_[ meta_.size( ) - 1 ] += size; } } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_MultiArray< T >::copyUnique( uint32_t index ) { copyUnique( *this , index ); } template< typename T > inline void T_MultiArray< T >::copyUnique( T_MultiArray< T > const& other , uint32_t index ) { const auto oSize( other.sizeOf( index ) ); if ( oSize == 0 ) { return; } const auto ms( meta_.size( ) ); const auto tSize( ms == 0 ? 0 : meta_[ ms - 1 ] ); const auto tFirst( ms == 0 ? 0 : meta_[ ms - 2 ] ); const auto oFirst( other.firstOf( index ) ); T const* ptr( &( other[ oFirst ] ) ); uint32_t added = 0; for ( uint32_t i = 0 ; i < oSize ; i ++ , ptr ++ ) { bool found = false; if ( tSize != 0 ) { T const* pCheck( &values_[ tFirst ] ); for ( uint32_t j = 0 ; j < tSize ; j ++ , pCheck ++ ) { if ( *pCheck == *ptr ) { found = true; break; } } } if ( !found ) { values_ << *ptr; added ++; } } if ( ms == 0 ) { meta_ << 0 << added; } else { meta_[ ms - 1 ] += added; } } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_MultiArray< T >::sort( uint32_t index , F_Comparator< T > cmp ) { values_.sort( meta_[ index * 2 ] , meta_[ index * 2 + 1 ] , cmp ); } /*= T_AutoArray ==============================================================*/ template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >::T_AutoArray( ) noexcept : array_( ) { } template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >::T_AutoArray( T_Self const& source ) noexcept : array_( source.array_ ) { } template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::operator =( T_Self const& source ) noexcept { array_ = source.array_; return *this; } template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >::T_AutoArray( T_Self&& source ) noexcept : array_( std::move( source.array_ ) ) { } template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::operator =( T_Self&& source ) noexcept { array_ = std::move( source.array_ ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline void swap( T_AutoArray< T , S , G >& lhs , T_AutoArray< T , S , G >& rhs ) noexcept { swap( lhs.array_ , rhs.array_ ); } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::clear( ) noexcept { if ( isStatic( ) ) { static_( ).clear( ); } else { dynamic_( ).clear( ); } return *this; } template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::free( ) noexcept { array_ = T_Static_( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline uint32_t T_AutoArray< T , S , G >::capacity( ) const noexcept { return isStatic( ) ? S : dynamic_( ).capacity( ); } template< typename T , uint32_t S , uint32_t G > inline uint32_t T_AutoArray< T , S , G >::size( ) const noexcept { return isStatic( ) ? static_( ).size( ) : dynamic_( ).size( ); } template< typename T , uint32_t S , uint32_t G > inline constexpr uint32_t T_AutoArray< T , S , G >::growth( ) const noexcept { return G; } template< typename T , uint32_t S , uint32_t G > inline bool T_AutoArray< T , S , G >::isStatic( ) const noexcept { return array_.template hasType< T_Static_ >( ); } template< typename T , uint32_t S , uint32_t G > inline bool T_AutoArray< T , S , G >::empty( ) const noexcept { return size( ) != 0; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::ensureCapacity( const uint32_t capacity ) noexcept { if ( capacity > S ) { if ( isStatic( ) ) { convertToDynamic_( capacity ); } else { dynamic_( ).ensureCapacity( capacity ); } } return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline T& T_AutoArray< T , S , G >::operator[] ( const uint32_t index ) noexcept { return isStatic( ) ? static_( )[ index ] : dynamic_( )[ index ]; } template< typename T , uint32_t S , uint32_t G > inline T const& T_AutoArray< T , S , G >::operator[] ( const uint32_t index ) const noexcept { return isStatic( ) ? static_( )[ index ] : dynamic_( )[ index ]; } template< typename T , uint32_t S , uint32_t G > inline T& T_AutoArray< T , S , G >::last( ) noexcept { assert( !empty( ) ); return (*this)[ size( ) - 1 ]; } template< typename T , uint32_t S , uint32_t G > inline T const& T_AutoArray< T , S , G >::last( ) const noexcept { assert( !empty( ) ); return (*this)[ size( ) - 1 ]; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline int32_t T_AutoArray< T , S , G >::indexOf( T const& item ) const noexcept { return isStatic( ) ? static_( ).indexOf( item ) : dynamic_( ).indexOf( item ); } template< typename T , uint32_t S , uint32_t G > inline bool T_AutoArray< T , S , G >::contains( T const& item ) const noexcept { return indexOf( item ) != -1; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline uint32_t T_AutoArray< T , S , G >::add( T const& item ) noexcept { ensureCapacity( size( ) + 1 ); return isStatic( ) ? static_( ).add( item ) : dynamic_( ).add( item ); } template< typename T , uint32_t S , uint32_t G > inline uint32_t T_AutoArray< T , S , G >::add( T&& item ) noexcept { ensureCapacity( size( ) + 1 ); return isStatic( ) ? static_( ).add( std::move( item ) ) : dynamic_( ).add( std::move( item ) ); } template< typename T , uint32_t S , uint32_t G > template< typename... Args > inline T& T_AutoArray< T , S , G >::addNew( Args&& ... args ) { ensureCapacity( size( ) + 1 ); return isStatic( ) ? static_( ).addNew( std::forward< Args >( args ) ... ) : dynamic_( ).addNew( std::forward< Args >( args ) ... ); } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::addAll( T_Self const& other ) noexcept { const auto osz( other.size( ) ); if ( !osz ) { return *this; } // Try using container's native addAll() if we can const auto inisz( size( ) ); const bool tst( isStatic( ) ); const bool ost( other.isStatic( ) ); if ( tst == ost && ( !tst || inisz + osz <= S ) ) { if ( tst ) { static_( ).addAll( other.static_( ) ); } else { dynamic_( ).addAll( other.dynamic_( ) ); } return *this; } // Otherwise we need to add manually. ensureCapacity( inisz + osz ); if ( isStatic( ) ) { for ( uint32_t i = 0 ; i < osz ; i ++ ) { static_( ).add( other[ i ] ); } } else { for ( uint32_t i = 0 ; i < osz ; i ++ ) { dynamic_( ).add( other[ i ] ); } } return *this; } template< typename T , uint32_t S , uint32_t G > inline T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::addAll( T_Self&& other ) noexcept { const auto osz( other.size( ) ); if ( !osz ) { return *this; } // Try using container's native addAll() if we can const auto inisz( size( ) ); const bool tst( isStatic( ) ); const bool ost( other.isStatic( ) ); if ( tst == ost && ( !tst || inisz + osz <= S ) ) { if ( tst ) { static_( ).addAll( std::move( other.static_( ) ) ); } else { dynamic_( ).addAll( std::move( other.dynamic_( ) ) ); } return *this; } // Otherwise we need to add manually. ensureCapacity( inisz + osz ); if ( isStatic( ) ) { for ( uint32_t i = 0 ; i < osz ; i ++ ) { static_( ).add( std::move( other[ i ] ) ); } } else { for ( uint32_t i = 0 ; i < osz ; i ++ ) { dynamic_( ).add( std::move( other[ i ] ) ); } } other.free( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline void T_AutoArray< T , S , G >::insert( const uint32_t index , T const& item ) noexcept { ensureCapacity( size( ) + 1 ); return isStatic( ) ? static_( ).insert( index , item ) : dynamic_( ).insert( index , item ); } template< typename T , uint32_t S , uint32_t G > inline void T_AutoArray< T , S , G >::insert( const uint32_t index , T&& item ) noexcept { ensureCapacity( size( ) + 1 ); return isStatic( ) ? static_( ).insert( index , std::move( item ) ) : dynamic_( ).insert( index , std::move( item ) ); } template< typename T , uint32_t S , uint32_t G > template< typename... Args > inline T& T_AutoArray< T , S , G >::insertNew( const uint32_t index , Args&& ... args ) { ensureCapacity( size( ) + 1 ); return isStatic( ) ? static_( ).insertNew( index , std::forward< Args >( args ) ... ) : dynamic_( ).insertNew( index , std::forward< Args >( args ) ... ); } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline void T_AutoArray< T , S , G >::remove( const uint32_t index ) noexcept { isStatic( ) ? static_( ).remove( index ) : dynamic_( ).remove( index ); } template< typename T , uint32_t S , uint32_t G > inline void T_AutoArray< T , S , G >::removeSwap( const uint32_t index ) noexcept { isStatic( ) ? static_( ).removeSwap( index ) : dynamic_( ).removeSwap( index ); } template< typename T , uint32_t S , uint32_t G > inline void T_AutoArray< T , S , G >::removeLast( ) noexcept { assert( !empty( ) ); remove( size( ) - 1 ); } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > void T_AutoArray< T , S , G >::sort( F_Comparator< T > cmp ) noexcept { sort( 0 , size( ) , std::move( cmp ) ); } template< typename T , uint32_t S , uint32_t G > void T_AutoArray< T , S , G >::sort( const uint32_t first , const uint32_t items , F_Comparator< T > cmp ) noexcept { if ( isStatic( ) ) { static_( ).sort( first , items , std::move( cmp ) ); } else { dynamic_( ).sort( first , items , std::move( cmp ) ); } } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > T_AutoArray< T , S , G > T_AutoArray< T , S , G >::copyRange( const uint32_t first , const uint32_t last ) const noexcept { // XXX: this uses manual calls to underlying add() methods; it could // be optimised, but I'm not sure it's necessary to do so. auto const sz( size( ) ); if ( first >= sz || last < first ) { return T_Self( ); } const auto l( std::min( last , sz - 1 ) ); T_Self nd; nd.ensureCapacity( l - first + 1 ); if ( isStatic( ) ) { T_Static_ const& src( static_( ) ); T_Static_& dst( nd.static_( ) ); for ( auto i = first ; i <= l ; i ++ ) { dst.add( src[ i ] ); } } else if ( nd.isStatic( ) ) { T_Dynamic_ const& src( dynamic_( ) ); T_Static_& dst( nd.static_( ) ); for ( auto i = first ; i <= l ; i ++ ) { dst.add( src[ i ] ); } } else { T_Dynamic_ const& src( dynamic_( ) ); T_Dynamic_& dst( nd.dynamic_( ) ); for ( auto i = first ; i <= l ; i ++ ) { dst.add( src[ i ] ); } } return nd; } template< typename T , uint32_t S , uint32_t G > T_AutoArray< T , S , G > T_AutoArray< T , S , G >::moveRange( const uint32_t first , const uint32_t last ) noexcept { // XXX: this uses manual calls to underlying add() methods; it could // be optimised, but I'm not sure it's necessary to do so. auto const sz( size( ) ); if ( first >= sz || last < first ) { return T_Self( ); } const auto l( std::min( last , sz - 1 ) ); T_Self nd; nd.ensureCapacity( l - first + 1 ); if ( isStatic( ) ) { T_Static_& src( static_( ) ); T_Static_& dst( nd.static_( ) ); for ( auto i = first ; i <= l ; i ++ ) { dst.add( std::move( src[ i ] ) ); } } else if ( nd.isStatic( ) ) { T_Dynamic_& src( dynamic_( ) ); T_Static_& dst( nd.static_( ) ); for ( auto i = first ; i <= l ; i ++ ) { dst.add( std::move( src[ i ] ) ); } } else { T_Dynamic_& src( dynamic_( ) ); T_Dynamic_& dst( nd.dynamic_( ) ); for ( auto i = first ; i <= l ; i ++ ) { dst.add( std::move( src[ i ] ) ); } } return nd; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > void T_AutoArray< T , S , G >::convertToDynamic_( const uint32_t capacity ) noexcept { assert( isStatic( ) ); T_Static_& s( static_( ) ); T_Dynamic_ d{ G }; d.ensureCapacity( std::max( s.capacity( ) , capacity ) ); auto const sz( s.size( ) ); for ( auto i = 0u ; i < sz ; i ++ ) { d.add( std::move( s[ i ] ) ); } array_ = std::move( d ); } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::operator<< ( T const& item ) noexcept { add( item ); return *this; } template< typename T , uint32_t S , uint32_t G > T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::operator<< ( T&& item ) noexcept { add( std::move( item ) ); return *this; } template< typename T , uint32_t S , uint32_t G > T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::operator<< ( T_Self const& other ) noexcept { addAll( other ); return *this; } template< typename T , uint32_t S , uint32_t G > T_AutoArray< T , S , G >& T_AutoArray< T , S , G >::operator<< ( T_Self&& other ) noexcept { addAll( std::move( other ) ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T , uint32_t S , uint32_t G > inline T_StaticArray< T , S >& T_AutoArray< T , S , G >::static_( ) noexcept { return array_.template value< T_Static_ >( ); } template< typename T , uint32_t S , uint32_t G > inline T_StaticArray< T , S > const& T_AutoArray< T , S , G >::static_( ) const noexcept { return array_.template value< T_Static_ >( ); } template< typename T , uint32_t S , uint32_t G > inline T_Array< T >& T_AutoArray< T , S , G >::dynamic_( ) noexcept { return array_.template value< T_Dynamic_ >( ); } template< typename T , uint32_t S , uint32_t G > inline T_Array< T > const& T_AutoArray< T , S , G >::dynamic_( ) const noexcept { return array_.template value< T_Dynamic_ >( ); } } // namespace #endif // _H_EBCL_INLINE_ARRAYS