corelib/include/ebcl/HashTables.hh

208 lines
5.7 KiB
C++

/******************************************************************************/
/* HASH TABLES ****************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_HASHTABLES
#define _H_LW_LIB_HASHTABLES
#include <ebcl/Arrays.hh>
#include <ebcl/HashIndex.hh>
namespace ebcl {
// F_KeyMatch< K > - Equality check function for keys
template< typename K >
using F_KeyMatch = std::function< bool( K const& , K const& ) >;
// T_DefaultKeyMatch< K > - Default equality check for keys
template< typename K >
struct T_DefaultKeyMatch
{
static bool keysMatch( K const& , K const& );
};
/*= KEY / VALUE TABLE ========================================================*/
/*
* T_KeyValueTable - Hash table with separate key and value storage.
* This class is meant to be used when data with unrelated types need to be
* associated with each other, e.g. string -> int mapping.
*/
template<
typename KeyType ,
typename ValueType
>
class T_KeyValueTable
{
public:
typedef F_KeyMatch< KeyType > F_Match;
private:
typedef T_KeyValueTable< KeyType , ValueType > MyType_;
F_Match match_;
T_HashIndex index_;
T_Array< KeyType > keys_;
T_Array< ValueType > values_;
public:
M_TEMPLATE_POINTERS( MyType_ );
// ---------------------------------------------------------------------
T_KeyValueTable( uint32_t initialSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t hashSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t growth = T_HashIndex::DEFAULT_GROWTH ,
F_Match match = T_DefaultKeyMatch< KeyType >::keysMatch );
template< typename K , typename T >
friend void swap( T_KeyValueTable< K , T >& lhs , T_KeyValueTable< K , T >& rhs );
// ---------------------------------------------------------------------
// Add a new value (fails if key already present)
template<
typename A , typename B ,
T_EnableIfTypesMatch< KeyType , A > = true ,
T_EnableIfTypesMatch< ValueType , B > = true
> bool add( A&& k , B&& v );
// Update an existing value (fails if key not present)
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> bool update( KeyType const& k , A&& v );
// Add or modify a key/value pair
template<
typename A , typename B ,
T_EnableIfTypesMatch< KeyType , A > = true ,
T_EnableIfTypesMatch< ValueType , B > = true
> void set( A&& k , B&& v );
// Remove a key/value pair
bool remove( KeyType const& k );
void clear( );
void free( );
// ---------------------------------------------------------------------
uint32_t size( ) const noexcept;
T_Array< KeyType > const& keys( ) const noexcept;
T_Array< ValueType > const& values( ) const noexcept;
T_Array< ValueType >& values( ) noexcept;
uint32_t indexOf( KeyType const& k ) const;
bool contains( KeyType const& k ) const;
ValueType const * get( KeyType const& k ) const;
ValueType * get( KeyType const& k );
template< typename... ArgTypes >
ValueType& getOrCreate( KeyType const& k , ArgTypes&&... args );
ValueType& operator[] ( uint32_t index );
ValueType const& operator[] ( uint32_t index ) const;
// ---------------------------------------------------------------------
private:
uint32_t find( KeyType const& k , uint32_t hash ) const;
};
template< typename K , typename T >
void swap( T_KeyValueTable< K , T >& lhs , T_KeyValueTable< K , T >& rhs );
/*= OBJECT TABLE =============================================================*/
/*
* This class is meant to be used to store objects that somehow contain their
* own keys. Of course, modifying one of these objects' key after it's been
* inserted will cause major SNAFU's.
*/
template<
typename KeyType ,
typename ValueType
>
class T_ObjectTable
{
public:
typedef F_KeyMatch< KeyType > F_Match;
typedef std::function< KeyType( ValueType const& ) > F_GetKey;
private:
typedef T_ObjectTable< KeyType , ValueType > MyType_;
F_Match match_;
F_GetKey keyGetter_;
T_HashIndex index_;
T_Array< ValueType > values_;
public:
M_TEMPLATE_POINTERS( MyType_ );
T_ObjectTable( ) = delete;
// ---------------------------------------------------------------------
T_ObjectTable( F_GetKey keyGetter , uint32_t initialSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t hashSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t growth = T_HashIndex::DEFAULT_GROWTH ,
F_Match match = T_DefaultKeyMatch< KeyType >::keysMatch );
template< typename K , typename T >
friend void swap( T_ObjectTable< K , T >& lhs , T_ObjectTable< K , T >& rhs );
// ---------------------------------------------------------------------
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> bool add( A&& v );
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> bool update( A&& v );
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> void set( A&& v );
bool remove( KeyType const& k );
void clear( );
void free( );
// ---------------------------------------------------------------------
uint32_t size( ) const;
uint32_t indexOf( KeyType const& k ) const;
bool contains( KeyType const& k ) const;
T_Array< KeyType > keys( ) const noexcept;
T_Array< ValueType > const& values( ) const noexcept;
T_Array< ValueType >& values( ) noexcept;
ValueType const * get( KeyType const& k ) const;
ValueType * get( KeyType const& k );
ValueType& operator[] ( uint32_t index );
ValueType const& operator[] ( uint32_t index ) const;
// ---------------------------------------------------------------------
private:
uint32_t find( KeyType const& k , uint32_t hash ) const;
};
template< typename K , typename T >
void swap( T_ObjectTable< K , T >& lhs , T_ObjectTable< K , T >& rhs );
}
#endif // _H_LW_LIB_HASHTABLES
#include <ebcl/inline/HashTables.hh>