corelib/include/ebcl/HashIndex.hh

81 lines
2.2 KiB
C++

/******************************************************************************/
/* HASH INDEX *****************************************************************/
/******************************************************************************/
#ifndef _H_EBCL_HASHINDEX
#define _H_EBCL_HASHINDEX
#include <ebcl/Externals.hh>
#include <ebcl/Pointers.hh>
namespace ebcl {
/*
* 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
#include <ebcl/inline/HashIndex.hh>
#endif // _H_EBCL_HASHINDEX