197 lines
5.6 KiB
C++
197 lines
5.6 KiB
C++
|
/******************************************************************************/
|
||
|
/* SETS ***********************************************************************/
|
||
|
/******************************************************************************/
|
||
|
|
||
|
#ifndef _H_EBCL_SETS
|
||
|
#define _H_EBCL_SETS
|
||
|
#include <ebcl/Arrays.hh>
|
||
|
#include <ebcl/HashIndex.hh>
|
||
|
namespace ebcl {
|
||
|
|
||
|
|
||
|
/*= SETS =====================================================================*/
|
||
|
|
||
|
// 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 fully dynamic array to be used)
|
||
|
M_DEFINE_TEMPLATE_TAG( ArrayBacked ,
|
||
|
uint32_t InPlace ,
|
||
|
uint32_t Growth = 0
|
||
|
);
|
||
|
|
||
|
// IndexBacked implementation tag - the implementation will use a
|
||
|
// T_HashIndex and an array. InitialSize and HashSize affect the index,
|
||
|
// Growth affects both the index and the array.
|
||
|
M_DEFINE_TEMPLATE_TAG( IndexBacked ,
|
||
|
uint32_t InitialSize = T_HashIndex::DEFAULT_SIZE ,
|
||
|
uint32_t HashSize = T_HashIndex::DEFAULT_SIZE ,
|
||
|
uint32_t Growth = T_HashIndex::DEFAULT_GROWTH );
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
|
||
|
// Templated horrors used by the main T_Set class.
|
||
|
struct T_SetHelper
|
||
|
{
|
||
|
// Default implementation to use; also determines the in-place
|
||
|
// storage size
|
||
|
using DefaultImplementation = IndexBacked< >;
|
||
|
|
||
|
// Default implementation class
|
||
|
template< typename Type
|
||
|
> using DefaultType = T_SetImplementation<
|
||
|
Type , DefaultImplementation >;
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
// In-place storage size
|
||
|
template< typename Type
|
||
|
> static constexpr auto DefaultSize{
|
||
|
sizeof( DefaultType< Type > ) };
|
||
|
// In-place storage alignment
|
||
|
template< typename Type
|
||
|
> static constexpr auto DefaultAlign{
|
||
|
alignof( DefaultType< Type > ) };
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
// Implementation handler operations
|
||
|
enum E_Operation
|
||
|
{
|
||
|
// New instance; output = storage
|
||
|
INIT ,
|
||
|
// Copy instance; output = storage, rArg = source
|
||
|
INIT_COPY ,
|
||
|
// Move instance; output = storage, wArg = source
|
||
|
INIT_MOVE ,
|
||
|
// Destroy instance; wArg = storage
|
||
|
DESTROY ,
|
||
|
|
||
|
// Get size; rArg = storage, output = result
|
||
|
SIZE ,
|
||
|
// Get index of element; wArg = storage, rArg = element, output = result
|
||
|
INDEX_OF ,
|
||
|
// Access an element; wArg = index , rArg = storage, output = pointer
|
||
|
ACCESS ,
|
||
|
|
||
|
// Add copy of element; wArg = storage, rArg = element, output = result
|
||
|
ADD_COPY ,
|
||
|
// Move & add element; wArg = storage, rArg = element, output = result
|
||
|
ADD_MOVE ,
|
||
|
// Delete element; wArg = storage, rArg = element, output = result
|
||
|
REMOVE ,
|
||
|
|
||
|
// Free memory; wArg = storage
|
||
|
FREE ,
|
||
|
// Clear contents; wArg = storage
|
||
|
CLEAR ,
|
||
|
};
|
||
|
|
||
|
// Handler function type
|
||
|
using F_Handler = std::function<
|
||
|
void( E_Operation , void* , void const* , void* ) >;
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
// Handler for in-place implementations
|
||
|
template< typename Type , typename Impl
|
||
|
> struct T_InPlaceHandler
|
||
|
{
|
||
|
static void shdl( E_Operation operation ,
|
||
|
void* wArg ,
|
||
|
void const* rArg ,
|
||
|
void* output );
|
||
|
};
|
||
|
|
||
|
// Handler for heap-allocated implementations
|
||
|
template< typename Type , typename Impl
|
||
|
> struct T_HeapHandler
|
||
|
{
|
||
|
static void shdl( E_Operation operation ,
|
||
|
void* wArg ,
|
||
|
void const* rArg ,
|
||
|
void* output );
|
||
|
};
|
||
|
|
||
|
// Use the in-place handler if the implementation data can fit into the
|
||
|
// in-place storage; otherwise use the heap-allocated handler.
|
||
|
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 >
|
||
|
>;
|
||
|
};
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
|
||
|
// A set of elements of type Type
|
||
|
template< typename Type
|
||
|
> class T_Set
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
// Storage area for the implementation's data
|
||
|
std::aligned_storage_t<
|
||
|
T_SetHelper::DefaultSize< Type > ,
|
||
|
T_SetHelper::DefaultAlign< Type >
|
||
|
> storage_;
|
||
|
|
||
|
// Handler
|
||
|
T_SetHelper::F_Handler handler_;
|
||
|
|
||
|
public:
|
||
|
// Default constructor, using the default implementation
|
||
|
T_Set( ) noexcept;
|
||
|
// Create a set with a specific implementation
|
||
|
template< typename Tag
|
||
|
> T_Set( UseTag< Tag > impl ) noexcept;
|
||
|
|
||
|
// Copy constructor / assignment
|
||
|
T_Set( T_Set const& other ) noexcept;
|
||
|
T_Set& operator =( T_Set const& other ) noexcept;
|
||
|
|
||
|
// Move constructor / assignment
|
||
|
T_Set( T_Set&& other ) noexcept;
|
||
|
T_Set& operator =( T_Set&& other ) noexcept;
|
||
|
|
||
|
~T_Set( );
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
// Returns amount of elements
|
||
|
uint32_t size( ) const noexcept;
|
||
|
// Checks if item is in the set
|
||
|
bool contains( Type const& item ) const noexcept;
|
||
|
// Returns underlying index of item, or -1 if not in the set
|
||
|
int32_t indexOf( Type const& item ) const noexcept;
|
||
|
|
||
|
// Access an element using its underlying index
|
||
|
Type const& operator[]( uint32_t index ) const noexcept;
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
// Add copy of item, returns true if added
|
||
|
bool add( Type const& item ) noexcept;
|
||
|
// Add moved item, returns true if added
|
||
|
bool add( Type&& item ) noexcept;
|
||
|
// Remove item, returns true if removed
|
||
|
bool remove( Type const& item ) noexcept;
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
void clear( ) noexcept;
|
||
|
void free( ) noexcept;
|
||
|
};
|
||
|
|
||
|
|
||
|
}
|
||
|
#endif // _H_EBCL_SETS
|
||
|
#include <ebcl/inline/Sets.hh>
|