corelib/include/ebcl/inline/HashTables.hh

439 lines
11 KiB
C++
Raw Normal View History

/******************************************************************************/
/* HASH TABLES - INLINE CODE **************************************************/
/******************************************************************************/
#ifndef _H_EBCL_INLINE_HASHTABLES
#define _H_EBCL_INLINE_HASHTABLES
#include <ebcl/HashTables.hh>
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 ];
}
2017-11-05 13:00:35 +01:00
template< typename K , typename V >
template< typename... ArgTypes >
V& T_KeyValueTable< K , V >::getOrCreate(
K const& k ,
ArgTypes&&... args )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx != T_HashIndex::INVALID_INDEX ) {
return values_[ idx ];
}
index_.add( hash );
keys_.add( k );
return values_.addNew( std::forward< ArgTypes >( args ) ... );
}
/*----------------------------------------------------------------------------*/
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