![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 #ifndef __LIST_H 00012 #define __LIST_H 00013 00014 #include "RakAssert.h" 00015 #include <string.h> // memmove 00016 #include "Export.h" 00017 #include "RakMemoryOverride.h" 00018 00020 static const unsigned int MAX_UNSIGNED_LONG = 4294967295U; 00021 00024 namespace DataStructures 00025 { 00028 template <class list_type> 00029 class RAK_DLL_EXPORT List 00030 { 00031 public: 00033 List(); 00034 00035 // Destructor 00036 ~List(); 00037 00040 List( const List& original_copy ); 00041 00043 List& operator= ( const List& original_copy ); 00044 00048 list_type& operator[] ( const unsigned int position ) const; 00049 00053 list_type& Get ( const unsigned int position ) const; 00054 00057 void Push(const list_type &input, const char *file, unsigned int line ); 00058 00062 list_type& Pop(void); 00063 00067 void Insert( const list_type &input, const unsigned int position, const char *file, unsigned int line ); 00068 00071 void Insert( const list_type &input, const char *file, unsigned int line ); 00072 00079 void Replace( const list_type &input, const list_type filler, const unsigned int position, const char *file, unsigned int line ); 00080 00083 void Replace( const list_type &input ); 00084 00087 void RemoveAtIndex( const unsigned int position ); 00088 00092 void RemoveAtIndexFast( const unsigned int position ); 00093 00095 void RemoveFromEnd(const unsigned num=1); 00096 00102 unsigned int GetIndexOf( const list_type &input ) const; 00103 00105 unsigned int Size( void ) const; 00106 00108 void Clear( bool doNotDeallocateSmallBlocks, const char *file, unsigned int line ); 00109 00111 void Preallocate( unsigned countNeeded, const char *file, unsigned int line ); 00112 00116 void Compress( const char *file, unsigned int line ); 00117 00118 private: 00120 list_type* listArray; 00121 00123 unsigned int list_size; 00124 00126 unsigned int allocation_size; 00127 }; 00128 template <class list_type> 00129 List<list_type>::List() 00130 { 00131 allocation_size = 0; 00132 listArray = 0; 00133 list_size = 0; 00134 } 00135 00136 template <class list_type> 00137 List<list_type>::~List() 00138 { 00139 if (allocation_size>0) 00140 RakNet::OP_DELETE_ARRAY(listArray, _FILE_AND_LINE_); 00141 } 00142 00143 00144 template <class list_type> 00145 List<list_type>::List( const List& original_copy ) 00146 { 00147 // Allocate memory for copy 00148 00149 if ( original_copy.list_size == 0 ) 00150 { 00151 list_size = 0; 00152 allocation_size = 0; 00153 } 00154 else 00155 { 00156 listArray = RakNet::OP_NEW_ARRAY<list_type >( original_copy.list_size , _FILE_AND_LINE_ ); 00157 00158 for ( unsigned int counter = 0; counter < original_copy.list_size; ++counter ) 00159 listArray[ counter ] = original_copy.listArray[ counter ]; 00160 00161 // Don't call constructors, assignment operators, etc. 00162 //memcpy(listArray, original_copy.listArray, original_copy.list_size*sizeof(list_type)); 00163 00164 list_size = allocation_size = original_copy.list_size; 00165 } 00166 } 00167 00168 template <class list_type> 00169 List<list_type>& List<list_type>::operator= ( const List& original_copy ) 00170 { 00171 if ( ( &original_copy ) != this ) 00172 { 00173 Clear( false, _FILE_AND_LINE_ ); 00174 00175 // Allocate memory for copy 00176 00177 if ( original_copy.list_size == 0 ) 00178 { 00179 list_size = 0; 00180 allocation_size = 0; 00181 } 00182 00183 else 00184 { 00185 listArray = RakNet::OP_NEW_ARRAY<list_type >( original_copy.list_size , _FILE_AND_LINE_ ); 00186 00187 for ( unsigned int counter = 0; counter < original_copy.list_size; ++counter ) 00188 listArray[ counter ] = original_copy.listArray[ counter ]; 00189 // Don't call constructors, assignment operators, etc. 00190 //memcpy(listArray, original_copy.listArray, original_copy.list_size*sizeof(list_type)); 00191 00192 list_size = allocation_size = original_copy.list_size; 00193 } 00194 } 00195 00196 return *this; 00197 } 00198 00199 00200 template <class list_type> 00201 inline list_type& List<list_type>::operator[] ( const unsigned int position ) const 00202 { 00203 #ifdef _DEBUG 00204 if (position>=list_size) 00205 { 00206 RakAssert ( position < list_size ); 00207 } 00208 #endif 00209 return listArray[ position ]; 00210 } 00211 00212 // Just here for debugging 00213 template <class list_type> 00214 inline list_type& List<list_type>::Get ( const unsigned int position ) const 00215 { 00216 return listArray[ position ]; 00217 } 00218 00219 template <class list_type> 00220 void List<list_type>::Push(const list_type &input, const char *file, unsigned int line) 00221 { 00222 Insert(input, file, line); 00223 } 00224 00225 template <class list_type> 00226 inline list_type& List<list_type>::Pop(void) 00227 { 00228 #ifdef _DEBUG 00229 RakAssert(list_size>0); 00230 #endif 00231 --list_size; 00232 return listArray[list_size]; 00233 } 00234 00235 template <class list_type> 00236 void List<list_type>::Insert( const list_type &input, const unsigned int position, const char *file, unsigned int line ) 00237 { 00238 #ifdef _DEBUG 00239 if (position>list_size) 00240 { 00241 RakAssert( position <= list_size ); 00242 } 00243 #endif 00244 00245 // Reallocate list if necessary 00246 if ( list_size == allocation_size ) 00247 { 00248 // allocate twice the currently allocated memory 00249 list_type * new_array; 00250 00251 if ( allocation_size == 0 ) 00252 allocation_size = 16; 00253 else 00254 allocation_size *= 2; 00255 00256 new_array = RakNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line ); 00257 00258 // copy old array over 00259 for ( unsigned int counter = 0; counter < list_size; ++counter ) 00260 new_array[ counter ] = listArray[ counter ]; 00261 00262 // Don't call constructors, assignment operators, etc. 00263 //memcpy(new_array, listArray, list_size*sizeof(list_type)); 00264 00265 // set old array to point to the newly allocated and twice as large array 00266 RakNet::OP_DELETE_ARRAY(listArray, file, line); 00267 00268 listArray = new_array; 00269 } 00270 00271 // Move the elements in the list to make room 00272 for ( unsigned int counter = list_size; counter != position; counter-- ) 00273 listArray[ counter ] = listArray[ counter - 1 ]; 00274 00275 // Don't call constructors, assignment operators, etc. 00276 //memmove(listArray+position+1, listArray+position, (list_size-position)*sizeof(list_type)); 00277 00278 // Insert the new item at the correct spot 00279 listArray[ position ] = input; 00280 00281 ++list_size; 00282 00283 } 00284 00285 00286 template <class list_type> 00287 void List<list_type>::Insert( const list_type &input, const char *file, unsigned int line ) 00288 { 00289 // Reallocate list if necessary 00290 00291 if ( list_size == allocation_size ) 00292 { 00293 // allocate twice the currently allocated memory 00294 list_type * new_array; 00295 00296 if ( allocation_size == 0 ) 00297 allocation_size = 16; 00298 else 00299 allocation_size *= 2; 00300 00301 new_array = RakNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line ); 00302 00303 if (listArray) 00304 { 00305 // copy old array over 00306 for ( unsigned int counter = 0; counter < list_size; ++counter ) 00307 new_array[ counter ] = listArray[ counter ]; 00308 00309 // Don't call constructors, assignment operators, etc. 00310 //memcpy(new_array, listArray, list_size*sizeof(list_type)); 00311 00312 // set old array to point to the newly allocated and twice as large array 00313 RakNet::OP_DELETE_ARRAY(listArray, file, line); 00314 } 00315 00316 listArray = new_array; 00317 } 00318 00319 // Insert the new item at the correct spot 00320 listArray[ list_size ] = input; 00321 00322 ++list_size; 00323 } 00324 00325 template <class list_type> 00326 inline void List<list_type>::Replace( const list_type &input, const list_type filler, const unsigned int position, const char *file, unsigned int line ) 00327 { 00328 if ( ( list_size > 0 ) && ( position < list_size ) ) 00329 { 00330 // Direct replacement 00331 listArray[ position ] = input; 00332 } 00333 else 00334 { 00335 if ( position >= allocation_size ) 00336 { 00337 // Reallocate the list to size position and fill in blanks with filler 00338 list_type * new_array; 00339 allocation_size = position + 1; 00340 00341 new_array = RakNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line ); 00342 00343 // copy old array over 00344 00345 for ( unsigned int counter = 0; counter < list_size; ++counter ) 00346 new_array[ counter ] = listArray[ counter ]; 00347 00348 // Don't call constructors, assignment operators, etc. 00349 //memcpy(new_array, listArray, list_size*sizeof(list_type)); 00350 00351 // set old array to point to the newly allocated array 00352 RakNet::OP_DELETE_ARRAY(listArray, file, line); 00353 00354 listArray = new_array; 00355 } 00356 00357 // Fill in holes with filler 00358 while ( list_size < position ) 00359 listArray[ list_size++ ] = filler; 00360 00361 // Fill in the last element with the new item 00362 listArray[ list_size++ ] = input; 00363 00364 #ifdef _DEBUG 00365 00366 RakAssert( list_size == position + 1 ); 00367 00368 #endif 00369 00370 } 00371 } 00372 00373 template <class list_type> 00374 inline void List<list_type>::Replace( const list_type &input ) 00375 { 00376 if ( list_size > 0 ) 00377 listArray[ list_size - 1 ] = input; 00378 } 00379 00380 template <class list_type> 00381 void List<list_type>::RemoveAtIndex( const unsigned int position ) 00382 { 00383 #ifdef _DEBUG 00384 if (position >= list_size) 00385 { 00386 RakAssert( position < list_size ); 00387 return; 00388 } 00389 #endif 00390 00391 if ( position < list_size ) 00392 { 00393 // Compress the array 00394 for ( unsigned int counter = position; counter < list_size - 1 ; ++counter ) 00395 listArray[ counter ] = listArray[ counter + 1 ]; 00396 // Don't call constructors, assignment operators, etc. 00397 // memmove(listArray+position, listArray+position+1, (list_size-1-position) * sizeof(list_type)); 00398 00399 RemoveFromEnd(); 00400 } 00401 } 00402 00403 template <class list_type> 00404 void List<list_type>::RemoveAtIndexFast( const unsigned int position ) 00405 { 00406 #ifdef _DEBUG 00407 if (position >= list_size) 00408 { 00409 RakAssert( position < list_size ); 00410 return; 00411 } 00412 #endif 00413 --list_size; 00414 listArray[position]=listArray[list_size]; 00415 } 00416 00417 template <class list_type> 00418 inline void List<list_type>::RemoveFromEnd( const unsigned num ) 00419 { 00420 // Delete the last elements on the list. No compression needed 00421 #ifdef _DEBUG 00422 RakAssert(list_size>=num); 00423 #endif 00424 list_size-=num; 00425 } 00426 00427 template <class list_type> 00428 unsigned int List<list_type>::GetIndexOf( const list_type &input ) const 00429 { 00430 for ( unsigned int i = 0; i < list_size; ++i ) 00431 if ( listArray[ i ] == input ) 00432 return i; 00433 00434 return MAX_UNSIGNED_LONG; 00435 } 00436 00437 template <class list_type> 00438 inline unsigned int List<list_type>::Size( void ) const 00439 { 00440 return list_size; 00441 } 00442 00443 template <class list_type> 00444 void List<list_type>::Clear( bool doNotDeallocateSmallBlocks, const char *file, unsigned int line ) 00445 { 00446 if ( allocation_size == 0 ) 00447 return; 00448 00449 if (allocation_size>512 || doNotDeallocateSmallBlocks==false) 00450 { 00451 RakNet::OP_DELETE_ARRAY(listArray, file, line); 00452 allocation_size = 0; 00453 listArray = 0; 00454 } 00455 list_size = 0; 00456 } 00457 00458 template <class list_type> 00459 void List<list_type>::Compress( const char *file, unsigned int line ) 00460 { 00461 list_type * new_array; 00462 00463 if ( allocation_size == 0 ) 00464 return ; 00465 00466 new_array = RakNet::OP_NEW_ARRAY<list_type >( allocation_size , file, line ); 00467 00468 // copy old array over 00469 for ( unsigned int counter = 0; counter < list_size; ++counter ) 00470 new_array[ counter ] = listArray[ counter ]; 00471 00472 // Don't call constructors, assignment operators, etc. 00473 //memcpy(new_array, listArray, list_size*sizeof(list_type)); 00474 00475 // set old array to point to the newly allocated array 00476 RakNet::OP_DELETE_ARRAY(listArray, file, line); 00477 00478 listArray = new_array; 00479 } 00480 00481 template <class list_type> 00482 void List<list_type>::Preallocate( unsigned countNeeded, const char *file, unsigned int line ) 00483 { 00484 unsigned amountToAllocate = allocation_size; 00485 if (allocation_size==0) 00486 amountToAllocate=16; 00487 while (amountToAllocate < countNeeded) 00488 amountToAllocate<<=1; 00489 00490 if ( allocation_size < amountToAllocate) 00491 { 00492 // allocate twice the currently allocated memory 00493 list_type * new_array; 00494 00495 allocation_size=amountToAllocate; 00496 00497 new_array = RakNet::OP_NEW_ARRAY< list_type >( allocation_size , file, line ); 00498 00499 if (listArray) 00500 { 00501 // copy old array over 00502 for ( unsigned int counter = 0; counter < list_size; ++counter ) 00503 new_array[ counter ] = listArray[ counter ]; 00504 00505 // Don't call constructors, assignment operators, etc. 00506 //memcpy(new_array, listArray, list_size*sizeof(list_type)); 00507 00508 // set old array to point to the newly allocated and twice as large array 00509 RakNet::OP_DELETE_ARRAY(listArray, file, line); 00510 } 00511 00512 listArray = new_array; 00513 } 00514 } 00515 00516 } // End namespace 00517 00518 #endif
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.