/* ....[@@@..[@@@..............[@.................. MUD++ is a written from ....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and ....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++. ....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing ....[@......[@..[@@@@@..[@@@@@.................. development project. All ................................................ contributions are welcome. ....Copyright(C).1995.Melvin.Smith.............. Enjoy. ------------------------------------------------------------------------------ Melvin Smith (aka Fusion) msmith@hom.net MUD++ development mailing list mudpp@van.ml.org ------------------------------------------------------------------------------ hash.cc */ // TEMPLATE FILE template< class T > void HashTable< T >::reset() const { for( int i = 0; i < HASH_KEY; i++ ) { table[ i ].reset(); if( table[ i ].peek() ) { // Override const member //const_cast< HashTable< T > * >(this)->ihash = i; ((HashTable< T > *)this)->ihash = i; return; } } } template< class T > const HashTable< T > & HashTable< T >::next() const { int i; table[ ihash ].next(); if( !table[ ihash ].peek() && ihash < HASH_KEY -1 ) { for( i = ihash + 1; i < HASH_KEY; i++ ) { table[ i ].reset(); if( table[ i ].peek() ) { //const_cast< HashTable< T > * >(this)->ihash = i; ((HashTable< T > * )this)->ihash = i; return *this; } } } return *this; } template < class T > void HashTable< T >::clr() { HashNode * ptr; for( ihash = 0; ihash < HASH_KEY; ihash++ ) { table[ ihash ].reset(); while( ( ptr = table[ ihash ].remove() ) ) { // delete (T*)ptr->getObj(); delete ptr; } } } // Dont want to change the internal state of container so create // tlist to do iterating. template < class T > T * HashTable< T >::lookup( const char * x ) { HashNode * ptr; LList< HashNode > tlist = table[ getHashKey( x ) ]; tlist.reset(); while( ( ptr = tlist.peek() ) ) { tlist.next(); if( ptr->getKey() == x ) return (T*)ptr->getObj(); } return 0; } template < class T > void HashTable< T >::remove( const char * x ) { HashNode * ptr; int ihash = getHashKey( x ); LList< HashNode > tlist = table[ ihash ]; tlist.reset(); while( ( ptr = tlist.peek() ) ) { tlist.next(); if( ptr->getKey() == x ) { table[ ihash ].remove( ptr ); return; } } } template < class T > void HashTable< T >::removeAllInstancesOf(T * what) { HashNode * ptr; for( ihash = 0; ihash < HASH_KEY; ihash++ ) { for_each( table[ ihash ], ptr ) { if ( (T*)ptr->getObj() == what ) { // Maybe just remove() will do ? table[ ihash ].remove( ptr ); delete ptr; } } } } // Need to work on the hasher, this will not hash effectively // over large table sizes. For now its good enough. template< class T > int HashTable< T >::getHashKey( const char * str ) { int key = (int)str[0]; key <<= 2; if( str[0] ) key |= (int)str[1]; // be it null or not return key % HASH_KEY; } template < class T > T * HashTable< T >::peek() const { HashNode *x = table[ ihash ].peek(); if( x ) return (T*)x->getObj(); return 0; } template < class T > T * HashTable< T >::remove() { int i; HashNode *x; x = table[ ihash ].remove(); if( !x && ihash < HASH_KEY -1 ) { for( i = ihash + 1; i < HASH_KEY; i++ ) { table[ i ].reset(); if( (x = table[ i ].remove()) ) { ((HashTable< T > * )this)->ihash = i; return (T*)x->getObj(); } } } else if ( x ) { return (T*)x->getObj(); } return 0; } template < class T > const String & HashTable< T >::getKey() const { static String empty; HashNode *x = table[ ihash ].peek(); if( x ) return x->getKey(); return empty; } template < class T > T * HashTable< T >::lookup( const String & x ) { return lookup( x.chars() ); } template < class T > void HashTable< T >::add( const String & x, T * y ) { HashNode *ptr = new HashNode( x, (void*)y ); int i = getHashKey( ptr->getKey() ); table[ i ].addTop( ptr ); } template < class T > void HashTable< T >::remove( const String & x ) { remove( x.chars() ); }