123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #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 T> class LListNode
- {
- public:
- LListNode<T> * Next;
- LListNode<T> * Prev;
- T * Data;
- LListNode()
- {
- Next = NULL;
- Prev = NULL;
- Data = NULL;
- }
- };
- //---------------------------------------------------------------------------------------
- // LList template
- //---------------------------------------------------------------------------------------
- template <class T> 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<T> *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<T> *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<T> *prevNode = NULL;
- LListNode<T> *nextNode = findNode( next );
- LListNode<T> *newNode = new LListNode<T>;
- 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<T> *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<T> *node = NULL;
- while( (node = iterate( node ) )!=NULL )
- {
- LListNode<T> *nodeToKill = node;
- node = node->Prev;
- free( nodeToKill->Data );
- }
- }
- //---------------------------------------------------------------------------------------
- // Find node
- //---------------------------------------------------------------------------------------
- LListNode<T> *findNode( T *entry )
- {
- LListNode<T> *it = NULL;
- while( (it = iterate( it ) )!=NULL )
- {
- if( it->Data == entry )
- {
- return it;
- }
- }
- return NULL;
- }
- //---------------------------------------------------------------------------------------
- // Returns the next node in list
- //---------------------------------------------------------------------------------------
- LListNode<T> *iterate( LListNode<T> *entry = NULL )
- {
- if( entry == NULL ) return first_entry;
- return entry->Next;
- }
- };
- #endif
|