You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
6.9 KiB
352 lines
6.9 KiB
//========= 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__ */
|
|
|