0ad/source/dcdt/se/sr_list.h

330 lines
14 KiB
C++

# ifndef SR_LIST_H
# define SR_LIST_H
/** \file sr_list.h
* Manages a circular linked list */
# include "sr_class_manager.h"
# include "sr_list_node.h"
# include "sr_output.h"
/*! \class SrListBase sr_list.h
\brief Base class for SrList
SrListBase implements methods for managing a double linked
circular list. The user should however use the template
class SrList for an implementation that includes automatic
type casts for the user type. A manager to the user
data is required, which must be a class deriving SrListNode. */
class SrListBase
{ private :
SrListNode* _first; // first element
SrListNode* _cur; // current element
SrClassManagerBase* _man; // manager of user data, that derives SrListNode
int _elements; // the number of elements in the list
public :
/*! Initiates an empty list. The class manager must manage a user class
deriving from SrListNode. */
SrListBase ( SrClassManagerBase* m );
/*! Copy constructor. The class manager of l is shared. */
SrListBase ( const SrListBase& l );
/*! Constructor from a given node. the list takes control of the nodes
headed by n. The number of elements is set to zero, but it can be
adjusted with method elements() if required.
The class manager must be compatible with the derived type of n. */
SrListBase ( SrListNode* n, SrClassManagerBase* m );
/*! The destructor deletes all nodes from memory. */
~SrListBase ();
/*! Returns the manager of the user data */
SrClassManagerBase* class_manager() const { return _man; }
/*! Deletes all elements of the list. */
void init ();
/*! Returns true if there is no elements in the list. */
bool empty () const { return _first? false:true; }
/*! Changes the internal elements counter maintained during list manipulations.
If e<0, will count all nodes to correctly update the internal counter,
otherwise will just take the new amount e. Having a wrong value has no
consequences. */
void elements ( int e );
/*! Returns the current number of elements in the list. */
int elements () const { return _elements; }
/*! Returns the current element being pointed by the SrListBase internal pointer. */
SrListNode* cur () const { return _cur; }
/*! Sets the internal current element pointer to n. It is the user responsability
to ensure that n makes part of the list controlled by SrListBase. */
void cur ( SrListNode* n ) { _cur = n; }
/*! Returns the first element of the list. */
SrListNode* first () const { return _first; }
/*! Sets the internal first element pointer to n. Its the user responsability
to ensure that n makes part of the list controlled by SrListBase */
void first ( SrListNode* n ) { _first = n; }
/*! Returns the last element of the list. */
SrListNode* last () const { return _first? _first->prior():0; }
/*! Sets the last element of the list to be n by adjusting the internal first pointer.
It is the user responsability to ensure that n makes part of the list controlled
by SrListBase. (as the list is circular, only the first pointer is mantained). */
void last ( SrListNode* n ) { _first = n->next(); }
/*! Puts the current position cur() pointing to the first node. */
void gofirst () { _cur=_first; }
/*! Puts the current position cur() pointing to the last node. */
void golast () { if (_first) _cur=_first->prior(); }
/*! Puts the current position cur() pointing to the next node curnext();
Attention: this method cannot be called if the list is empty! */
void gonext () { _cur=_cur->next(); }
/*! Puts the current position cur() pointing to the prior node curprior();
Attention: this method cannot be called if the list is empty! */
void goprior () { _cur=_cur->prior(); }
/*! Returns the next element of the current position cur().
Attention: this method cannot be called if the list is empty! */
SrListNode* curnext () const { return _cur->next(); }
/*! Returns the prior element of the current position cur().
Attention: this method cannot be called if the list is empty! */
SrListNode* curprior () const { return _cur->prior(); }
/*! This method calls gonext(), and returns true iff the last element was not reached.
Use this to iterate over a hole list, like : \code
if ( !l.empty() )
{ l.gofirst();
do { l.cur()->do_something();
} while ( l.notlast() );
} \endcode
Attention: this method cannot be called if the list is empty! */
bool notlast () { gonext(); return _cur==_first? false:true; }
/*! This method calls goprior(), and returns true iff the first element was not reached.
Use this to iterate over a hole list in backwards, like : \code
if ( !l.empty() )
{ l.golast();
do { l.cur()->do_something();
} while ( l.notfirst() );
} \endcode
Attention: this method cannot be called if the list is empty! */
bool notfirst () { goprior(); return _cur->next()==_first? false:true; }
/*! Returns true iff the current position is pointing to the last element.
Attention: this method cannot be called if the list is empty! */
bool inlast () const { return _cur->next()==_first? true:false; }
/*! Returns true iff the current position is pointing to the first element,
or if the list is empty. */
bool infirst () const { return _cur==_first? true:false; }
/*! Extracts the first element of the list, the cur position is set to be
the next element. */
SrListNode* pop_front () { _cur=_first; return extract(); }
/*! Extracts the last element of the list, the cur position is left as the
first element. */
SrListNode* pop_back () { golast(); return extract(); }
/*! Inserts n before the first element and makes n be the first element of
the list and also the current one. */
void push_front ( SrListNode* n ) { _cur=_first; insert_prior(n); _first=_cur; }
/*! Inserts n after the last element and makes n be the last element of the list
and also the current one. */
void push_back ( SrListNode* n ) { golast(); insert_next(n); }
/*! Inserts n after the current element. The current element becomes n. */
void insert_next ( SrListNode* n );
/*! Allocates a new element, inserting it after the current one.
The current element becomes the new one, and is returned. */
SrListNode* insert_next ();
/*! Inserts n prior to the current element. The current element becomes n. */
void insert_prior ( SrListNode* n );
/*! Allocates a new element, inserting it after the current one.
The current element becomes the new one, and is returned. */
SrListNode* insert_prior ();
/*! Inserts a copy of list l after the cur position, list l stays unchanged. */
void insert_list ( const SrListBase& l ) { insert_list(l._first); }
/*! Inserts a copy of the list pointed by l after the cur position, list l stays unchanged. */
void insert_list ( const SrListNode *l );
/*! Replaces the current element by n, only swaping their pointers.
The original current element is not deleted but returned. */
SrListNode* replace ( SrListNode* n );
/*! Extract the current element and return it (without deleting it). If the list
is empty, 0 is returned. The current element becomes the next one, and the
same for the first element if it is removed. */
SrListNode* extract ();
/*! Removes the current element calling extract() and deletes it. */
void remove ();
/*! Does a selection sort. The current position stays at the first element. */
void sort ();
/*! Inserts the node in its sorted position. Return the last comparison result:
>0 if it was inserted as the last element in the list, <0 if it was inserted
in the middle of the list, and 0 if it was inserted just before a duplicated
element. */
int insort ( SrListNode* n );
/*! Linear search considering that the list is sorted.
Current position will point the found element if true is returned. */
bool search ( const SrListNode *n );
/*! Linear search that will test all elements in the list, case needed for
when the list is not sorted.
Current position will point the found element if true is returned. */
bool search_all ( const SrListNode *n );
/*! Get control of the nodes in list l, and set l to be an empty list.
The data manager of l and SrList must be of the same type. */
void take_data ( SrListBase& l );
/*! Get control of the nodes headed by n. The number of elements is set to
zero, but it can be adjusted with method elements() if required.
The data manager of SrList must be compatible with the derived n type. */
void take_data ( SrListNode* n );
/*! Returns the first element of the list, and set the list to be empty. */
SrListNode* leave_data ();
/*! Outputs the list in the format: [e1 e2 en ]. */
friend SrOutput& operator<< ( SrOutput& o, const SrListBase& l );
};
/*! \class SrList sr_list.h
\brief Manages a circular linked list of derived classes X of SrLink
SrList defines automatic type casts to the user type, which must
derive SrListNode. For documentation of the methods
see the documentation of the base class SrListBase methods. */
template <class X>
class SrList : public SrListBase
{ public :
/*! Default constructor that automatically creates a SrClassManager<X>. */
SrList () : SrListBase ( new SrClassManager<X> ) {}
/*! Constructor with a given class manager. */
SrList ( SrClassManagerBase* m ) : SrListBase ( m ) {}
/*! Copy constructor. Inititates the list as a copy of l,
duplicating all elements and sharing the class manager. */
SrList ( const SrList& l ) : SrListBase ( l ) {}
/*! Constructor from a given node. The list takes control of the nodes
headed by n. The number of elements is set to zero, but it can be
adjusted later with method elements() if required. */
SrList ( X* n ) : SrListBase ( n, new SrClassManager<X> ) {}
X* cur () const { return (X*)SrListBase::cur(); }
void cur ( X* n ) { SrListBase::cur((SrListNode*)n); }
X* first () const { return (X*)SrListBase::first(); }
void first ( X* n ) { SrListBase::first((SrListNode*)n); }
X* last () { return (X*) SrListBase::last(); }
void last ( X* n ) { SrListBase::last((SrListNode*)n); }
X* curnext () const { return (X*)SrListBase::curnext(); }
X* curprior () const { return (X*)SrListBase::curprior(); }
X* pop_front () { return (X*)SrListBase::pop_front(); }
X* pop_back () { return (X*)SrListBase::pop_back(); }
void push_front ( X* n ) { SrListBase::push_front(n); }
void push_back ( X* n ) { SrListBase::push_back(n); }
void insert_next ( X* n ) { SrListBase::insert_next(n); }
X* insert_next () { return (X*)SrListBase::insert_next(); }
void insert_prior ( X* n ) { SrListBase::insert_prior(n); }
X* insert_prior () { return (X*)SrListBase::insert_prior(); }
X* replace ( X* n ) { return (X*)SrListBase::replace(n); }
X* extract () { return (X*)SrListBase::extract(); }
void operator= ( const SrList& l ) { init(); insert_list(l); }
};
/*! Base class for iterating over lists. */
class SrListIteratorBase
{ private :
SrListNode* _cur;
SrListNode* _first;
SrListNode* _last;
char _rcode;
const SrListBase* _list;
SrListNode* _node;
public :
/*! Constructor */
SrListIteratorBase ( const SrListBase& l );
/*! Constructor */
SrListIteratorBase ( SrListNode* n );
/*! Returns the current element being pointed by the iterator */
SrListNode* get () const { return _cur; }
/*! Returns the first element being pointed by the iterator */
SrListNode* getfirst () const { return _first; }
/*! Returns the last element being pointed by the iterator */
SrListNode* getlast () const { return _last; }
/*! Must be called each time the associate list is changed */
void reset ();
/*! Points the iterator to the first element. */
void first () { _cur=_first; _rcode=1; }
/*! Points the iterator to the last element. */
void last () { _cur=_last; _rcode=1; }
/*! Advances the current position of the iterator of one position */
void next () { _cur=_cur->next(); }
/*! Walk back the current position of the iterator of one position */
void prior () { _cur=_cur->prior(); }
/*! This method only makes sense when called in a loop, like in: the following
for ( it.first(); it.inrange(); it.next() ) { ... }
or for ( it.last(); it.inrange(); it.prior() ) { ... } */
bool inrange ();
/*! Returns true if the current position is pointing to the last element. */
bool inlast () const { return _cur==_last; }
/*! Returns true if the current position is pointing to the first element,
or if the list is empty. */
bool infirst () const { return _cur==_first; }
};
/*! Derives SrListIteratorBase providing correct type casts for the user type */
template <class X>
class SrListIterator : public SrListIteratorBase
{ public :
SrListIterator ( const SrList<X>& l ) : SrListIteratorBase(l) {}
SrListIterator ( X* n ) : SrListIteratorBase((SrListNode*)n) {}
X* get () { return (X*)SrListIteratorBase::get(); }
X* operator-> () { return (X*)SrListIteratorBase::get(); }
};
//============================== end of file ===============================
# endif // SR_LIST_H