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.