SinglyLinkedList.hpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 
00022 #ifndef SinglyLinkedList_hpp
00023 #define SinglyLinkedList_hpp
00024 
00025 #include "util/error/Log.hpp"
00026 
00027 
00028 namespace se_core {
00029 
00038     template <class ElementType, int maxElements, int xid> class SinglyLinkedList {
00039     public:
00040         typedef int iterator_type;
00041 
00042 
00047         SinglyLinkedList(const char* name)
00048             : nodes_(new ElementType*[ MAX_ELEMENTS ])
00049             , nextNodes_(new iterator_type[ MAX_ELEMENTS ])
00050             , name_(name) {
00051             clear();
00052             DebugExec(count_ = 0);
00053         }
00054 
00055 
00059         virtual ~SinglyLinkedList() {
00060             delete[] nodes_;
00061             delete[] nextNodes_;
00062         }
00063 
00064 
00074         void add(ElementType* element, iterator_type &firstNode) {
00075             // Check that there are free nodes left
00076             DebugExec(if(firstFreeNode_ == end())) LogDetail(name_ << ": " << MAX_ELEMENTS << " - " << count_);
00077             DebugExec(if(firstFreeNode_ == end())) LogDetail("Size: " << size(firstNode));
00078 
00079             AssertFatal(firstFreeNode_ < MAX_ELEMENTS && firstFreeNode_ >= 0, name_ << " Max size: " << MAX_ELEMENTS << " Chain size: " << size(firstNode));
00080             AssertFatal((element) != 0, name_);
00081             //DbgAssert(!isFree(firstNode));
00082 
00083             // Store pointer to the second node in free node chain
00084             iterator_type tmp = nextNodes_[ firstFreeNode_ ];
00085 
00086             // Make the first free node part of the node chain
00087             nextNodes_[ firstFreeNode_ ] = firstNode;
00088             firstNode = firstFreeNode_;
00089 
00090             // Remove used node from free node chain
00091             firstFreeNode_ = tmp;
00092 
00093             // Store actor as first node of the chain
00094             nodes_[ firstNode ] = element;
00095             DebugExec(++count_);
00096 
00097             DebugExec(if(nodes_[0] == 0) LogDetail(name_));
00098         }
00099 
00100 
00105         ElementType* remove(iterator_type &iterator, const iterator_type &previousElement) {
00106             //Assert(nodes_[0] != 0);
00107             // Store the reference to the element after the iterator
00108             iterator_type tmp = nextNodes_[ iterator ];
00109 
00110             // Put the iterator node into the free node chain
00111             nextNodes_[ iterator ] = firstFreeNode_;
00112             firstFreeNode_ = iterator;
00113 
00114             // Make the iterator point to the next node in the chain
00115             if(previousElement != end()) {
00116                 nextNodes_[ previousElement ] = tmp;
00117             }
00118             iterator = tmp;
00119             Assert(iterator >= -1);
00120             Assert(iterator < MAX_ELEMENTS);
00121 
00122             DebugExec(if(nodes_[0] == 0) LogDetail(name_));
00123 
00124             // Return deleted node
00125             return nodes_[ firstFreeNode_ ];
00126         }
00127 
00128 
00132         ElementType* pop(iterator_type &iterator) {
00133             // Store the reference to the element after the iterator
00134             iterator_type tmp = nextNodes_[ iterator ];
00135             AssertFatal(tmp < MAX_ELEMENTS && tmp >= -1, name_ << " Max size: " << MAX_ELEMENTS);
00136 
00137             // Put the iterator node into the free node chain
00138             nextNodes_[ iterator ] = firstFreeNode_;
00139             firstFreeNode_ = iterator;
00140 
00141             // Make the iterator point to the next node in the chain
00142             iterator = tmp;
00143 
00144             DebugExec(--count_);
00145 
00146             // Return deleted node
00147             return nodes_[ firstFreeNode_ ];
00148         }
00149 
00150 
00162         bool remove(ElementType* element, iterator_type &firstNode) {
00163             //DbgAssert(!isFree(firstNode));
00164             iterator_type iterator = firstNode;
00165             iterator_type prev = end();
00166             //Assert(nodes_[0] != 0 || firstNode == end());
00167 
00168             while(iterator != end()) {
00169                 if(nodes_[ iterator ] == element) {
00170                     if(iterator == firstNode) {
00171                         remove(iterator, end());
00172                         firstNode = iterator;
00173                         return true;
00174                     }
00175                     else {
00176                         // BUG: If two are removed in a row...
00177                         remove(iterator, prev);
00178                         return true;
00179                     }
00180                 }
00181                 else {
00182                     prev = iterator;
00183                     iterator = nextNodes_[ iterator ];
00184                 }
00185             }
00186             DebugExec(if(nodes_[0] == 0) LogDetail(name_));
00187             DebugExec(--count_);
00188             return false;
00189         }
00190 
00191 
00199         void removeChain(iterator_type &firstNode) {
00200             // Store beginning of chain
00201             //DbgAssert(!isFree(firstNode));
00202             if(firstNode == end())
00203                 return;
00204             iterator_type tmp = firstNode;
00205 
00206             // Find last node
00207             while(nextNodes_[ firstNode ] != end()) {
00208                 firstNode = nextNodes_[ firstNode ];
00209             }
00210             // Make last node point to free nodes
00211             nextNodes_[ firstNode ] = firstFreeNode_;
00212 
00213             // Make list of free nodes point to first node
00214             firstFreeNode_ = tmp;
00215 
00216             // Reset firstNode of cleared chain
00217             firstNode = end();
00218         }
00219 
00220 
00228         bool hasElement(ElementType* element, iterator_type& firstNode) {
00229             //DbgAssert(!isFree(firstNode));
00230             iterator_type iterator = firstNode;
00231             while(iterator != end()) {
00232                 if(nodes_[ iterator ] == element)
00233                     return true;
00234 
00235                 // Make iterator point to the next node in the chain
00236                 iterator = nextNodes_[ iterator ];
00237             }
00238             return false;
00239         }
00240 
00241 
00253         ElementType* next(iterator_type& iterator) {
00254             //DbgAssert(!isFree(iterator));
00255             //DbgAssert(iterator != end());
00256             //DbgAssert(iterator >= 0);
00257             DbgAssert(iterator >= 0 && iterator < MAX_ELEMENTS);
00258 
00259             // Store actor
00260             ElementType* tmp = nodes_[ iterator ];
00261 
00262             // Make iterator point to the next node in the chain
00263             iterator = nextNodes_[ iterator ];
00264 
00265             // Return the element the iterator pointed to previously
00266             return tmp;
00267         }
00268 
00269 
00273         static const iterator_type end() {
00274             return -1;
00275         }
00276 
00277 
00285         int size(const iterator_type& firstNode) {
00286             //DbgAssert(!isFree(firstNode));
00287             int s = 0;
00288             iterator_type iterator = firstNode;
00289             while(iterator != end()) {
00290                 ++s;
00291                 iterator = nextNodes_[ iterator ];
00292             }
00293             return s;
00294         }
00295 
00296 
00297         int capacity() {
00298             return size(firstFreeNode_);
00299         }
00300 
00301         bool isFree(const iterator_type &it) {
00302             iterator_type iterator = firstFreeNode_;
00303             while(iterator != end()) {
00304                 if(it == iterator) return true;
00305                 iterator = nextNodes_[ iterator ];
00306             }
00307             return false;
00308         }
00309 
00310 
00311 
00317         void clear() {
00318             firstFreeNode_ = 0;
00319             for(iterator_type i = 0; i < MAX_ELEMENTS; ++i) {
00320                 nextNodes_[ i ] = i + 1;
00321             }
00322             nextNodes_[ MAX_ELEMENTS - 1 ] = end();
00323             //LogDetail("Free node list size (" << name << "): " << size(firstFreeNode_));
00324         }
00325 
00326 
00333         //static const iterator_type end() = -1;
00334         // Must be primitive type
00335         //static const int end() = -1;
00336 
00337 
00338     private:
00339         static const iterator_type MAX_ELEMENTS = maxElements;
00345         iterator_type firstFreeNode_;
00346 
00350         ElementType** nodes_;
00351 
00357         iterator_type* nextNodes_;
00358 
00359     protected:
00363         const char* name_;
00364         DebugExec(int count_);
00365     };
00366 
00367 }
00368 
00369 #endif

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:13 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo