/******************************************************************************/ /* HASH TABLES - INLINE CODE **************************************************/ /******************************************************************************/ #ifndef _H_EBCL_INLINE_HASHTABLES #define _H_EBCL_INLINE_HASHTABLES #include namespace ebcl { /*= T_DefaultKeyMatch ========================================================*/ template< typename K > inline bool T_DefaultKeyMatch< K >::keysMatch( K const& a , K const& b ) { return a == b; } /*= T_KeyValueTable ==========================================================*/ template< typename K , typename V > inline T_KeyValueTable< K , V >::T_KeyValueTable( uint32_t initialSize , uint32_t hashSize , uint32_t growth , F_KeyMatch< K > match ) : match_( match ) , index_( hashSize , initialSize , growth ) , keys_( growth ) , values_( growth ) { } /*----------------------------------------------------------------------------*/ template< typename K , typename T > void swap( T_KeyValueTable< K , T >& lhs , T_KeyValueTable< K , T >& rhs ) { using std::swap; swap( lhs.match_ , rhs.match_ ); swap( lhs.index_ , rhs.index_ ); swap( lhs.keys_ , rhs.keys_ ); swap( lhs.values_ , rhs.values_ ); } /*----------------------------------------------------------------------------*/ template< typename K , typename V > template< typename A , typename B , T_EnableIfTypesMatch< K , A > , T_EnableIfTypesMatch< V , B > > inline bool T_KeyValueTable< K , V >::add( A&& k , B&& v ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx != T_HashIndex::INVALID_INDEX ) { return false; } keys_.add( std::forward< A >( k ) ); values_.add( std::forward< B >( v ) ); index_.add( hash ); return true; } template< typename K , typename V > template< typename B , T_EnableIfTypesMatch< V , B > > inline bool T_KeyValueTable< K , V >::update( K const& k , B&& v ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return false; } values_[ idx ] = std::forward< B >( v ); return true; } template< typename K , typename V > template< typename A , typename B , T_EnableIfTypesMatch< K , A > , T_EnableIfTypesMatch< V , B > > inline void T_KeyValueTable< K , V >::set( A&& k , B&& v ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { keys_.add( std::forward< A >( k ) ); values_.add( std::forward< B >( v ) ); index_.add( hash ); } else { values_[ idx ] = std::forward< B >( v ); } } template< typename K , typename V > inline bool T_KeyValueTable< K , V >::remove( K const& k ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return false; } keys_.removeSwap( idx ); values_.removeSwap( idx ); index_.remove( idx ); return true; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline void T_KeyValueTable< K , V >::clear( ) { values_.clear( ); keys_.clear( ); index_.clear( ); } template< typename K , typename V > inline void T_KeyValueTable< K , V >::free( ) { values_.free( ); keys_.free( ); index_.free( ); } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline uint32_t T_KeyValueTable< K , V >::size( ) const { return keys_.size( ); } template< typename K , typename V > T_Array< K > const& T_KeyValueTable< K , V >::keys( ) const { return keys_; } template< typename K , typename V > T_Array< V > const& T_KeyValueTable< K , V >::values( ) const { return values_; } template< typename K , typename V > inline uint32_t T_KeyValueTable< K , V >::indexOf( K const& k ) const { return find( k , ComputeHash( k ) ); } template< typename K , typename V > inline bool T_KeyValueTable< K , V >::contains( K const& k ) const { const uint32_t hash = ComputeHash( k ); return find( k , hash ) != T_HashIndex::INVALID_INDEX; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline V const* T_KeyValueTable< K , V >::get( K const& k ) const { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return nullptr; } return &values_[ idx ]; } template< typename K , typename V > inline V* T_KeyValueTable< K , V >::get( K const& k ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return nullptr; } return &values_[ idx ]; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline V& T_KeyValueTable< K , V >::operator[] ( uint32_t index ) { return values_[ index ]; } template< typename K , typename V > inline V const& T_KeyValueTable< K , V >::operator[] ( uint32_t index ) const { return values_[ index ]; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline uint32_t T_KeyValueTable< K , V >::find( K const& k , uint32_t hash ) const { uint32_t idx = index_.first( hash ); while ( idx != T_HashIndex::INVALID_INDEX ) { if ( match_( keys_[ idx ] , k ) ) { break; } idx = index_.next( idx ); } return idx; } /*= T_ObjectTable ============================================================*/ template< typename K , typename V > inline T_ObjectTable< K , V >::T_ObjectTable( T_ObjectTable< K , V >::F_GetKey keyGetter , uint32_t initialSize , uint32_t hashSize , uint32_t growth , T_ObjectTable< K , V >::F_Match match ) : match_( match ) , keyGetter_( keyGetter ) , index_( hashSize , initialSize , growth ) , values_( growth ) { } /*----------------------------------------------------------------------------*/ template< typename K , typename T > void swap( T_ObjectTable< K , T >& lhs , T_ObjectTable< K , T >& rhs ) { using std::swap; swap( lhs.keyGetter_ , rhs.keyGetter_ ); swap( lhs.match_ , rhs.match_ ); swap( lhs.index_ , rhs.index_ ); swap( lhs.values_ , rhs.values_ ); } /*----------------------------------------------------------------------------*/ template< typename K , typename V > template< typename A , T_EnableIfTypesMatch< V , A > > inline bool T_ObjectTable< K , V >::add( A&& v ) { K k = keyGetter_( v ); const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx != T_HashIndex::INVALID_INDEX ) { return false; } values_.add( std::forward< A >( v ) ); index_.add( hash ); return true; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > template< typename A , T_EnableIfTypesMatch< V , A > > inline bool T_ObjectTable< K , V >::update( A&& v ) { K k = keyGetter_( v ); const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return false; } values_[ idx ] = std::forward< A >( v ); return true; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > template< typename A , T_EnableIfTypesMatch< V , A > > inline void T_ObjectTable< K , V >::set( A&& v ) { K k = keyGetter_( v ); const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { values_.add( std::forward< A >( v ) ); index_.add( hash ); } else { values_[ idx ] = std::forward< A >( v ); } } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline bool T_ObjectTable< K , V >::remove( K const& k ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return false; } values_.removeSwap( idx ); index_.remove( idx ); return true; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline void T_ObjectTable< K , V >::clear( ) { values_.clear( ); index_.clear( ); } template< typename K , typename V > inline void T_ObjectTable< K , V >::free( ) { values_.free( ); index_.free( ); } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline uint32_t T_ObjectTable< K , V >::size( ) const { return values_.size( ); } template< typename K , typename V > inline uint32_t T_ObjectTable< K , V >::indexOf( K const& k ) const { return find( k , ComputeHash( k ) ); } template< typename K , typename V > inline bool T_ObjectTable< K , V >::contains( K const& k ) const { const uint32_t hash = ComputeHash( k ); return find( k , hash ) != T_HashIndex::INVALID_INDEX; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline T_Array< K > T_ObjectTable< K , V >::keys( ) const { const auto sz( size( ) ); T_Array< K > k( sz ? sz : 1 ); for ( uint32_t i = 0 ; i < sz ; i ++ ) { k.add( keyGetter_( values_[ i ] ) ); } return k; } template< typename K , typename V > inline T_Array< V > const& T_ObjectTable< K , V >::values( ) const { return values_; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline V const* T_ObjectTable< K , V >::get( K const& k ) const { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return nullptr; } return &values_[ idx ]; } template< typename K , typename V > inline V* T_ObjectTable< K , V >::get( K const& k ) { const uint32_t hash = ComputeHash( k ); uint32_t idx = find( k , hash ); if ( idx == T_HashIndex::INVALID_INDEX ) { return nullptr; } return &values_[ idx ]; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline V& T_ObjectTable< K , V >::operator[] ( uint32_t index ) { return values_[ index ]; } template< typename K , typename V > inline V const& T_ObjectTable< K , V >::operator[] ( uint32_t index ) const { return values_[ index ]; } /*----------------------------------------------------------------------------*/ template< typename K , typename V > inline uint32_t T_ObjectTable< K , V >::find( K const& k , uint32_t hash ) const { uint32_t idx = index_.first( hash ); while ( idx != T_HashIndex::INVALID_INDEX ) { if ( match_( keyGetter_( values_[ idx ] ) , k ) ) { break; } idx = index_.next( idx ); } return idx; } } // namespace #endif // _H_EBCL_INLINE_HASHTABLES