/*
....[@@@..[@@@..............[@.................. 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@falcon.mercer.peachnet.edu
MUD++ development mailing list mudpp-list@spice.com
------------------------------------------------------------------------------
indexable.h
*/
#ifndef INDEXABLE_H
#define INDEXABLE_H
#include "string.h"
#include "index.h"
#include "llist.h"
template< class T >
class Indexable
{
private:
Index index;
T * obj;
public:
Indexable()
: obj(0)
{
}
Indexable( const Index & x, T * y )
: index(x), obj(y)
{
}
virtual ~Indexable()
{
if( obj )
delete obj;
}
T * peek() const { return obj; }
T * getObj() const { return obj; }
void setObj( T * pObj )
{
if( pObj != obj )
{
if( obj )
delete obj;
obj = pObj;
}
}
const Index & getIndex() const { return index; }
void setIndex( const Index & x ) { index = x; }
const String getScope() const { return index.getScope(); }
const String getKey() const { return index.getKey(); }
void setScope( const String & x ) { index.setScope( x ); }
void setKey( const String & x ) { index.setKey( x ); }
};
#define HASH_KEY 64
// An array of LList objects.
template< class T >
class IndexList
{
private:
// Don't remove spaces in template defs. C++ will barf if you
// write LList<Indexable< T >>, and according to the spec its wrong.
LList< Indexable< T > > table[ HASH_KEY ];
int ihash;
protected:
public:
IndexList()
: ihash(0)
{
}
void addIndex( const Index &, T * );
int getHashKey( const String & );
int getHashKey( const char * );
T *lookup( const Index & );
T *lookup( const String & );
T *lookup( const char * );
void removeIndex( const Index & );
void removeIndex( const String & );
void removeIndex( const char * );
// List like iteration interface
void reset() const;
void clr(); // Destroys all nodes within index
void setScope( const String & );
const IndexList & next() const;
T * peek() const;
const Index & getIndex();
};
template< class T >
int IndexList< T >::getHashKey( const String & str )
{
int key = (int)str[0];
if( str[0] )
key += (int)str[1]; // be it null or not
return key % HASH_KEY;
}
template< class T >
int IndexList< T >::getHashKey( const char * str )
{
int key = (int)str[0];
if( str[0] )
key += (int)str[1]; // be it null or not
return key % HASH_KEY;
}
template< class T >
void IndexList< T >::reset() const
{
for( int i = 0; i < HASH_KEY; i++ )
{
table[ i ].reset();
if( table[ i ].peek() )
{
// Override const member
const_cast< IndexList< T > * >(this)->ihash = i;
return;
}
}
}
template< class T >
void IndexList< T >::setScope( const String & x )
{
ihash = 0;
Indexable< T > *ptr;
for( ihash = 0; ihash < HASH_KEY; ihash++ )
{
table[ ihash ].reset();
while( ( ptr = table[ ihash ].peek() ) )
{
table[ ihash ].next();
ptr->setScope( x );
}
}
}
template< class T >
const IndexList< T > & IndexList< T >::next() const
{
int i;
table[ ihash ].next();
if( !table[ ihash ].peek() )
{
if( ihash < HASH_KEY - 1 )
{
for( i = ihash + 1; i < HASH_KEY; i++ )
{
table[ i ].reset();
if( table[ i ].peek() )
{
const_cast< IndexList * >(this)->ihash = i;
return *this;
}
}
}
}
return *this;
}
template < class T >
T * IndexList< T >::peek() const
{
Indexable< T > *x = table[ ihash ].peek();
if( x )
return x->peek();
return 0;
}
template < class T >
const Index & IndexList< T >::getIndex()
{
static Index empty;
Indexable< T > *x = table[ ihash ].peek();
if( x )
return x->getIndex();
return empty;
}
template < class T >
void IndexList< T >::clr()
{
Indexable< T > *ptr;
for( ihash = 0; ihash < HASH_KEY; ihash++ )
{
table[ ihash ].reset();
while( ( ptr = table[ ihash ].remove() ) )
delete ptr;
}
}
// For now, the scope portion of the index isn't used
// inside the IndexList object since all objects in that
// list are of same scope. This can me changed easily.
template < class T >
T * IndexList< T >::lookup( const Index & x )
{
return lookup( x.getKey() );
}
template < class T >
T * IndexList< T >::lookup( const String & x )
{
return lookup( x.chars() );
}
// Dont want to change the internal state of container so create
// tlist to do iterating.
template < class T >
T * IndexList< T >::lookup( const char * x )
{
Indexable< T > *ptr;
LList< Indexable< T > > tlist = table[ getHashKey( x ) ];
tlist.reset();
while( ( ptr = tlist.peek() ) )
{
tlist.next();
if( ptr->getKey() == x )
{
return ptr->getObj();
}
}
return 0;
}
template < class T >
void IndexList< T >::addIndex( const Index & x, T * y )
{
Indexable< T > *ptr = new Indexable< T >( x, y );
int i = getHashKey( ptr->getKey() );
table[ i ].addTop( ptr );
}
template < class T >
void IndexList< T >::removeIndex( const Index & x )
{
removeIndex( x.getKey().chars() );
}
template < class T >
void IndexList< T >::removeIndex( const String & x )
{
removeIndex( x.chars() );
}
template < class T >
void IndexList< T >::removeIndex( const char * )
{
}
#endif