2017-11-01 20:14:23 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
/* HASH TABLES - INLINE CODE **************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2017-11-01 21:44:54 +01:00
|
|
|
#ifndef _H_EBCL_INLINE_HASHTABLES
|
|
|
|
#define _H_EBCL_INLINE_HASHTABLES
|
|
|
|
#include <ebcl/HashTables.hh>
|
|
|
|
namespace ebcl {
|
2017-11-01 20:14:23 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*= 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 >
|
2017-12-10 12:00:17 +01:00
|
|
|
inline uint32_t T_KeyValueTable< K , V >::size( ) const noexcept
|
2017-11-01 20:14:23 +01:00
|
|
|
{
|
|
|
|
return keys_.size( );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename K , typename V >
|
2017-12-10 12:00:17 +01:00
|
|
|
T_Array< K > const& T_KeyValueTable< K , V >::keys( ) const noexcept
|
2017-11-01 20:14:23 +01:00
|
|
|
{
|
|
|
|
return keys_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename K , typename V >
|
2017-12-10 12:00:17 +01:00
|
|
|
T_Array< V > const& T_KeyValueTable< K , V >::values( ) const noexcept
|
|
|
|
{
|
|
|
|
return values_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename K , typename V >
|
|
|
|
T_Array< V >& T_KeyValueTable< K , V >::values( ) noexcept
|
2017-11-01 20:14:23 +01:00
|
|
|
{
|
|
|
|
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 ) ... );
|
|
|
|
}
|
|
|
|
|
2017-11-01 20:14:23 +01:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
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 >
|
2017-12-10 12:00:17 +01:00
|
|
|
inline T_Array< K > T_ObjectTable< K , V >::keys( ) const noexcept
|
2017-11-01 20:14:23 +01:00
|
|
|
{
|
|
|
|
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 >
|
2017-12-10 12:00:17 +01:00
|
|
|
inline T_Array< V > const& T_ObjectTable< K , V >::values( ) const noexcept
|
|
|
|
{
|
|
|
|
return values_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename K , typename V >
|
|
|
|
inline T_Array< V >& T_ObjectTable< K , V >::values( ) noexcept
|
2017-11-01 20:14:23 +01:00
|
|
|
{
|
|
|
|
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
|
2017-11-01 21:44:54 +01:00
|
|
|
#endif // _H_EBCL_INLINE_HASHTABLES
|