• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

DS_List.h

Go to the documentation of this file.
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__, __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__, __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__, __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__, __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

Generated on Thu Sep 30 2010 01:27:22 for RakNet by  doxygen 1.7.1