Shadowrun: Awakened 29 September 2011 - Build 871
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_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.

GNU Lesser General Public License 3 Sourceforge.net