diff --git a/Sets-inline.hh b/Sets-inline.hh new file mode 100644 index 0000000..60ca427 --- /dev/null +++ b/Sets-inline.hh @@ -0,0 +1,299 @@ +/******************************************************************************/ +/* 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 =================================*/ + +#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 =====================================*/ + +#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 ===========================================================*/ + +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*)wArg) T_Impl_( ); + 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; + } +} + + +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_**)wArg = new T_Impl_( ); + 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; + } +} + + +/*============================================================================*/ + +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 , (char*) &storage_ , nullptr , nullptr ); +} + + +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 diff --git a/Sets.hh b/Sets.hh new file mode 100644 index 0000000..cb1b62e --- /dev/null +++ b/Sets.hh @@ -0,0 +1,179 @@ +/******************************************************************************/ +/* SETS ***********************************************************************/ +/******************************************************************************/ + +#ifndef _H_EBCL_SETS +#define _H_EBCL_SETS +#include +namespace ebcl { + +// FIXME move this to utilities \/ + +// Define a structure that can be used as a tag +#define M_DEFINE_TAG( NAME ) \ + struct NAME { } +// Define a tag structure that can carry arguments +#define M_DEFINE_TEMPLATE_TAG( NAME , ARGS... ) \ + template< ARGS > \ + M_DEFINE_TAG( NAME ) + +// A structure that can be used to carry a tag structure instance +template< typename Tag > +struct UseTag +{ + const Tag tag; + + template< typename ... ArgTypes > + constexpr UseTag( ArgTypes&&... args ) noexcept + : tag( std::forward< ArgTypes >( args ) ... ) { } +}; + + +// Implementation of a set of type Type. The actual implementation is +// determined by the ImplTag type. +template< typename Type , typename ImplTag > + class T_SetImplementation; + + +// ArrayBacked implementation tag. InPlace is the amount of items to +// store in-place (0 will cause a T_Array to be used +M_DEFINE_TEMPLATE_TAG( ArrayBacked , + uint32_t InPlace , + uint32_t Growth = 0 +); +//M_DEFINE_TAG( IndexBacked ); + + +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; +}; + +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; +}; + +struct T_SetHelper +{ + using DefaultImplementation = ArrayBacked< 8 >; // FIXME should use Index by default + + template< typename Type + > using DefaultType = T_SetImplementation< + Type , DefaultImplementation >; + + template< typename Type + > static constexpr auto DefaultSize{ sizeof( DefaultType< Type > ) }; + + template< typename Type + > static constexpr auto DefaultAlign{ alignof( DefaultType< Type > ) }; + + enum E_Operation + { + INIT , + DESTROY , + + SIZE , + INDEX_OF , + + ADD_COPY , + ADD_MOVE , + REMOVE , + }; + + template< typename Type , typename Impl + > struct T_InPlaceHandler + { + static void shdl( E_Operation operation , + void* wArg , + void const* rArg , + void* output ); + }; + + template< typename Type , typename Impl + > struct T_HeapHandler + { + static void shdl( E_Operation operation , + void* wArg , + void const* rArg , + void* output ); + }; + + template< + typename Type , typename ImplTag , + typename Impl = T_SetImplementation< Type , ImplTag > + > using T_Handler = std::conditional_t< + sizeof( Impl ) <= DefaultSize< Type > , + T_InPlaceHandler< Type , ImplTag > , + T_HeapHandler< Type , ImplTag > + >; + + using F_Handler = std::function< + void( E_Operation , void* , void const* , void* ) >; +}; + +template< typename Type > +class T_Set +{ + private: + + std::aligned_storage_t< + T_SetHelper::DefaultSize< Type > , + T_SetHelper::DefaultAlign< Type > + > storage_; + const T_SetHelper::F_Handler handler_; + + public: + T_Set( ) noexcept; + + template< typename Tag + > T_Set( UseTag< Tag > impl ) noexcept; + + ~T_Set( ); + + // --------------------------------------------------------------------- + + uint32_t size( ) const noexcept; + bool contains( Type const& item ) 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; +}; + + +} +#endif // _H_EBCL_SETS +// XXX #include +#include "Sets-inline.hh" +