corelib/include/ebcl/inline/Arrays.hh

2191 lines
52 KiB
C++

/******************************************************************************/
/* ARRAYS - INLINE CODE *******************************************************/
/******************************************************************************/
#ifndef _H_EBCL_INLINE_ARRAYS
#define _H_EBCL_INLINE_ARRAYS
#include <ebcl/Arrays.hh>
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( valid( ) );
pos_ += D;
return *this;
}
M_HDR_ inline M_CNAME_T_ M_CNAME_::operator++ (int) noexcept
{
assert( valid( ) );
auto copy( *this );
pos_ += D;
return copy;
}
M_HDR_ inline M_CNAME_T_& M_CNAME_::operator-- () noexcept
{
assert( valid( ) );
pos_ -= D;
return *this;
}
M_HDR_ inline M_CNAME_T_ M_CNAME_::operator-- (int) noexcept
{
assert( valid( ) );
auto copy( *this );
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( valid( ) );
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( valid( ) );
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( valid( ) );
pos_ += D;
return *this;
}
M_HDR_ inline M_CNAME_T_ M_CNAME_::operator++ (int) noexcept
{
assert( valid( ) );
auto copy( *this );
pos_ += D;
return copy;
}
M_HDR_ inline M_CNAME_T_& M_CNAME_::operator-- () noexcept
{
assert( valid( ) );
pos_ -= D;
return *this;
}
M_HDR_ inline M_CNAME_T_ M_CNAME_::operator-- (int) noexcept
{
assert( valid( ) );
auto copy( *this );
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( valid( ) );
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( valid( ) );
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