2017-11-01 20:14:23 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
/* ARRAYS - INLINE CODE *******************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2017-11-01 21:44:54 +01:00
|
|
|
#ifndef _H_EBCL_INLINE_ARRAYS
|
|
|
|
#define _H_EBCL_INLINE_ARRAYS
|
|
|
|
#include <ebcl/Arrays.hh>
|
|
|
|
namespace ebcl {
|
2017-11-01 20:14:23 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*= 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 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 >
|
|
|
|
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 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 >::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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*= 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 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 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 >::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 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 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
|
|
|
|
{
|
|
|
|
return 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
|
|
|
|
{
|
|
|
|
return isStatic( )
|
|
|
|
? static_( ).removeSwap( index )
|
|
|
|
: dynamic_( ).removeSwap( index );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
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
|
2017-11-01 21:44:54 +01:00
|
|
|
#endif // _H_EBCL_INLINE_ARRAYS
|