corelib/include/ebcl/inline/Sets.hh

640 lines
15 KiB
C++
Raw Normal View History

2017-11-09 09:40:56 +01:00
/******************************************************************************/
/* SETS - INLINE CODE *********************************************************/
/******************************************************************************/
#ifndef _H_EBCL_INLINE_SETS
#define _H_EBCL_INLINE_SETS
#include <ebcl/Sets.hh>
namespace ebcl {
/*= SET IMPLEMENTATION - FULLY DYNAMIC ARRAY =================================*/
template< typename Type , uint32_t Growth >
class T_SetImplementation< Type , ArrayBacked< 0 , Growth > >
{
private:
T_Array< Type > data_;
public:
template< uint32_t G = Growth , typename std::enable_if_t< G == 0 , int > = 0
> T_SetImplementation( ) noexcept;
template< uint32_t G = Growth , typename std::enable_if_t< G != 0 , int > = 0
> T_SetImplementation( ) noexcept;
uint32_t size( ) const noexcept;
int32_t indexOf( Type const& item ) const noexcept;
Type const* access( uint32_t item ) const noexcept;
bool add( Type const& item ) noexcept;
bool add( Type&& item ) noexcept;
bool remove( Type const& item ) noexcept;
void free( ) noexcept;
void clear( ) noexcept;
};
/*----------------------------------------------------------------------------*/
#define M_TMPL_ template< typename Type , uint32_t Growth >
#define M_TYPE_ T_SetImplementation< Type , ArrayBacked< 0 , Growth > >
M_TMPL_
template< uint32_t G , typename std::enable_if_t< G == 0 , int > >
M_TYPE_::T_SetImplementation( ) noexcept
: data_( )
{ }
M_TMPL_
template< uint32_t G , typename std::enable_if_t< G != 0 , int > >
M_TYPE_::T_SetImplementation( ) noexcept
: data_( Growth )
{ }
/*----------------------------------------------------------------------------*/
M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept
{
return data_.size( );
}
M_TMPL_ int32_t M_TYPE_::indexOf(
Type const& item ) const noexcept
{
return data_.indexOf( item );
}
M_TMPL_ Type const* M_TYPE_::access(
const uint32_t item ) const noexcept
{
return &data_[ item ];
}
/*----------------------------------------------------------------------------*/
M_TMPL_ bool M_TYPE_::add(
Type const& item ) noexcept
{
const auto ok( indexOf( item ) == -1 );
if ( ok ) {
data_.add( item );
}
return ok;
}
M_TMPL_ bool M_TYPE_::add(
Type&& item ) noexcept
{
const auto ok( indexOf( item ) == -1 );
if ( ok ) {
data_.add( std::move( item ) );
}
return ok;
}
M_TMPL_ bool M_TYPE_::remove(
Type const& item ) noexcept
{
const auto index( indexOf( item ) );
if ( index >= 0 ) {
data_.removeSwap( index );
}
return index >= 0;
}
/*----------------------------------------------------------------------------*/
M_TMPL_ void M_TYPE_::free( ) noexcept
{
data_.free( );
}
M_TMPL_ void M_TYPE_::clear( ) noexcept
{
data_.clear( );
}
#undef M_TMPL_
#undef M_TYPE_
/*= SET IMPLEMENTATION - AUTOMATIC ARRAY =====================================*/
template< typename Type , uint32_t InPlace , uint32_t Growth >
class T_SetImplementation< Type , ArrayBacked< InPlace , Growth > >
{
private:
T_AutoArray< Type , InPlace ,
Growth == 0 ? ( InPlace * 4 ) : Growth
> data_;
public:
uint32_t size( ) const noexcept;
int32_t indexOf( Type const& item ) const noexcept;
Type const* access( uint32_t item ) const noexcept;
bool add( Type const& item ) noexcept;
bool add( Type&& item ) noexcept;
bool remove( Type const& item ) noexcept;
void free( ) noexcept;
void clear( ) noexcept;
};
/*----------------------------------------------------------------------------*/
#define M_TMPL_ template< typename Type , uint32_t ISize , uint32_t Growth >
#define M_TYPE_ T_SetImplementation< Type , ArrayBacked< ISize , Growth > >
M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept
{
return data_.size( );
}
M_TMPL_ int32_t M_TYPE_::indexOf(
Type const& item ) const noexcept
{
return data_.indexOf( item );
}
M_TMPL_ Type const* M_TYPE_::access(
const uint32_t item ) const noexcept
{
return &data_[ item ];
}
/*----------------------------------------------------------------------------*/
M_TMPL_ bool M_TYPE_::add(
Type const& item ) noexcept
{
const auto ok( indexOf( item ) == -1 );
if ( ok ) {
data_.add( item );
}
return ok;
}
M_TMPL_ bool M_TYPE_::add(
Type&& item ) noexcept
{
const auto ok( indexOf( item ) == -1 );
if ( ok ) {
data_.add( std::move( item ) );
}
return ok;
}
M_TMPL_ bool M_TYPE_::remove(
Type const& item ) noexcept
{
const auto index( indexOf( item ) );
if ( index >= 0 ) {
data_.removeSwap( index );
}
return index >= 0;
}
/*----------------------------------------------------------------------------*/
M_TMPL_ void M_TYPE_::free( ) noexcept
{
data_.free( );
}
M_TMPL_ void M_TYPE_::clear( ) noexcept
{
data_.clear( );
}
#undef M_TMPL_
#undef M_TYPE_
/*= SET IMPLEMENTATION - INDEX ===============================================*/
template<
typename Type ,
uint32_t InitialSize ,
uint32_t HashSize ,
uint32_t Growth
> class T_SetImplementation< Type , IndexBacked< InitialSize , HashSize , Growth > >
{
static_assert( InitialSize > 0 , "invalid initial size" );
static_assert( HashSize > 0 , "invalid hash array size" );
static_assert( Growth > 0 , "invalid growth" );
private:
T_HashIndex index_{ HashSize , InitialSize , Growth };
T_Array< Type > items_{ Growth };
public:
uint32_t size( ) const noexcept;
int32_t indexOf( Type const& item ) const noexcept;
Type const* access( uint32_t item ) const noexcept;
bool add( Type const& item ) noexcept;
bool add( Type&& item ) noexcept;
bool remove( Type const& item ) noexcept;
void free( ) noexcept;
void clear( ) noexcept;
private:
uint32_t find( Type const& k ,
const uint32_t hash ) const noexcept;
};
/*----------------------------------------------------------------------------*/
#define M_TMPL_ template< typename Type , uint32_t ISize , uint32_t HSize , uint32_t Growth >
#define M_TYPE_ T_SetImplementation< Type , IndexBacked< ISize , HSize , Growth > >
M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept
{
return items_.size( );
}
M_TMPL_ int32_t M_TYPE_::indexOf(
Type const& item ) const noexcept
{
const auto idx{ find( item , ComputeHash( item ) ) };
return idx == T_HashIndex::INVALID_INDEX ? -1 : int32_t( idx );
}
M_TMPL_ Type const* M_TYPE_::access(
const uint32_t item ) const noexcept
{
return &items_[ item ];
}
/*----------------------------------------------------------------------------*/
M_TMPL_ bool M_TYPE_::add(
Type const& item ) noexcept
{
const auto hash{ ComputeHash( item ) };
const auto idx{ find( item , hash ) };
if ( idx == T_HashIndex::INVALID_INDEX ) {
index_.add( hash );
items_.add( item );
}
return idx == T_HashIndex::INVALID_INDEX;
}
M_TMPL_ bool M_TYPE_::add(
Type&& item ) noexcept
{
const auto hash{ ComputeHash( item ) };
const auto idx{ find( item , hash ) };
if ( idx == T_HashIndex::INVALID_INDEX ) {
index_.add( hash );
items_.add( std::move( item ) );
}
return idx == T_HashIndex::INVALID_INDEX;
}
M_TMPL_ bool M_TYPE_::remove(
Type const& item ) noexcept
{
const auto hash{ ComputeHash( item ) };
const auto idx{ find( item , hash ) };
if ( idx != T_HashIndex::INVALID_INDEX ) {
items_.removeSwap( idx );
index_.remove( idx );
}
return idx != T_HashIndex::INVALID_INDEX;
}
/*----------------------------------------------------------------------------*/
M_TMPL_ void M_TYPE_::free( ) noexcept
{
index_.free( );
items_.free( );
}
M_TMPL_ void M_TYPE_::clear( ) noexcept
{
index_.clear( );
items_.clear( );
}
/*----------------------------------------------------------------------------*/
M_TMPL_ uint32_t M_TYPE_::find(
Type const& k ,
const uint32_t hash ) const noexcept
{
uint32_t idx = index_.first( hash );
while ( idx != T_HashIndex::INVALID_INDEX ) {
// XXX use a match function?
// if ( match_( keys_[ idx ] , k ) ) {
// break;
// }
if ( items_[ idx ] == k ) {
break;
}
idx = index_.next( idx );
}
return idx;
}
#undef M_TMPL_
#undef M_TYPE_
/*= COMMON HANDLER ===========================================================*/
// In-place version
template< typename Type , typename ImplTag >
void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl(
const E_Operation operation ,
void* const wArg ,
void const* const rArg ,
void* const output )
{
using T_Impl_ = T_SetImplementation< Type , ImplTag >;
switch ( operation ) {
case INIT:
::new ((char*)output) T_Impl_( );
break;
case INIT_COPY:
::new ((char*)output) T_Impl_( *(T_Impl_ const*)rArg );
break;
case INIT_MOVE:
::new ((char*)output) T_Impl_( std::move( *(T_Impl_*)wArg ) );
break;
case DESTROY:
((T_Impl_*)wArg)->~T_Impl_( );
break;
//------------------------------------------------------------------
case SIZE:
*((uint32_t*) output) = ((T_Impl_ const*)rArg)->size( );
break;
case INDEX_OF:
*((uint32_t*) output) = ((T_Impl_ const*)wArg)->indexOf(
*(Type const*) rArg );
break;
case ACCESS:
*((Type const**) output) = ((T_Impl_ const*)rArg)->access(
*(uint32_t const*) wArg );
break;
//------------------------------------------------------------------
case ADD_COPY:
*((bool*)output) = ((T_Impl_*)wArg)->add( *(Type const*) rArg );
break;
case ADD_MOVE:
*((bool*)output) = ((T_Impl_*)wArg)->add(
std::move( *const_cast< Type* >( (Type const*) rArg ) ) );
break;
case REMOVE:
*((bool*)output) = ((T_Impl_*)wArg)->remove( *((Type const*) rArg) );
break;
//------------------------------------------------------------------
case FREE:
((T_Impl_*)wArg)->free( );
break;
case CLEAR:
((T_Impl_*)wArg)->clear( );
break;
}
}
/*----------------------------------------------------------------------------*/
// Heap-allocated implementation
template< typename Type , typename ImplTag >
void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl(
E_Operation operation ,
void* wArg ,
void const* rArg ,
void* output )
{
using T_Impl_ = T_SetImplementation< Type , ImplTag >;
switch ( operation ) {
case INIT:
*(T_Impl_**)output = ::new T_Impl_( );
break;
case INIT_COPY:
*(T_Impl_**)output = ::new T_Impl_( **(T_Impl_ const**)rArg );
2017-11-09 09:40:56 +01:00
break;
case INIT_MOVE:
*(T_Impl_**)output = ::new T_Impl_( std::move( **(T_Impl_**)wArg ) );
2017-11-09 09:40:56 +01:00
break;
case DESTROY:
delete *(T_Impl_**)wArg;
break;
//------------------------------------------------------------------
case SIZE:
*((uint32_t*) output) = (*(T_Impl_ const**)rArg)->size( );
break;
case INDEX_OF:
*((uint32_t*) output) = (*(T_Impl_ const**)wArg)->indexOf(
*(Type const*) rArg );
break;
case ACCESS:
*((Type const**) output) = (*(T_Impl_ const**)rArg)->access(
*(uint32_t const*) wArg );
break;
//------------------------------------------------------------------
case ADD_COPY:
*((bool*)output) = (*(T_Impl_**)wArg)->add( *(Type const*) rArg );
break;
case ADD_MOVE:
*((bool*)output) = (*(T_Impl_**)wArg)->add(
std::move( *const_cast< Type* >( (Type const*) rArg ) ) );
break;
case REMOVE:
*((bool*)output) = (*(T_Impl_**)wArg)->remove( *((Type const*) rArg) );
break;
//------------------------------------------------------------------
case FREE:
(*(T_Impl_**)wArg)->free( );
break;
case CLEAR:
(*(T_Impl_**)wArg)->clear( );
break;
}
}
/*= T_Set ====================================================================*/
template< typename Type >
T_Set< Type >::T_Set( ) noexcept
: T_Set( UseTag< T_SetHelper::DefaultImplementation >( ) )
{ }
template< typename Type >
template< typename Tag >
T_Set< Type >::T_Set( const UseTag< Tag > ) noexcept
: handler_( T_SetHelper::T_Handler< Type , Tag >::shdl )
{
handler_( T_SetHelper::INIT , nullptr , nullptr , &storage_ );
}
/*----------------------------------------------------------------------------*/
template< typename Type >
T_Set< Type >::T_Set(
T_Set const& other ) noexcept
: handler_( other.handler_ )
{
handler_( T_SetHelper::INIT_COPY , nullptr , &other.storage_ , &storage_ );
}
template< typename Type >
T_Set< Type >& T_Set< Type >::operator =(
T_Set const& other ) noexcept
{
handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr );
handler_ = other.handler_;
handler_( T_SetHelper::INIT_COPY , nullptr , &other.storage_ , &storage_ );
return *this;
2017-11-09 09:40:56 +01:00
}
/*----------------------------------------------------------------------------*/
template< typename Type >
T_Set< Type >::T_Set(
T_Set&& other ) noexcept
: handler_( other.handler_ )
{
handler_( T_SetHelper::INIT_MOVE , &other.storage_ , nullptr , &storage_ );
}
template< typename Type >
T_Set< Type >& T_Set< Type >::operator =(
T_Set&& other ) noexcept
{
handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr );
handler_ = other.handler_;
handler_( T_SetHelper::INIT_MOVE , &other.storage_ , nullptr , &storage_ );
return *this;
2017-11-09 09:40:56 +01:00
}
/*----------------------------------------------------------------------------*/
template< typename Type >
T_Set< Type >::~T_Set( )
{
handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr );
}
/*----------------------------------------------------------------------------*/
template< typename Type >
uint32_t T_Set< Type >::size( ) const noexcept
{
uint32_t r;
handler_( T_SetHelper::SIZE , nullptr , &storage_ , &r );
return r;
}
template< typename Type >
bool T_Set< Type >::contains(
Type const& item ) const noexcept
{
return indexOf( item ) >= 0;
}
template< typename Type >
int32_t T_Set< Type >::indexOf(
Type const& item ) const noexcept
{
int32_t r;
handler_( T_SetHelper::INDEX_OF , const_cast< decltype( storage_ )* >( &storage_ ) ,
&item , &r );
return r;
}
template< typename Type >
Type const& T_Set< Type >::operator[](
uint32_t index ) const noexcept
{
Type* ptr;
handler_( T_SetHelper::ACCESS , &index , &storage_ , &ptr );
return *ptr;
}
/*----------------------------------------------------------------------------*/
template< typename Type >
bool T_Set< Type >::add(
Type const& item ) noexcept
{
bool r;
handler_( T_SetHelper::ADD_COPY , &storage_ , &item , &r );
return r;
}
template< typename Type >
bool T_Set< Type >::add(
Type&& item ) noexcept
{
bool r;
handler_( T_SetHelper::ADD_MOVE , &storage_ , &item , &r );
return r;
}
template< typename Type >
bool T_Set< Type >::remove(
Type const& item ) noexcept
{
bool r;
handler_( T_SetHelper::REMOVE , &storage_ , &item , &r );
return r;
}
/*----------------------------------------------------------------------------*/
template< typename Type >
void T_Set< Type >::free( ) noexcept
{
handler_( T_SetHelper::FREE , &storage_ , nullptr , nullptr );
}
template< typename Type >
void T_Set< Type >::clear( ) noexcept
{
handler_( T_SetHelper::CLEAR , &storage_ , nullptr , nullptr );
}
}
#endif // _H_EBCL_INLINE_SETS