/******************************************************************************/ /* HASH TABLES ****************************************************************/ /******************************************************************************/ #ifndef _H_LW_LIB_HASHTABLES #define _H_LW_LIB_HASHTABLES #include #include 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; T_Array< KeyType > const& keys( ) const; T_Array< ValueType > const& values( ) const; 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; T_Array< ValueType > const& values( ) const; 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