/*
....[@@@..[@@@..............[@.................. 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
------------------------------------------------------------------------------
llist.cc
*/
// TEMPLATE FILE
int Node::allocated_nodes = 0;
#ifdef _ARRAY_H
Array< Node *> free_nodes( 128,128 );
void * Node::operator new( size_t size )
{
if ( !free_nodes.length() )
{
int i;
Node * newtable = (Node *) new char[size<<7];
allocated_nodes += 128;
for ( i=0; i < 128; i++)
{
free_nodes.add( newtable + i);
}
}
return free_nodes.removeTop();
}
void Node::operator delete( void * ptr )
{
free_nodes.add( (Node *) ptr );
}
int Node::getFreeCount()
{
return free_nodes.length();
}
#else
int Node::getFreeCount()
{
return -1;
}
#endif // _ARRAY_H
template < class T >
void LList< T >::copy( const LList< T > & x )
{
Node * node = x.head;
if( &x != this )
{
destroyList();
while( node )
{
add( (T*)node->obj );
node = node->next;
}
}
}
template < class T >
void LList< T >::destroyList()
{
// Make sure its not a copied list that was used for iterating
// which is just going out of scope.
if( !( flags & RDONLY ) )
{
if( head )
{
for( current = head; head; head = current )
{
current = current->next;
delete head;
}
}
}
else
{
flags &= ~RDONLY; // clear read only bit
head = current = 0;
}
}
template < class T >
void LList< T >::addTop( T * obj )
{
if( !obj )
return;
else if( flags & RDONLY )
return; // need to bug this later
Node * newNode = new Node( (void*)obj );
newNode->next = head;
head = newNode;
if( ! current )
current = newNode;
}
template < class T >
void LList< T >::add( T * obj )
{
if( !obj )
return;
else if( flags & RDONLY )
return; // need to bug this later
Node * newNode = new Node( (void*)obj );
if( !head )
{
head = current = newNode;
return;
}
newNode->next = current;
if( head == current )
{
head = newNode;
current = newNode;
return;
}
Node * tlast;
for( tlast = head; tlast->next; tlast = tlast->next )
{
if( tlast->next == current )
{
tlast->next = newNode;
break;
}
}
if( !tlast->next )
tlast->next = newNode;
current = newNode;
}
// Add a node after current node, used for sequential building
// of a list mostly.
template < class T >
void LList< T >::addAfterCurrent( T * obj )
{
if( !obj )
return;
else if( flags & RDONLY )
return; // need to bug this later
Node * newNode = new Node( (void*)obj );
if( !head )
{
head = current = newNode;
return;
}
else if( !current )
current = head;
newNode->next = current->next;
current->next = newNode;
}
template < class T >
T* LList< T >::remove( T * obj )
{
if( !head )
return NULL;
else if( flags & RDONLY )
return NULL; // need to bug this later
Node * rem;
Node * tlast = 0;
T * delobj;
if( head->obj == (void*)obj )
{
if( current == head )
current = head->next;
rem = head;
head = head->next;
delobj = (T*)rem->obj;
delete rem;
return delobj;
}
for( rem = head; rem; rem = rem->next )
{
if( rem->obj == (void*)obj )
{
if( rem == current )
current = current->next;
if( tlast )
tlast->next = rem->next;
delobj = (T*)rem->obj;
delete rem;
return delobj;
}
tlast = rem;
}
return NULL;
}
template < class T >
T *LList< T >::remove()
{
if( !head )
return 0;
else if( flags & RDONLY )
return 0; // need to bug this later
Node * rem = current;
if( !rem )
return 0;
else if( rem == head )
{
head = head->next;
current = current->next;
}
else
{
for( current = head; current->next; current = current->next )
{
if( current->next == rem )
{
current->next = rem->next;
break;
}
}
}
T * obj = (T*)rem->obj;
delete rem;
return obj;
}
// Does node by node copy. This is so constructed objects
// that have list data will copy correctly. Note that the
// actual object pointers still point to same address.
template < class T >
LList< T >::LList( const LList< T > & x )
: head(0), current(0), flags(0)
{
Node * node = x.head;
while( node )
{
add( (T*)node->obj );
node = node->next;
}
}
template < class T >
void LList< T >::next() const
{
if( current )
{
//const_cast< LList< T > * >(this)->current = current->next;
((LList< T > *)this)->current = current->next;
}
}
// Do read-only copy of a list. Items can't be added or removed
// from this list. It is only for iterating, etc. and is written
// specifically for this with the least overhead.
template < class T >
const LList< T > & LList< T >::operator = ( const LList< T > & x )
{
if( &x != this )
{
destroyList();
head = x.head;
current = x.head;
flags |= RDONLY;
}
return *this;
}
template < class T >
T *LList< T >::peek() const
{
if( !current )
return 0;
return (T*)current->obj;
}
template < class T >
T *LList< T >::peekNext() const
{
if( !current || !current->next )
return 0;
return (T*)current->next->obj;
}