This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

322 lines
7.4 KiB
C++

//========= 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__ */