/* ....[@@@..[@@@..............[@.................. 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