/******************************************************************************/ /* SETS - INLINE CODE *********************************************************/ /******************************************************************************/ #ifndef _H_EBCL_INLINE_SETS #define _H_EBCL_INLINE_SETS // XXX #include #include "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; bool add( Type const& item ) noexcept; bool add( Type&& item ) noexcept; bool remove( Type const& item ) 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_ 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; } #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; bool add( Type const& item ) noexcept; bool add( Type&& item ) noexcept; bool remove( Type const& item ) 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_ 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; } #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 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; } } /*----------------------------------------------------------------------------*/ // 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 ); break; case INIT_MOVE: *(T_Impl_**)output = ::new T_Impl_( std::move( *(T_Impl_**)wArg ) ); 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 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; } } /*= 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_ ); } /*----------------------------------------------------------------------------*/ 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_ ); } /*----------------------------------------------------------------------------*/ 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 > 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; } } #endif // _H_EBCL_INLINE_SETS