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>
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
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__, __LINE__);
00141 }
00142
00143
00144 template <class list_type>
00145 List<list_type>::List( const List& original_copy )
00146 {
00147
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__, __LINE__ );
00157
00158 for ( unsigned int counter = 0; counter < original_copy.list_size; ++counter )
00159 listArray[ counter ] = original_copy.listArray[ counter ];
00160
00161
00162
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__, __LINE__ );
00174
00175
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__, __LINE__ );
00186
00187 for ( unsigned int counter = 0; counter < original_copy.list_size; ++counter )
00188 listArray[ counter ] = original_copy.listArray[ counter ];
00189
00190
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
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
00246 if ( list_size == allocation_size )
00247 {
00248
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
00259 for ( unsigned int counter = 0; counter < list_size; ++counter )
00260 new_array[ counter ] = listArray[ counter ];
00261
00262
00263
00264
00265
00266 RakNet::OP_DELETE_ARRAY(listArray, file, line);
00267
00268 listArray = new_array;
00269 }
00270
00271
00272 for ( unsigned int counter = list_size; counter != position; counter-- )
00273 listArray[ counter ] = listArray[ counter - 1 ];
00274
00275
00276
00277
00278
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
00290
00291 if ( list_size == allocation_size )
00292 {
00293
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
00306 for ( unsigned int counter = 0; counter < list_size; ++counter )
00307 new_array[ counter ] = listArray[ counter ];
00308
00309
00310
00311
00312
00313 RakNet::OP_DELETE_ARRAY(listArray, file, line);
00314 }
00315
00316 listArray = new_array;
00317 }
00318
00319
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
00331 listArray[ position ] = input;
00332 }
00333 else
00334 {
00335 if ( position >= allocation_size )
00336 {
00337
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
00344
00345 for ( unsigned int counter = 0; counter < list_size; ++counter )
00346 new_array[ counter ] = listArray[ counter ];
00347
00348
00349
00350
00351
00352 RakNet::OP_DELETE_ARRAY(listArray, file, line);
00353
00354 listArray = new_array;
00355 }
00356
00357
00358 while ( list_size < position )
00359 listArray[ list_size++ ] = filler;
00360
00361
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
00394 for ( unsigned int counter = position; counter < list_size - 1 ; ++counter )
00395 listArray[ counter ] = listArray[ counter + 1 ];
00396
00397
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
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
00469 for ( unsigned int counter = 0; counter < list_size; ++counter )
00470 new_array[ counter ] = listArray[ counter ];
00471
00472
00473
00474
00475
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
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
00502 for ( unsigned int counter = 0; counter < list_size; ++counter )
00503 new_array[ counter ] = listArray[ counter ];
00504
00505
00506
00507
00508
00509 RakNet::OP_DELETE_ARRAY(listArray, file, line);
00510 }
00511
00512 listArray = new_array;
00513 }
00514 }
00515
00516 }
00517
00518 #endif