2017-11-01 20:14:23 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
/* HASH INDEX *****************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2017-11-01 21:44:54 +01:00
|
|
|
#ifndef _H_EBCL_HASHINDEX
|
|
|
|
#define _H_EBCL_HASHINDEX
|
|
|
|
#include <ebcl/Externals.hh>
|
|
|
|
#include <ebcl/Pointers.hh>
|
|
|
|
namespace ebcl {
|
2017-11-01 20:14:23 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is based on http://glampert.com/2016/05-04/dissecting-idhashindex,
|
|
|
|
* which explains how the hash tables in idTech4 work. Not looking at the code
|
|
|
|
* to avoid GPL-related issues, so my implementation will probably suck.
|
|
|
|
*
|
|
|
|
* Unlike the original thing, this version considers that:
|
|
|
|
* - all additions are made at the end of the array (and therefore at the
|
|
|
|
* end of the index),
|
|
|
|
* - erasing is done by swapping the element being erased and the last
|
|
|
|
* element of the index.
|
|
|
|
*
|
|
|
|
* It also keeps track of the hash key for a given index in order to make
|
|
|
|
* erasing easier.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class T_HashIndex
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static constexpr uint32_t INVALID_INDEX = 0xffffffff;
|
|
|
|
static constexpr uint32_t DEFAULT_SIZE = 1024;
|
|
|
|
static constexpr uint32_t DEFAULT_GROWTH = 1024;
|
|
|
|
|
|
|
|
private:
|
|
|
|
static uint32_t invalidIndex_;
|
|
|
|
|
|
|
|
uint32_t hashSize_;
|
|
|
|
uint32_t* hash_;
|
|
|
|
|
|
|
|
uint32_t indexSize_;
|
|
|
|
uint32_t indexGrowth_;
|
|
|
|
uint32_t indexUsed_;
|
|
|
|
uint32_t* index_;
|
|
|
|
uint32_t* indexReverse_;
|
|
|
|
|
|
|
|
uint32_t hashMask_;
|
|
|
|
uint32_t lookupMask_;
|
|
|
|
|
|
|
|
void enlargeIndex( uint32_t needed );
|
|
|
|
void allocateIfNecessary( );
|
|
|
|
|
|
|
|
public:
|
|
|
|
T_HashIndex( ) noexcept;
|
|
|
|
T_HashIndex( uint32_t hashSize , uint32_t indexSize , uint32_t growth = DEFAULT_GROWTH ) noexcept;
|
|
|
|
|
|
|
|
T_HashIndex( T_HashIndex const& source );
|
|
|
|
T_HashIndex( T_HashIndex&& source ) noexcept;
|
|
|
|
|
|
|
|
~T_HashIndex( );
|
|
|
|
|
|
|
|
T_HashIndex& operator =( T_HashIndex const& other );
|
|
|
|
T_HashIndex& operator =( T_HashIndex&& other ) noexcept;
|
|
|
|
|
|
|
|
friend void swap( T_HashIndex& lhs , T_HashIndex& rhs ) noexcept;
|
|
|
|
|
|
|
|
void free( );
|
|
|
|
void clear( );
|
|
|
|
|
|
|
|
void add( uint32_t key );
|
|
|
|
void remove( uint32_t index );
|
|
|
|
|
|
|
|
uint32_t first( uint32_t key ) const;
|
|
|
|
uint32_t next( uint32_t index ) const;
|
|
|
|
};
|
|
|
|
M_CLASS_POINTERS( HashIndex );
|
|
|
|
void swap( T_HashIndex& lhs , T_HashIndex& rhs ) noexcept;
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace
|
2017-11-01 21:44:54 +01:00
|
|
|
#include <ebcl/inline/HashIndex.hh>
|
|
|
|
#endif // _H_EBCL_HASHINDEX
|