2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #ifndef __HASHTABLE_H__
30 #define __HASHTABLE_H__
33 ===============================================================================
35 General hash table. Slower than idHashIndex but it can also be used for
36 linked lists and other data structures than just indexes or arrays.
38 ===============================================================================
41 template< class Type >
44 idHashTable( int newtablesize = 256 );
45 idHashTable( const idHashTable<Type> &map );
48 // returns total size of allocated memory
49 size_t Allocated( void ) const;
50 // returns total size of allocated memory including size of hash table type
51 size_t Size( void ) const;
53 void Set( const char *key, Type &value );
54 bool Get( const char *key, Type **value = NULL ) const;
55 bool Remove( const char *key );
58 void DeleteContents( void );
60 // the entire contents can be itterated over, but note that the
61 // exact index for a given element may change when new elements are added
62 int Num( void ) const;
63 Type * GetIndex( int index ) const;
65 int GetSpread( void ) const;
73 hashnode_s( const idStr &k, Type v, hashnode_s *n ) : key( k ), value( v ), next( n ) {};
74 hashnode_s( const char *k, Type v, hashnode_s *n ) : key( k ), value( v ), next( n ) {};
83 int GetHash( const char *key ) const;
88 idHashTable<Type>::idHashTable
91 template< class Type >
92 ID_INLINE idHashTable<Type>::idHashTable( int newtablesize ) {
94 assert( idMath::IsPowerOfTwo( newtablesize ) );
96 tablesize = newtablesize;
97 assert( tablesize > 0 );
99 heads = new hashnode_s *[ tablesize ];
100 memset( heads, 0, sizeof( *heads ) * tablesize );
104 tablesizemask = tablesize - 1;
109 idHashTable<Type>::idHashTable
112 template< class Type >
113 ID_INLINE idHashTable<Type>::idHashTable( const idHashTable<Type> &map ) {
118 assert( map.tablesize > 0 );
120 tablesize = map.tablesize;
121 heads = new hashnode_s *[ tablesize ];
122 numentries = map.numentries;
123 tablesizemask = map.tablesizemask;
125 for( i = 0; i < tablesize; i++ ) {
126 if ( !map.heads[ i ] ) {
132 for( node = map.heads[ i ]; node != NULL; node = node->next ) {
133 *prev = new hashnode_s( node->key, node->value, NULL );
134 prev = &( *prev )->next;
141 idHashTable<Type>::~idHashTable<Type>
144 template< class Type >
145 ID_INLINE idHashTable<Type>::~idHashTable( void ) {
152 idHashTable<Type>::Allocated
155 template< class Type >
156 ID_INLINE size_t idHashTable<Type>::Allocated( void ) const {
157 return sizeof( heads ) * tablesize + sizeof( *heads ) * numentries;
162 idHashTable<Type>::Size
165 template< class Type >
166 ID_INLINE size_t idHashTable<Type>::Size( void ) const {
167 return sizeof( idHashTable<Type> ) + sizeof( heads ) * tablesize + sizeof( *heads ) * numentries;
172 idHashTable<Type>::GetHash
175 template< class Type >
176 ID_INLINE int idHashTable<Type>::GetHash( const char *key ) const {
177 return ( idStr::Hash( key ) & tablesizemask );
182 idHashTable<Type>::Set
185 template< class Type >
186 ID_INLINE void idHashTable<Type>::Set( const char *key, Type &value ) {
187 hashnode_s *node, **nextPtr;
190 hash = GetHash( key );
191 for( nextPtr = &(heads[hash]), node = *nextPtr; node != NULL; nextPtr = &(node->next), node = *nextPtr ) {
192 s = node->key.Cmp( key );
204 *nextPtr = new hashnode_s( key, value, heads[ hash ] );
205 (*nextPtr)->next = node;
210 idHashTable<Type>::Get
213 template< class Type >
214 ID_INLINE bool idHashTable<Type>::Get( const char *key, Type **value ) const {
218 hash = GetHash( key );
219 for( node = heads[ hash ]; node != NULL; node = node->next ) {
220 s = node->key.Cmp( key );
223 *value = &node->value;
241 idHashTable<Type>::GetIndex
243 the entire contents can be itterated over, but note that the
244 exact index for a given element may change when new elements are added
247 template< class Type >
248 ID_INLINE Type *idHashTable<Type>::GetIndex( int index ) const {
253 if ( ( index < 0 ) || ( index > numentries ) ) {
259 for( i = 0; i < tablesize; i++ ) {
260 for( node = heads[ i ]; node != NULL; node = node->next ) {
261 if ( count == index ) {
273 idHashTable<Type>::Remove
276 template< class Type >
277 ID_INLINE bool idHashTable<Type>::Remove( const char *key ) {
283 hash = GetHash( key );
284 head = &heads[ hash ];
286 for( prev = NULL, node = *head; node != NULL; prev = node, node = node->next ) {
287 if ( node->key == key ) {
289 prev->next = node->next;
306 idHashTable<Type>::Clear
309 template< class Type >
310 ID_INLINE void idHashTable<Type>::Clear( void ) {
315 for( i = 0; i < tablesize; i++ ) {
317 while( next != NULL ) {
331 idHashTable<Type>::DeleteContents
334 template< class Type >
335 ID_INLINE void idHashTable<Type>::DeleteContents( void ) {
340 for( i = 0; i < tablesize; i++ ) {
342 while( next != NULL ) {
357 idHashTable<Type>::Num
360 template< class Type >
361 ID_INLINE int idHashTable<Type>::Num( void ) const {
365 #if defined(ID_TYPEINFO)
369 #if !defined(__GNUC__) || __GNUC__ < 4
372 idHashTable<Type>::GetSpread
375 template< class Type >
376 int idHashTable<Type>::GetSpread( void ) const {
377 int i, average, error, e;
380 // if no items in hash
384 average = numentries / tablesize;
386 for ( i = 0; i < tablesize; i++ ) {
388 for( node = heads[ i ]; node != NULL; node = node->next ) {
391 e = abs( numItems - average );
396 return 100 - (error * 100 / numentries);
400 #if defined(ID_TYPEINFO)
404 #endif /* !__HASHTABLE_H__ */