diff options
Diffstat (limited to 'public/list.h')
| -rw-r--r-- | public/list.h | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/public/list.h b/public/list.h new file mode 100644 index 0000000..af25411 --- /dev/null +++ b/public/list.h @@ -0,0 +1,352 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef __LIST_H__ +#define __LIST_H__ + +// TODO: +// GetPositionAtIndex needs to keep a cache of the previous call so +// that it doesn't do a linear search every time. + +#include <stdlib.h> + +// FIXME: change the name of this to something more specific. +typedef struct +{ +} _Position; +typedef _Position *Position; + +template <class T> class GList; +template <class T> class GListIterator; + +// GListNode: Class decleration and definition +template <class T> class GListNode +{ +private: + T data; + GListNode<T> *next; + GListNode<T> *prev; + GListNode(); + GListNode( T item ); + friend class GList<T>; + friend class GListIterator<T>; +}; + +template <class T> +GListNode<T>::GListNode() +{ + next = NULL; + prev = NULL; +} + +template <class T> +GListNode<T>::GListNode( T item ) +{ + data = item; + next = NULL; + prev = NULL; +} + +// GList: Class decleration and definition +template <class T> class GList +{ +public: + // Contructors/destructors + GList(); + + // + Position InsertAtHead( T ); + Position InsertAtTail( T ); + T Remove( Position position ); + void RemoveAll( void (*DeleteItem)( T ) ); + void RemoveSelectedItems( bool (*NeedsRemovalFunc)( T ), void (*DeleteItemFunc)( T ) ); + Position InsertAfter( T item, Position position ); + Position InsertBefore( T item, Position position ); + bool IsEmpty(); + int GetNumItems(); + T GetItemAtPosition( Position position ); + Position GetPositionAtIndex( int index ); + T GetItemAtIndex( int index ); + +protected: + GListNode<T> *head; + GListNode<T> *tail; + int numItems; + friend class GListIterator<T>; +}; + +template<class T> +GList<T>::GList() +{ + // Set up a dummy head node and a dummy tail node. + head = new GListNode<T>; + tail = new GListNode<T>; + head->next = tail; + head->prev = head; + tail->next = tail; + tail->prev = head; + numItems = 0; +} + +template<class T> +Position GList<T>::InsertAtHead( T item ) +{ + GListNode<T> *newNode = new GListNode<T>( item ); + head->next->prev = newNode; + newNode->next = head->next; + newNode->prev = head; + head->next = newNode; + numItems++; + return ( Position )( void * )newNode; +} + +template<class T> +Position GList<T>::InsertAtTail( T item ) +{ + GListNode<T> *newNode = new GListNode<T>( item ); + tail->prev->next = newNode; + newNode->prev = tail->prev; + tail->prev = newNode; + newNode->next = tail; + numItems++; + return ( Position )( void * )newNode; +} + +template<class T> +T GList<T>::Remove( Position position ) +{ + GListNode<T> *node = ( GListNode<T> * )( void * )position; + node->prev->next = node->next; + node->next->prev = node->prev; + T data = node->data; + numItems--; + delete node; + return data; +} + +template<class T> +void GList<T>::RemoveAll( void (*DeleteItemFunc)( T ) ) +{ + GListNode<T> *tmpNode; + GListNode<T> *node = head->next; + while( node != tail ) + { + if( DeleteItemFunc ) + { + DeleteItemFunc( node->data ); + } + tmpNode = node->next; + delete node; + node = tmpNode; + } + head->next = tail; + head->prev = head; + tail->next = tail; + tail->prev = head; + numItems = 0; +} + +template<class T> +void GList<T>::RemoveSelectedItems( bool (*NeedsRemovalFunc)( T ), void (*DeleteItemFunc)( T ) ) +{ + GListNode<T> *tmpNode; + GListNode<T> *node = head->next; + while( node != tail ) + { + if( NeedsRemovalFunc( node->data ) ) + { + DeleteItemFunc( node->data ); + node->prev->next = node->next; + node->next->prev = node->prev; + tmpNode = node; + node = node->next; + delete tmpNode; + numItems--; + } + else + { + node = node->next; + } + } +} + +template<class T> +Position GList<T>::InsertAfter( T item, Position position ) +{ + GListNode<T> *node = ( GListNode<T> * )( void * )position; + GListNode<T> *newNode = new GListNode<T>( item ); + newNode->prev = node; + newNode->next = node->next; + node->next->prev = newNode; + node->next = newNode; + numItems++; + return ( Position )( void * )newNode; +} + +template<class T> +Position GList<T>::InsertBefore( T item, Position position ) +{ + GListNode<T> *node = ( GListNode<T> * )( void * )position; + GListNode<T> *newNode = new GListNode<T>( item ); + newNode->prev = node->prev; + newNode->next = node; + node->prev->next = newNode; + node->prev = newNode; + numItems++; + return ( Position )( void * )newNode; +} + +template<class T> +bool GList<T>::IsEmpty() +{ + return ( numItems == 0 ); +} + +template <class T> +int GList<T>::GetNumItems() +{ + return numItems; +} + +template<class T> +T GList<T>::GetItemAtPosition( Position position ) +{ + return ( ( GListNode<T> * )( void * )position )->data; +} + +template<class T> +Position GList<T>::GetPositionAtIndex( int index ) +{ + int i; + GListNode<T> *node = head->next; + for( i = 0; i < index; i++ ) + { + node = node->next; + } + return ( Position )( void * )node; +} + +template<class T> +T GList<T>::GetItemAtIndex( int index ) +{ + return GetItemAtPosition( GetPositionAtIndex( index ) ); +} + +// GListIterator: Class decleration and definition +template<class T> class GListIterator +{ +public: + GListIterator( GList<T> *GList ); + void GotoHead( void ); + void GotoTail( void ); + void Goto( int index ); + void Increment(); + void Decrement(); + T GetCurrentAndIncrement(); + T GetCurrentAndDecrement(); + T IncrementAndGetCurrent(); + T DecrementAndGetCurrent(); + // postfix + T operator++( int ) { return GetCurrentAndIncrement(); } + T operator--( int ) { return GetCurrentAndDecrement(); } + // prefix + T operator++() { return IncrementAndGetCurrent(); } + T operator--() { return DecrementAndGetCurrent(); } + T GetCurrent(); + bool AtEnd( void ); + bool AtBeginning( void ); +protected: + GList<T> *list; + GListNode<T> *currentNode; +}; + +template<class T> +GListIterator<T>::GListIterator( GList<T> *list ) +{ + this->list = list; + GotoHead(); +} + +template<class T> +void GListIterator<T>::GotoHead() +{ + this->currentNode = list->head->next; +} + +template<class T> +void GListIterator<T>::GotoTail() +{ + this->currentNode = list->tail->prev; +} + +template<class T> +void GListIterator<T>::Goto( int index ) +{ + currentNode = ( GListNode<T> * )( void * )list->GetPositionAtIndex( index ); +} + +template<class T> +void GListIterator<T>::Increment() +{ + currentNode = currentNode->next; +} + +template<class T> +void GListIterator<T>::Decrement() +{ + currentNode = currentNode->prev; +} + +template<class T> +T GListIterator<T>::GetCurrentAndIncrement() +{ + T retval = currentNode->data; + Increment(); + return retval; +} + +template<class T> +T GListIterator<T>::GetCurrentAndDecrement() +{ + T retval = currentNode->data; + Decrement(); + return retval; +} + +template<class T> +T GListIterator<T>::IncrementAndGetCurrent() +{ + Increment(); + return GetCurrent(); +} + +template<class T> +T GListIterator<T>::DecrementAndGetCurrent() +{ + Decrement(); + return GetCurrent(); +} + +template<class T> +T GListIterator<T>::GetCurrent() +{ + return currentNode->data; +} + +template<class T> +bool GListIterator<T>::AtEnd( void ) +{ + return currentNode->next == currentNode; +} + +template<class T> +bool GListIterator<T>::AtBeginning( void ) +{ + return currentNode->prev == currentNode; +} + +#endif /* __LIST_H__ */ |