/*
....[@@@..[@@@..............[@.................. 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() );
}