//========= 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 // FIXME: change the name of this to something more specific. typedef struct { } _Position; typedef _Position *Position; template class GList; template class GListIterator; // GListNode: Class decleration and definition template class GListNode { private: T data; GListNode *next; GListNode *prev; GListNode(); GListNode(T item); friend class GList; friend class GListIterator; }; template GListNode::GListNode() { next = NULL; prev = NULL; } template GListNode::GListNode(T item) { data = item; next = NULL; prev = NULL; } // GList: Class decleration and definition template 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 *head; GListNode *tail; int numItems; friend class GListIterator; }; template GList::GList() { // Set up a dummy head node and a dummy tail node. head = new GListNode; tail = new GListNode; head->next = tail; head->prev = head; tail->next = tail; tail->prev = head; numItems = 0; } template Position GList::InsertAtHead(T item) { GListNode *newNode = new GListNode(item); head->next->prev = newNode; newNode->next = head->next; newNode->prev = head; head->next = newNode; numItems++; return (Position)(void *)newNode; } template Position GList::InsertAtTail(T item) { GListNode *newNode = new GListNode(item); tail->prev->next = newNode; newNode->prev = tail->prev; tail->prev = newNode; newNode->next = tail; numItems++; return (Position)(void *)newNode; } template T GList::Remove(Position position) { GListNode *node = (GListNode *)(void *)position; node->prev->next = node->next; node->next->prev = node->prev; T data = node->data; numItems--; delete node; return data; } template void GList::RemoveAll(void (*DeleteItemFunc)(T)) { GListNode *tmpNode; GListNode *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 void GList::RemoveSelectedItems(bool (*NeedsRemovalFunc)(T), void (*DeleteItemFunc)(T)) { GListNode *tmpNode; GListNode *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 Position GList::InsertAfter(T item, Position position) { GListNode *node = (GListNode *)(void *)position; GListNode *newNode = new GListNode(item); newNode->prev = node; newNode->next = node->next; node->next->prev = newNode; node->next = newNode; numItems++; return (Position)(void *)newNode; } template Position GList::InsertBefore(T item, Position position) { GListNode *node = (GListNode *)(void *)position; GListNode *newNode = new GListNode(item); newNode->prev = node->prev; newNode->next = node; node->prev->next = newNode; node->prev = newNode; numItems++; return (Position)(void *)newNode; } template bool GList::IsEmpty() { return (numItems == 0); } template int GList::GetNumItems() { return numItems; } template T GList::GetItemAtPosition(Position position) { return ((GListNode *)(void *)position)->data; } template Position GList::GetPositionAtIndex(int index) { int i; GListNode *node = head->next; for (i = 0; i < index; i++) { node = node->next; } return (Position)(void *)node; } template T GList::GetItemAtIndex(int index) { return GetItemAtPosition(GetPositionAtIndex(index)); } // GListIterator: Class decleration and definition template class GListIterator { public: GListIterator(GList *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 *list; GListNode *currentNode; }; template GListIterator::GListIterator(GList *list) { this->list = list; GotoHead(); } template void GListIterator::GotoHead() { this->currentNode = list->head->next; } template void GListIterator::GotoTail() { this->currentNode = list->tail->prev; } template void GListIterator::Goto(int index) { currentNode = (GListNode *)(void *)list->GetPositionAtIndex(index); } template void GListIterator::Increment() { currentNode = currentNode->next; } template void GListIterator::Decrement() { currentNode = currentNode->prev; } template T GListIterator::GetCurrentAndIncrement() { T retval = currentNode->data; Increment(); return retval; } template T GListIterator::GetCurrentAndDecrement() { T retval = currentNode->data; Decrement(); return retval; } template T GListIterator::IncrementAndGetCurrent() { Increment(); return GetCurrent(); } template T GListIterator::DecrementAndGetCurrent() { Decrement(); return GetCurrent(); } template T GListIterator::GetCurrent() { return currentNode->data; } template bool GListIterator::AtEnd(void) { return currentNode->next == currentNode; } template bool GListIterator::AtBeginning(void) { return currentNode->prev == currentNode; } #endif /* __LIST_H__ */