//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #ifndef LLIST_H #define LLIST_H //*************************************************************************************** // Linked List //*************************************************************************************** // This template has an overhead of size LListNode for each entry in the linked list - // be aware of this for very large linked lists. // // This template has no destructor! You must explicitly call free() if you want the // contents of the list to be destroyed. // // // WARNING - this template has not been thoroughly tested so there may be bugs in it! // // -Bramage //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- // LListNode template data node //--------------------------------------------------------------------------------------- template class LListNode { public: LListNode * Next; LListNode * Prev; T * Data; LListNode() { Next = NULL; Prev = NULL; Data = NULL; } }; //--------------------------------------------------------------------------------------- // LList template //--------------------------------------------------------------------------------------- template class LList { protected: LListNode< T > *first_entry; LListNode< T > *last_entry; int cnt; public: //--------------------------------------------------------------------------------------- // Constructor initializes empty list //--------------------------------------------------------------------------------------- LList() { reset(); } //--------------------------------------------------------------------------------------- // Reset list to empty state by abandoning contents //--------------------------------------------------------------------------------------- void reset(void) { first_entry = NULL; last_entry = NULL; cnt = 0; } //--------------------------------------------------------------------------------------- // Return entry count //--------------------------------------------------------------------------------------- int size(void) const { return cnt; } //--------------------------------------------------------------------------------------- // Return first list entry (NULL if list empty) //--------------------------------------------------------------------------------------- T *first(void) const { if( first_entry ){ return first_entry->Data; } else { return NULL; } } //--------------------------------------------------------------------------------------- // Return last list entry (NULL if list empty) //--------------------------------------------------------------------------------------- T *last(void) const { if( last_entry ) { return last_entry->Data; } else { return NULL; } } //--------------------------------------------------------------------------------------- // Returns next entry - returns first entry if current == NULL //--------------------------------------------------------------------------------------- T *next( T* current ) { if( current == NULL ) { return first(); } LListNode *next = findNode( current )->Next; if( next ) { return next->Data; } else { return NULL; } } //--------------------------------------------------------------------------------------- // Returns prev entry - returns last entry if current == NULL //--------------------------------------------------------------------------------------- T *prev( T *current ) { if( current == NULL ) { return last(); } LListNode *prev = findNode( current )->Prev; if( prev ) { return prev->Data; } else { return NULL; } } //--------------------------------------------------------------------------------------- // Link new item into list before specified entry // If specified entry==NULL, insert at end of list //--------------------------------------------------------------------------------------- T *link(T *entry, T *next = NULL) { LListNode *prevNode = NULL; LListNode *nextNode = findNode( next ); LListNode *newNode = new LListNode; newNode->Data = entry; if( nextNode == NULL) { prevNode = last_entry; last_entry = newNode; } else { prevNode = nextNode->Prev; nextNode->Prev = newNode; } if( prevNode == NULL ) { first_entry = newNode; } else { prevNode->Next = newNode; } newNode->Next = nextNode; newNode->Prev = prevNode; ++cnt; return entry; } //--------------------------------------------------------------------------------------- // Link new item into list before specified entry // If specified entry==NULL, insert at end of list //--------------------------------------------------------------------------------------- T *link(T &entry, T *next = NULL) { T *newEntry = new T; *newEntry = entry; return link( newEntry, next ); } //--------------------------------------------------------------------------------------- // Unlink item from list (without destroying it) //--------------------------------------------------------------------------------------- void unlink(T *entry) { LListNode *entryNode = findNode( entry ); if( !entryNode ) return; if( entryNode->Prev == NULL ) { first_entry = entryNode->Next; } else { entryNode->Prev->Next = entryNode->Next; } if( entryNode->Next == NULL ) { last_entry = entryNode->Prev; } else { entryNode->Next->Prev = entryNode->Prev; } delete entryNode; --cnt; } //--------------------------------------------------------------------------------------- // Allocate entry and insert before specified entry // If specified entry==NULL, insert at end of list //--------------------------------------------------------------------------------------- T * alloc( T *next = NULL ) { T *entry = new T; if( entry == NULL ) { return NULL; } return link( entry, next ); } //--------------------------------------------------------------------------------------- // Unlink item from list and destroy it //--------------------------------------------------------------------------------------- void free(T *entry) { unlink(entry); delete entry; } //--------------------------------------------------------------------------------------- // Unlink and destroy all list items //--------------------------------------------------------------------------------------- void free(void) { LListNode *node = NULL; while( (node = iterate( node ) )!=NULL ) { LListNode *nodeToKill = node; node = node->Prev; free( nodeToKill->Data ); } } //--------------------------------------------------------------------------------------- // Find node //--------------------------------------------------------------------------------------- LListNode *findNode( T *entry ) { LListNode *it = NULL; while( (it = iterate( it ) )!=NULL ) { if( it->Data == entry ) { return it; } } return NULL; } //--------------------------------------------------------------------------------------- // Returns the next node in list //--------------------------------------------------------------------------------------- LListNode *iterate( LListNode *entry = NULL ) { if( entry == NULL ) return first_entry; return entry->Next; } }; #endif