Shadowrun: Awakened 29 September 2011 - Build 871
DS_Multilist.h
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __MULTILIST_H
00011 #define __MULTILIST_H 
00012 
00013 #include "RakAssert.h"
00014 #include <string.h> // memmove
00015 #include "Export.h"
00016 #include "RakMemoryOverride.h"
00017 #include "NativeTypes.h"
00018 
00019 
00020 #ifdef _MSC_VER
00021 #pragma warning( push )
00022 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00023 #pragma warning( disable : 4512 ) // warning C4512: assignment operator could not be generated
00024 #endif
00025 
00027 enum MultilistType
00028 {
00030     ML_UNORDERED_LIST,
00032     ML_STACK,
00034     ML_QUEUE,
00036     ML_ORDERED_LIST,
00038     ML_VARIABLE_DURING_RUNTIME
00039 };
00040 
00043 namespace DataStructures
00044 {
00047     template <class templateType>
00048     void DeletePtr_RakNet(templateType &ptr, const char *file, unsigned int line ) {RakNet::OP_DELETE(ptr, file, line);}
00049 
00052     template <class templateType>
00053     void DeletePtr(templateType &ptr) {delete ptr;}
00054 
00060     template < class templateType >
00061     class MLKeyRef
00062     {
00063     public:
00064         MLKeyRef(const templateType& input) : val(input) {}
00065         const templateType &Get(void) const {return val;}
00066         bool operator<( const templateType &right ) {return val < right;}
00067         bool operator>( const templateType &right ) {return val > right;}
00068         bool operator==( const templateType &right ) {return val == right;}
00069     protected:
00070         const templateType &val;
00071     };
00072 
00078     #define DEFINE_MULTILIST_PTR_TO_MEMBER_COMPARISONS( _CLASS_NAME_, _KEY_TYPE_, _MEMBER_VARIABLE_NAME_ ) \
00079     bool operator<( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() < cls->_MEMBER_VARIABLE_NAME_;} \
00080     bool operator>( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() > cls->_MEMBER_VARIABLE_NAME_;} \
00081     bool operator==( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() == cls->_MEMBER_VARIABLE_NAME_;}
00082 
00083     typedef uint32_t DefaultIndexType;
00084 
00090     template <const MultilistType _MultilistType, class _DataType, class _KeyType=_DataType, class _IndexType=DefaultIndexType>
00091     class RAK_DLL_EXPORT Multilist
00092     {
00093     public:
00094         Multilist();
00095         ~Multilist();
00096         Multilist( const Multilist& source );
00097         Multilist& operator= ( const Multilist& source );
00098         _DataType& operator[] ( const _IndexType position ) const;
00102         void Push(const _DataType &d, const char *file=__FILE__, unsigned int line=__LINE__ );
00103         void Push(const _DataType &d, const _KeyType &key, const char *file=__FILE__, unsigned int line=__LINE__ );
00104 
00107         _DataType &Pop(const char *file=__FILE__, unsigned int line=__LINE__);
00108         _DataType &Peek(void) const;
00109 
00112         void PushOpposite(const _DataType &d, const char *file=__FILE__, unsigned int line=__LINE__ );
00113         void PushOpposite(const _DataType &d, const _KeyType &key, const char *file=__FILE__, unsigned int line=__LINE__ );
00114 
00116         _DataType &PopOpposite(const char *file=__FILE__, unsigned int line=__LINE__);
00117         _DataType &PeekOpposite(void) const;
00118 
00121         void InsertAtIndex(const _DataType &d, _IndexType index, const char *file=__FILE__, unsigned int line=__LINE__);    
00122         
00127         void RemoveAtIndex(_IndexType position, const char *file=__FILE__, unsigned int line=__LINE__);
00128 
00130         bool RemoveAtKey(_KeyType key, bool assertIfDoesNotExist, const char *file=__FILE__, unsigned int line=__LINE__);
00131 
00133         _IndexType GetIndexOf(_KeyType key) const;
00134 
00137         _IndexType GetInsertionIndex(_KeyType key) const;
00138 
00140         _DataType GetPtr(_KeyType key) const;
00141 
00143         void ForEach(void (*func)(_DataType &item, const char *file, unsigned int line), const char *file, unsigned int line);
00144         void ForEach(void (*func)(_DataType &item));    
00145 
00147         bool IsEmpty(void) const;
00148 
00150         _IndexType GetSize(void) const;
00151 
00154         void Clear( bool deallocateSmallBlocks=true, const char *file=__FILE__, unsigned int line=__LINE__ );
00155 
00158         void ClearPointers( bool deallocateSmallBlocks=true, const char *file=__FILE__, unsigned int line=__LINE__ );
00159 
00161         void ClearPointer( _KeyType key, const char *file=__FILE__, unsigned int line=__LINE__ );
00162 
00165         void ReverseList(void);
00166 
00169         void Reallocate(_IndexType size, const char *file=__FILE__, unsigned int line=__LINE__);
00170 
00174         void Sort(bool force);
00175 
00178         void TagSorted(void);
00179 
00182         void SetSortOrder(bool ascending);
00183 
00185         bool GetSortOrder(void) const;
00186 
00190         bool IsSorted(void) const;
00191 
00193         MultilistType GetMultilistType(void) const;
00194 
00198         void SetMultilistType(MultilistType newType);
00199 
00202         static void FindIntersection(
00203             Multilist& source1,
00204             Multilist& source2, 
00205             Multilist& intersection,
00206             Multilist& uniqueToSource1,
00207             Multilist& uniqueToSource2);
00208 
00209     protected:
00210         void ReallocateIfNeeded(const char *file, unsigned int line);
00211         void DeallocateIfNeeded(const char *file, unsigned int line);
00212         void ReallocToSize(_IndexType newAllocationSize, const char *file, unsigned int line);
00213         void ReverseListInternal(void);
00214         void InsertInOrderedList(const _DataType &d, const _KeyType &key);
00215         _IndexType GetIndexFromKeyInSortedList(const _KeyType &key, bool *objectExists) const;
00216         void InsertShiftArrayRight(const _DataType &d, _IndexType index);
00217         void DeleteShiftArrayLeft(_IndexType index);
00218         void QSortAscending(_IndexType left, _IndexType right);
00219         void QSortDescending(_IndexType left, _IndexType right);
00220         void CopySource( const Multilist& source );
00221 
00223         _DataType* data;
00224         
00226         _IndexType dataSize;
00227         
00229         _IndexType allocationSize;
00230 
00232         _IndexType queueHead;
00233 
00235         _IndexType queueTail;
00236 
00239         _IndexType preallocationSize;
00240 
00241         enum
00242         {
00243             ML_UNSORTED,
00244             ML_SORTED_ASCENDING,
00245             ML_SORTED_DESCENDING
00246         } sortState;
00247 
00248         bool ascendingSort;
00249 
00250         // In case we are using the variable type multilist
00251         MultilistType variableMultilistType;
00252     };
00253 
00254     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00255     Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Multilist()
00256     {
00257         data=0;
00258         dataSize=0;
00259         allocationSize=0;
00260         ascendingSort=true;
00261         sortState=ML_UNSORTED;
00262         queueHead=0;
00263         queueTail=0;
00264         preallocationSize=0;
00265 
00266         if (_MultilistType==ML_ORDERED_LIST)
00267             sortState=ML_SORTED_ASCENDING;
00268         else
00269             sortState=ML_UNSORTED;
00270 
00271         if (_MultilistType==ML_VARIABLE_DURING_RUNTIME)
00272             variableMultilistType=ML_UNORDERED_LIST;
00273     }
00274 
00275     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00276     Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::~Multilist()
00277     {
00278         if (data!=0)
00279             RakNet::OP_DELETE_ARRAY(data, _FILE_AND_LINE_);
00280     }
00281 
00282     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00283     Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Multilist( const Multilist& source )
00284     {
00285         CopySource(source);
00286     }
00287 
00288     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00289     Multilist<_MultilistType, _DataType, _KeyType, _IndexType>& Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::operator= ( const Multilist& source )
00290     {
00291         Clear(true);
00292         CopySource(source);
00293         return *this;
00294     }
00295 
00296     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00297     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::CopySource( const Multilist& source )
00298     {
00299         dataSize=source.GetSize();
00300         ascendingSort=source.ascendingSort;
00301         sortState=source.sortState;
00302         queueHead=0;
00303         queueTail=dataSize;
00304         preallocationSize=source.preallocationSize;
00305         variableMultilistType=source.variableMultilistType;
00306         if (source.data==0)
00307         {
00308             data=0;
00309             allocationSize=0;
00310         }
00311         else
00312         {
00313             allocationSize=dataSize;
00314             data = RakNet::OP_NEW_ARRAY<_DataType>(dataSize,_FILE_AND_LINE_);
00315             _IndexType i;
00316             for (i=0; i < dataSize; i++)
00317                 data[i]=source[i];
00318         }
00319     }
00320 
00321     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00322     _DataType& Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::operator[] ( const _IndexType position ) const
00323     {
00324         RakAssert(position<GetSize());
00325 
00326         if (GetMultilistType()==ML_QUEUE)
00327         {
00328             if ( queueHead + position >= allocationSize )
00329                 return data[ queueHead + position - allocationSize ];
00330             else
00331                 return data[ queueHead + position ];
00332         }
00333         
00334         return data[position];
00335     }
00336 
00337     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00338     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Push(const _DataType &d, const char *file, unsigned int line )
00339     {
00340         Push(d,d,file,line);
00341     }
00342 
00343     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00344     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Push(const _DataType &d, const _KeyType &key, const char *file, unsigned int line )
00345     {
00346         ReallocateIfNeeded(file,line);
00347 
00348         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
00349         {
00350             data[dataSize]=d;
00351             dataSize++;
00352         }
00353         else if (GetMultilistType()==ML_QUEUE)
00354         {
00355             data[queueTail++] = d;
00356 
00357             if ( queueTail == allocationSize )
00358                 queueTail = 0;
00359             dataSize++;
00360         }
00361         else
00362         {
00363             RakAssert(GetMultilistType()==ML_ORDERED_LIST);
00364             InsertInOrderedList(d,key);
00365         }
00366 
00367         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_QUEUE)
00368         {
00369             // Break sort if no longer sorted
00370             if (sortState!=ML_UNSORTED && dataSize>1)
00371             {
00372                 if (ascendingSort)
00373                 {
00374                     if ( MLKeyRef<_KeyType>(key) < operator[](dataSize-2) )
00375                         sortState=ML_UNSORTED;
00376                 }
00377                 else
00378                 {
00379                     if ( MLKeyRef<_KeyType>(key) > operator[](dataSize-2) )
00380                         sortState=ML_UNSORTED;
00381                 }
00382 
00383                 sortState=ML_UNSORTED;
00384             }
00385         }
00386     }
00387 
00388     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00389     _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Pop(const char *file, unsigned int line)
00390     {
00391         RakAssert(IsEmpty()==false);
00392         DeallocateIfNeeded(file,line);
00393         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
00394         {
00395             dataSize--;
00396             return data[dataSize];
00397         }
00398         else
00399         {
00400             RakAssert(GetMultilistType()==ML_QUEUE);
00401 
00402             if ( ++queueHead == allocationSize )
00403                 queueHead = 0;
00404 
00405             if ( queueHead == 0 )
00406                 return data[ allocationSize -1 ];
00407 
00408             dataSize--;
00409             return data[ queueHead -1 ];
00410         }
00411     }
00412 
00413     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00414     _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Peek(void) const
00415     {
00416         RakAssert(IsEmpty()==false);
00417         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
00418         {
00419             return data[dataSize-1];
00420         }
00421         else
00422         {
00423             RakAssert(GetMultilistType()==ML_QUEUE);
00424             return data[ queueHead ];
00425         }
00426     }
00427 
00428     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00429     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PushOpposite(const _DataType &d, const char *file, unsigned int line )
00430     {
00431         PushOpposite(d,d,file,line);
00432     }
00433 
00434     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00435     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PushOpposite(const _DataType &d, const _KeyType &key, const char *file, unsigned int line )
00436     {
00437         ReallocateIfNeeded(file,line);
00438 
00439         // Unordered list Push at back
00440         if (GetMultilistType()==ML_UNORDERED_LIST)
00441         {
00442             data[dataSize]=d;
00443             dataSize++;
00444         }
00445         else if (GetMultilistType()==ML_STACK)
00446         {
00447             // Stack push at front of the list, instead of back as normal
00448             InsertAtIndex(d,0,file,line);
00449         }
00450         else if (GetMultilistType()==ML_QUEUE)
00451         {
00452             // Queue push at front of the list, instead of back as normal
00453             InsertAtIndex(d,0,file,line);
00454         }
00455         else
00456         {
00457             RakAssert(GetMultilistType()==ML_ORDERED_LIST);
00458             InsertInOrderedList(d,key);
00459         }
00460 
00461         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_QUEUE)
00462         {
00463             // Break sort if no longer sorted
00464             if (sortState!=ML_UNSORTED && dataSize>1)
00465             {
00466                 if (ascendingSort)
00467                 {
00468                     if ( MLKeyRef<_KeyType>(key) > operator[](1) )
00469                         sortState=ML_UNSORTED;
00470                 }
00471                 else
00472                 {
00473                     if ( MLKeyRef<_KeyType>(key) < operator[](1) )
00474                         sortState=ML_UNSORTED;
00475                 }
00476             }
00477         }
00478     }
00479 
00480     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00481     _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PopOpposite(const char *file, unsigned int line)
00482     {
00483         RakAssert(IsEmpty()==false);
00484         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
00485         {
00486             // Copy leftmost to end
00487             ReallocateIfNeeded(file,line);
00488             data[dataSize]=data[0];
00489             DeleteShiftArrayLeft(0);
00490             --dataSize;
00491             // Assuming still leaves at least one element past the end of the list allocated
00492             DeallocateIfNeeded(file,line);
00493             // Return end
00494             return data[dataSize+1];
00495         }
00496         else
00497         {
00498             RakAssert(GetMultilistType()==ML_QUEUE);
00499             // Deallocate first, since we are returning off the existing list
00500             DeallocateIfNeeded(file,line);
00501             dataSize--;
00502 
00503             if (queueTail==0)
00504                 queueTail=allocationSize-1;
00505             else
00506                 --queueTail;
00507 
00508             return data[queueTail];
00509         }
00510     }
00511 
00512     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00513     _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PeekOpposite(void) const
00514     {
00515         RakAssert(IsEmpty()==false);
00516         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
00517         {
00518             return data[0];
00519         }
00520         else
00521         {
00522             RakAssert(GetMultilistType()==ML_QUEUE);
00523             _IndexType priorIndex;
00524             if (queueTail==0)
00525                 priorIndex=allocationSize-1;
00526             else
00527                 priorIndex=queueTail-1;
00528 
00529             return data[priorIndex];
00530         }
00531     }
00532 
00533     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00534     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertAtIndex(const _DataType &d, _IndexType index, const char *file, unsigned int line)
00535     {
00536         ReallocateIfNeeded(file,line);
00537 
00538         if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
00539         {
00540             if (index>=dataSize)
00541             {
00542                 // insert at end
00543                 data[dataSize]=d;
00544 
00545                 dataSize++;
00546             }
00547             else
00548             {
00549                 // insert at index
00550                 InsertShiftArrayRight(d,index);
00551             }
00552         }
00553         else
00554         {
00555             data[queueTail++] = d;
00556 
00557             if ( queueTail == allocationSize )
00558                 queueTail = 0;
00559 
00560             ++dataSize;
00561 
00562             if (dataSize==1)
00563                 return;
00564 
00565             _IndexType writeIndex, readIndex, trueWriteIndex, trueReadIndex;
00566             writeIndex=dataSize-1;
00567             readIndex=writeIndex-1;
00568             while (readIndex >= index)
00569             {
00570                 if ( queueHead + writeIndex >= allocationSize )
00571                     trueWriteIndex = queueHead + writeIndex - allocationSize;
00572                 else
00573                     trueWriteIndex = queueHead + writeIndex;
00574 
00575                 if ( queueHead + readIndex >= allocationSize )
00576                     trueReadIndex = queueHead + readIndex - allocationSize;
00577                 else
00578                     trueReadIndex = queueHead + readIndex;
00579 
00580                 data[trueWriteIndex]=data[trueReadIndex];
00581 
00582                 if (readIndex==0)
00583                     break;
00584                 writeIndex--;
00585                 readIndex--;
00586             }
00587 
00588             if ( queueHead + index >= allocationSize )
00589                 trueWriteIndex = queueHead + index - allocationSize;
00590             else
00591                 trueWriteIndex = queueHead + index;
00592 
00593             data[trueWriteIndex]=d;
00594         }
00595 
00596         if (_MultilistType!=ML_ORDERED_LIST)
00597             sortState=ML_UNSORTED;
00598     }
00599 
00600     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00601     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::RemoveAtIndex(_IndexType position, const char *file, unsigned int line)
00602     {
00603         RakAssert(position < dataSize);
00604         RakAssert(IsEmpty()==false);
00605 
00606         if (GetMultilistType()==ML_UNORDERED_LIST)
00607         {
00608             // Copy tail to current
00609             data[position]=data[dataSize-1];
00610         }
00611         else if (GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
00612         {
00613             DeleteShiftArrayLeft(position);
00614         }
00615         else
00616         {
00617             RakAssert(GetMultilistType()==ML_QUEUE);
00618 
00619             _IndexType index, next;
00620 
00621             if ( queueHead + position >= allocationSize )
00622                 index = queueHead + position - allocationSize;
00623             else
00624                 index = queueHead + position;
00625 
00626             next = index + 1;
00627 
00628             if ( next == allocationSize )
00629                 next = 0;
00630 
00631             while ( next != queueTail )
00632             {
00633                 // Overwrite the previous element
00634                 data[ index ] = data[ next ];
00635                 index = next;
00636                 //next = (next + 1) % allocationSize;
00637 
00638                 if ( ++next == allocationSize )
00639                     next = 0;
00640             }
00641 
00642             // Move the queueTail back
00643             if ( queueTail == 0 )
00644                 queueTail = allocationSize - 1;
00645             else
00646                 --queueTail;
00647         }
00648         
00649         
00650         dataSize--;
00651         DeallocateIfNeeded(file,line);
00652     }
00653 
00654     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00655     bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::RemoveAtKey(_KeyType key, bool assertIfDoesNotExist, const char *file, unsigned int line)
00656     {
00657         _IndexType index = GetIndexOf(key);
00658         if (index==(_IndexType)-1)
00659         {
00660             RakAssert(assertIfDoesNotExist==false && "RemoveAtKey element not found");
00661             return false;
00662         }
00663         RemoveAtIndex(index,file,line);
00664         return true;
00665     }
00666 
00667     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00668     _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetIndexOf(_KeyType key) const
00669     {
00670         _IndexType i;
00671         if (IsSorted())
00672         {
00673             bool objectExists;
00674             i=GetIndexFromKeyInSortedList(key, &objectExists);
00675             if (objectExists)
00676                 return i;
00677             return (_IndexType)-1;
00678         }
00679         else if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
00680         {
00681             for (i=0; i < dataSize; i++)
00682             {
00683                 if (MLKeyRef<_KeyType>(key)==data[i])
00684                     return i;
00685             }
00686             return (_IndexType)-1;
00687         }
00688         else
00689         {
00690             RakAssert( GetMultilistType()==ML_QUEUE );
00691 
00692             for (i=0; i < dataSize; i++)
00693             {
00694                 if (MLKeyRef<_KeyType>(key)==operator[](i))
00695                     return i;
00696             }
00697             return (_IndexType)-1;
00698         }
00699     }
00700 
00701     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00702     _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetInsertionIndex(_KeyType key) const
00703     {
00704         _IndexType i;
00705         if (IsSorted())
00706         {
00707             bool objectExists;
00708             i=GetIndexFromKeyInSortedList(key, &objectExists);
00709             if (objectExists)
00710                 return (_IndexType)-1;
00711             return i;
00712         }
00713         else if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
00714         {
00715             for (i=0; i < dataSize; i++)
00716             {
00717                 if (MLKeyRef<_KeyType>(key)==data[i])
00718                     return (_IndexType)-1;
00719             }
00720             return dataSize;
00721         }
00722         else
00723         {
00724             RakAssert( GetMultilistType()==ML_QUEUE );
00725 
00726             for (i=0; i < dataSize; i++)
00727             {
00728                 if (MLKeyRef<_KeyType>(key)==operator[](i))
00729                     return (_IndexType)-1;
00730             }
00731             return dataSize;
00732         }
00733     }
00734 
00735     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00736     _DataType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetPtr(_KeyType key) const
00737     {
00738         _IndexType i = GetIndexOf(key);
00739         if (i==(_IndexType)-1)
00740             return 0;
00741         return data[i];
00742     }
00743 
00744     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00745     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ForEach(void (*func)(_DataType &item, const char *file, unsigned int line), const char *file, unsigned int line)
00746     {
00747         _IndexType i;
00748         for (i=0; i < dataSize; i++)
00749             func(operator[](i), file, line);
00750     }
00751 
00752     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00753     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ForEach(void (*func)(_DataType &item))
00754     {
00755         _IndexType i;
00756         for (i=0; i < dataSize; i++)
00757             func(operator[](i));
00758     }
00759 
00760     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00761     bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::IsEmpty(void) const
00762     {
00763         return dataSize==0;
00764     }
00765 
00766     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00767     _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetSize(void) const
00768     {
00769         return dataSize;
00770     }
00771 
00772     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00773     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Clear( bool deallocateSmallBlocks, const char *file, unsigned int line )
00774     {
00775         dataSize=0;
00776         if (GetMultilistType()==ML_ORDERED_LIST)
00777             if (ascendingSort)
00778                 sortState=ML_SORTED_ASCENDING;
00779             else
00780                 sortState=ML_SORTED_DESCENDING;
00781         else
00782             sortState=ML_UNSORTED;
00783         queueHead=0;
00784         queueTail=0;
00785 
00786         if (deallocateSmallBlocks && allocationSize < 128 && data)
00787         {
00788             RakNet::OP_DELETE_ARRAY(data,file,line);
00789             data=0;
00790             allocationSize=0;
00791         }
00792     }
00793 
00794     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00795     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ClearPointers( bool deallocateSmallBlocks, const char *file, unsigned int line )
00796     {
00797         _IndexType i;
00798         for (i=0; i < dataSize; i++)
00799             RakNet::OP_DELETE(operator[](i), file, line);
00800         Clear(deallocateSmallBlocks, file, line);
00801     }
00802 
00803     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00804     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ClearPointer( _KeyType key, const char *file, unsigned int line )
00805     {
00806         _IndexType i;
00807         i = GetIndexOf(key);
00808         if (i!=-1)
00809         {
00810             RakNet::OP_DELETE(operator[](i), file, line);
00811             RemoveAtIndex(i);
00812         }
00813     }
00814 
00815     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00816     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReverseList(void)
00817     {
00818         if (IsSorted())
00819             ascendingSort=!ascendingSort;
00820 
00821         ReverseListInternal();
00822     }
00823 
00824     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00825     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Reallocate(_IndexType size, const char *file, unsigned int line)
00826     {
00827         _IndexType newAllocationSize;
00828         if (size < dataSize)
00829             newAllocationSize=dataSize;
00830         else
00831             newAllocationSize=size;
00832         preallocationSize=size;
00833         ReallocToSize(newAllocationSize,file,line);
00834     }
00835 
00836     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00837     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Sort(bool force)
00838     {
00839         if (IsSorted() && force==false)
00840             return;
00841 
00842         if (dataSize>1)
00843         {
00844             if (ascendingSort)
00845                 QSortAscending(0,dataSize-1);       
00846             else
00847                 QSortDescending(0,dataSize-1);
00848         }
00849 
00850         TagSorted();
00851     }
00852 
00853     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00854     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::TagSorted(void)
00855     {
00856         if (ascendingSort)
00857             sortState=ML_SORTED_ASCENDING;
00858         else
00859             sortState=ML_SORTED_DESCENDING;
00860     }
00861 
00862     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00863     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::QSortAscending(_IndexType leftEdge, _IndexType rightEdge)
00864     {
00865         _DataType temp;
00866         _IndexType left=leftEdge;
00867         _IndexType right=rightEdge;
00868         _IndexType pivotIndex=left++;
00869 
00870         while (left<right)
00871         {
00872             if (data[left] <= data[pivotIndex])
00873             {
00874                 ++left;
00875             }
00876             else
00877             {
00878                 temp=data[left];
00879                 data[left]=data[right];
00880                 data[right]=temp;
00881                 --right;
00882             }
00883         }
00884 
00885         temp=data[pivotIndex];
00886 
00887         // Move pivot to center
00888         if (data[left] > data[pivotIndex])
00889         {
00890             --left;
00891 
00892             data[pivotIndex]=data[left];
00893             data[left]=temp;
00894         }
00895         else
00896         {
00897             data[pivotIndex]=data[left];
00898             data[left]=temp;
00899 
00900             --left;
00901         }
00902 
00903         if (left!=leftEdge)
00904             QSortAscending(leftEdge, left);
00905 
00906         if (right!=rightEdge)
00907             QSortAscending(right, rightEdge);       
00908     }
00909 
00910     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00911     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::QSortDescending(_IndexType leftEdge, _IndexType rightEdge)
00912     {
00913         _DataType temp;
00914         _IndexType left=leftEdge;
00915         _IndexType right=rightEdge;
00916         _IndexType pivotIndex=left++;
00917 
00918         while (left<right)
00919         {
00920             if (data[left] >= data[pivotIndex])
00921             {
00922                 ++left;
00923             }
00924             else
00925             {
00926                 temp=data[left];
00927                 data[left]=data[right];
00928                 data[right]=temp;
00929                 --right;
00930             }
00931         }
00932 
00933         temp=data[pivotIndex];
00934 
00935         // Move pivot to center
00936         if (data[left] < data[pivotIndex])
00937         {
00938             --left;
00939 
00940             data[pivotIndex]=data[left];
00941             data[left]=temp;
00942         }
00943         else
00944         {
00945             data[pivotIndex]=data[left];
00946             data[left]=temp;
00947 
00948             --left;
00949         }
00950 
00951         if (left!=leftEdge)
00952             QSortDescending(leftEdge, left);
00953 
00954         if (right!=rightEdge)
00955             QSortDescending(right, rightEdge);      
00956     }
00957 
00958     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00959     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::SetSortOrder(bool ascending)
00960     {
00961         if (ascendingSort!=ascending && IsSorted())
00962         {
00963             ascendingSort=ascending;
00964             // List is sorted, and the sort order has changed. So reverse the list
00965             ReverseListInternal();
00966         }
00967         else
00968             ascendingSort=ascending;
00969     }
00970 
00971     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00972     bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetSortOrder(void) const
00973     {
00974         return ascendingSort;
00975     }
00976 
00977     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00978     bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::IsSorted(void) const
00979     {
00980         return GetMultilistType()==ML_ORDERED_LIST || sortState!=ML_UNSORTED;
00981     }
00982 
00983     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00984     MultilistType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetMultilistType(void) const
00985     {
00986         if (_MultilistType==ML_VARIABLE_DURING_RUNTIME)
00987             return variableMultilistType;
00988         return _MultilistType;
00989     }
00990 
00991     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
00992     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::SetMultilistType(MultilistType newType)
00993     {
00994         RakAssert(_MultilistType==ML_VARIABLE_DURING_RUNTIME);
00995         switch (variableMultilistType)
00996         {
00997         case ML_UNORDERED_LIST:
00998             switch (newType)
00999             {
01000             case ML_UNORDERED_LIST:
01001                 // No change
01002                 break;
01003             case ML_STACK:
01004                 // Same data format
01005                 break;
01006             case ML_QUEUE:
01007                 queueHead=0;
01008                 queueTail=dataSize;
01009                 break;
01010             case ML_ORDERED_LIST:
01011                 Sort(false);
01012                 break;
01013             }
01014             break;
01015         case ML_STACK:
01016             switch (newType)
01017             {
01018             case ML_UNORDERED_LIST:
01019                 // Same data format
01020                 break;
01021             case ML_STACK:
01022                 // No change
01023                 break;
01024             case ML_QUEUE:
01025                 queueHead=0;
01026                 queueTail=dataSize;
01027                 break;
01028             case ML_ORDERED_LIST:
01029                 Sort(false);
01030                 break;
01031             }
01032             break;
01033         case ML_QUEUE:
01034             switch (newType)
01035             {
01036             case ML_UNORDERED_LIST:
01037             case ML_STACK:
01038             case ML_ORDERED_LIST:
01039                 if (queueTail < queueHead)
01040                 {
01041                     // Realign data if wrapped
01042                     ReallocToSize(dataSize, _FILE_AND_LINE_);
01043                 }
01044                 else
01045                 {
01046                     // Else can just copy starting at head
01047                     _IndexType i;
01048                     for (i=0; i < dataSize; i++)
01049                         data[i]=operator[](i);
01050                 }
01051                 if (newType==ML_ORDERED_LIST)
01052                     Sort(false);
01053                 break;
01054             case ML_QUEUE:
01055                 // No change
01056                 break;
01057             }
01058             break;
01059         case ML_ORDERED_LIST:
01060             switch (newType)
01061             {
01062             case ML_UNORDERED_LIST:
01063             case ML_STACK:
01064             case ML_QUEUE:
01065                 // Same data format
01066                 // Tag as sorted
01067                 if (ascendingSort)
01068                     sortState=ML_SORTED_ASCENDING;
01069                 else
01070                     sortState=ML_SORTED_DESCENDING;
01071                 if (newType==ML_QUEUE)
01072                 {
01073                     queueHead=0;
01074                     queueTail=dataSize;
01075                 }
01076                 break;
01077             case ML_ORDERED_LIST:
01078                 // No change
01079                 break;
01080             }
01081             break;
01082         }
01083 
01084         variableMultilistType=newType;
01085     }
01086 
01087     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01088     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::FindIntersection(
01089         Multilist& source1,
01090         Multilist& source2, 
01091         Multilist& intersection,
01092         Multilist& uniqueToSource1,
01093         Multilist& uniqueToSource2)
01094     {
01095         _IndexType index1=0, index2=0;
01096         source1.SetSortOrder(true);
01097         source2.SetSortOrder(true);
01098         source1.Sort(false);
01099         source2.Sort(false);
01100         intersection.Clear(true,_FILE_AND_LINE_);
01101         uniqueToSource1.Clear(true,_FILE_AND_LINE_);
01102         uniqueToSource2.Clear(true,_FILE_AND_LINE_);
01103         
01104         while (index1 < source1.GetSize() && index2 < source2.GetSize())
01105         {
01106             if (source1[index1]<source2[index2])
01107             {
01108                 uniqueToSource1.Push(source1[index1],_FILE_AND_LINE_);
01109                 index1++;
01110             }
01111             else if (source1[index1]==source2[index2])
01112             {
01113                 intersection.Push(source1[index1],_FILE_AND_LINE_);
01114                 index1++;
01115                 index2++;
01116             }
01117             else
01118             {
01119                 uniqueToSource2.Push(source2[index2],_FILE_AND_LINE_);
01120                 index2++;
01121             }
01122         }
01123         while (index1 < source1.GetSize())
01124         {
01125             uniqueToSource1.Push(source1[index1],_FILE_AND_LINE_);
01126             index1++;
01127         }
01128         while (index2 < source2.GetSize())
01129         {
01130             uniqueToSource2.Push(source2[index2],_FILE_AND_LINE_);
01131             index2++;
01132         }
01133     }
01134 
01135     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01136     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReallocateIfNeeded(const char *file, unsigned int line)
01137     {
01138         if (dataSize<allocationSize)
01139             return;
01140 
01141         _IndexType newAllocationSize;
01142         if (allocationSize<16)
01143             newAllocationSize=32;
01144         else if (allocationSize>65536)
01145             newAllocationSize=allocationSize+65536;
01146         else
01147         {
01148             newAllocationSize=allocationSize<<1; // * 2
01149             // Protect against underflow
01150             if (newAllocationSize < allocationSize)
01151                 newAllocationSize=allocationSize+65536;
01152         }
01153 
01154         ReallocToSize(newAllocationSize,file,line);
01155     }
01156 
01157     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01158     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::DeallocateIfNeeded(const char *file, unsigned int line)
01159     {
01160         if (allocationSize<512)
01161             return;
01162         if (dataSize >= allocationSize/3 )
01163             return;
01164         if (dataSize <= preallocationSize )
01165             return;
01166         
01167         _IndexType newAllocationSize = dataSize<<1; // * 2
01168 
01169         ReallocToSize(newAllocationSize,file,line);
01170     }
01171 
01172     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01173     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReallocToSize(_IndexType newAllocationSize, const char *file, unsigned int line)
01174     {
01175         _DataType* newData = RakNet::OP_NEW_ARRAY<_DataType>(newAllocationSize,file,line);
01176         _IndexType i;
01177         for (i=0; i < dataSize; i++)
01178             newData[i]=operator[](i);
01179         if (dataSize>0)
01180         {
01181             RakNet::OP_DELETE_ARRAY(data,file,line);
01182             if (GetMultilistType()==ML_QUEUE)
01183             {
01184                 queueHead=0;
01185                 queueTail=dataSize;
01186             }
01187         }
01188         data=newData;
01189         allocationSize=newAllocationSize;
01190     }
01191 
01192     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01193     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReverseListInternal(void)
01194     {
01195         _DataType temp;
01196         _IndexType i;
01197         for (i=0; i < dataSize/2; i++)
01198         {
01199             temp=operator[](i);
01200             operator[](i)=operator[](dataSize-1-i);
01201             operator[](dataSize-1-i)=temp;
01202         }
01203     }
01204 
01205     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01206     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertInOrderedList(const _DataType &d, const _KeyType &key)
01207     {
01208         RakAssert(GetMultilistType()==ML_ORDERED_LIST);
01209 
01210         bool objectExists;
01211         _IndexType index;
01212         index = GetIndexFromKeyInSortedList(key, &objectExists);
01213 
01214     //  if (objectExists)
01215     //  {
01216             // Ordered list only allows unique insertions
01217     //      RakAssert("Duplicate insertion into ordered list" && false);
01218     //      return;
01219     //  }
01220 
01221         if (index>=dataSize)
01222         {
01223             // insert at end
01224             data[dataSize]=d;
01225             dataSize++;
01226         }
01227         else
01228         {
01229             // insert at index
01230             InsertShiftArrayRight(d,index);
01231         }
01232     }
01233 
01234     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01235     _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetIndexFromKeyInSortedList(const _KeyType &key, bool *objectExists) const
01236     {
01237         RakAssert(IsSorted());
01238         _IndexType index, upperBound, lowerBound;
01239 
01240         if (dataSize==0)
01241         {
01242             *objectExists=false;
01243             return 0;
01244         }
01245 
01246         upperBound=dataSize-1;
01247         lowerBound=0;
01248         index = dataSize/2;
01249 
01250 #ifdef _MSC_VER
01251     #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
01252 #endif
01253         while (1)
01254         {
01255             if (MLKeyRef<_KeyType>(key) > operator[](index) )
01256             {
01257                 if (ascendingSort)
01258                     lowerBound=index+1;
01259                 else
01260                     upperBound=index-1;
01261             }
01262             else if (MLKeyRef<_KeyType>(key) < operator[](index) )
01263             {
01264                 if (ascendingSort)
01265                     upperBound=index-1;
01266                 else
01267                     lowerBound=index+1;
01268             }
01269             else
01270             {
01271                 // ==
01272                 *objectExists=true;
01273                 return index;
01274             }
01275 
01276             index=lowerBound+(upperBound-lowerBound)/2;
01277 
01278             if (lowerBound>upperBound || upperBound==(_IndexType)-1)
01279             {
01280                 *objectExists=false;
01281                 return lowerBound; // No match
01282             }
01283         }
01284     }
01285 
01286     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01287     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertShiftArrayRight(const _DataType &d, _IndexType index)
01288     {
01289         RakAssert(_MultilistType!=ML_QUEUE);
01290 
01291         // Move the elements in the list to make room
01292         _IndexType i;
01293         for ( i = dataSize; i != index; i-- )
01294             data[ i ] = data[ i - 1 ];
01295 
01296         // Insert the new item at the correct spot
01297         data[ index ] = d;
01298 
01299         ++dataSize;
01300     }
01301 
01302     template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
01303     void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::DeleteShiftArrayLeft( _IndexType index )
01304     {
01305         RakAssert(index < dataSize);
01306         RakAssert(_MultilistType!=ML_QUEUE);
01307 
01308         _IndexType i;
01309         for ( i = index; i < dataSize-1; i++ )
01310             data[i]=data[i+1];
01311     }
01312 };
01313 
01314 /*
01315 struct KeyAndValue
01316 {
01317     int key;
01318     short value;
01319 };
01320 
01321 DEFINE_MULTILIST_PTR_TO_MEMBER_COMPARISONS(KeyAndValue,int,key)
01322 
01323 void MultilistUnitTest(void)
01324 {
01325     DataStructures::DefaultIndexType oldSize;
01326     DataStructures::Multilist<ML_UNORDERED_LIST, int> ml1;
01327     ml1.Reallocate(64);
01328     RakAssert(ml1.IsEmpty());
01329     ml1.Push(53);
01330     RakAssert(ml1.Peek()==53);
01331     RakAssert(ml1.IsEmpty()==false);
01332     RakAssert(ml1.Pop()==53);
01333     RakAssert(ml1.IsEmpty()==true);
01334     for (int i=0; i < 512; i++)
01335     ml1.Push(i);
01336     RakAssert(ml1.GetIndexOf(200)==200);
01337     RakAssert(ml1.PeekOpposite()==0);
01338     RakAssert(ml1.PopOpposite()==0);
01339     RakAssert(ml1.PeekOpposite()==1);
01340     RakAssert(ml1.Peek()==511);
01341     ml1.ReverseList();
01342     for (int i=0; i < 511; i++)
01343     RakAssert(ml1[i]==511-i);
01344     RakAssert(ml1.PeekOpposite()==511);
01345     RakAssert(ml1.Peek()==1);
01346     oldSize = ml1.GetSize();
01347     ml1.RemoveAtIndex(0);
01348     RakAssert(ml1.GetSize()==oldSize-1);
01349     RakAssert(ml1.PeekOpposite()==1);
01350     ml1.Clear(_FILE_AND_LINE_);
01351     RakAssert(ml1.IsEmpty()==true);
01352 
01353     ml1.Sort(true);
01354     ml1.Clear(_FILE_AND_LINE_);
01355 
01356     ml1.Push(100);
01357     ml1.Sort(true);
01358     ml1.Clear(_FILE_AND_LINE_);
01359 
01360     ml1.Push(50);
01361     ml1.Push(100);
01362     ml1.Sort(true);
01363     ml1.Clear(_FILE_AND_LINE_);
01364 
01365     ml1.Push(100);
01366     ml1.Push(50);
01367     ml1.Sort(true);
01368     ml1.Clear(_FILE_AND_LINE_);
01369 
01370     ml1.Push(100);
01371     ml1.Push(50);
01372     ml1.Push(150);
01373     ml1.Push(25);
01374     ml1.Push(175);
01375     ml1.Sort(true);
01376     RakAssert(ml1[0]==25);
01377     RakAssert(ml1[1]==50);
01378     RakAssert(ml1[2]==100);
01379     RakAssert(ml1[3]==150);
01380     RakAssert(ml1[4]==175);
01381     RakAssert(ml1.GetIndexOf(25)==0);
01382     RakAssert(ml1.GetIndexOf(50)==1);
01383     RakAssert(ml1.GetIndexOf(100)==2);
01384     RakAssert(ml1.GetIndexOf(150)==3);
01385     RakAssert(ml1.GetIndexOf(175)==4);
01386     ml1.Clear(_FILE_AND_LINE_);
01387 
01388     ml1.Push(1);
01389     ml1.Push(2);
01390     ml1.Push(3);
01391     ml1.Push(4);
01392     ml1.Push(5);
01393     ml1.Sort(true);
01394     RakAssert(ml1[0]==1);
01395     RakAssert(ml1[1]==2);
01396     RakAssert(ml1[2]==3);
01397     RakAssert(ml1[3]==4);
01398     RakAssert(ml1[4]==5);
01399     RakAssert(ml1.GetIndexOf(1)==0);
01400     RakAssert(ml1.GetIndexOf(2)==1);
01401     RakAssert(ml1.GetIndexOf(3)==2);
01402     RakAssert(ml1.GetIndexOf(4)==3);
01403     RakAssert(ml1.GetIndexOf(5)==4);
01404     ml1.Clear(_FILE_AND_LINE_);
01405 
01406     ml1.Push(5);
01407     ml1.Push(4);
01408     ml1.Push(3);
01409     ml1.Push(2);
01410     ml1.Push(1);
01411     ml1.Sort(true);
01412     RakAssert(ml1[0]==1);
01413     RakAssert(ml1[1]==2);
01414     RakAssert(ml1[2]==3);
01415     RakAssert(ml1[3]==4);
01416     RakAssert(ml1[4]==5);
01417     RakAssert(ml1.GetIndexOf(1)==0);
01418     RakAssert(ml1.GetIndexOf(2)==1);
01419     RakAssert(ml1.GetIndexOf(3)==2);
01420     RakAssert(ml1.GetIndexOf(4)==3);
01421     RakAssert(ml1.GetIndexOf(5)==4);
01422     ml1.Sort(true);
01423     RakAssert(ml1[0]==1);
01424     RakAssert(ml1[1]==2);
01425     RakAssert(ml1[2]==3);
01426     RakAssert(ml1[3]==4);
01427     RakAssert(ml1[4]==5);
01428     RakAssert(ml1.GetIndexOf(1)==0);
01429     RakAssert(ml1.GetIndexOf(2)==1);
01430     RakAssert(ml1.GetIndexOf(3)==2);
01431     RakAssert(ml1.GetIndexOf(4)==3);
01432     RakAssert(ml1.GetIndexOf(5)==4);
01433     ml1.Clear(_FILE_AND_LINE_);
01434 
01435     DataStructures::Multilist<ML_STACK, int> ml2;
01436     ml2.Reallocate(64);
01437     RakAssert(ml2.IsEmpty());
01438     ml2.Push(53);
01439     RakAssert(ml2.Peek()==53);
01440     RakAssert(ml2.IsEmpty()==false);
01441     RakAssert(ml2.Pop()==53);
01442     RakAssert(ml2.IsEmpty()==true);
01443     for (int i=0; i < 512; i++)
01444     ml2.Push(i);
01445     RakAssert(ml2.GetIndexOf(200)==200);
01446     RakAssert(ml2.PeekOpposite()==0);
01447     RakAssert(ml2.PopOpposite()==0);
01448     RakAssert(ml2.PeekOpposite()==1);
01449     RakAssert(ml2.Peek()==511);
01450     ml2.ReverseList();
01451     for (int i=0; i < 511; i++)
01452     RakAssert(ml2[i]==511-i);
01453     RakAssert(ml2.PeekOpposite()==511);
01454     RakAssert(ml2.Peek()==1);
01455     oldSize = ml2.GetSize();
01456     ml2.RemoveAtIndex(0);
01457     RakAssert(ml2.GetSize()==oldSize-1);
01458     RakAssert(ml2.Peek()==1);
01459     RakAssert(ml2.PeekOpposite()==510);
01460     ml2.Clear(_FILE_AND_LINE_);
01461     RakAssert(ml2.IsEmpty()==true);
01462 
01463     DataStructures::Multilist<ML_QUEUE, int> ml3;
01464     RakAssert(ml3.IsEmpty());
01465     ml3.Push(53);
01466     RakAssert(ml3.Peek()==53);
01467     RakAssert(ml3.IsEmpty()==false);
01468     RakAssert(ml3.Pop()==53);
01469     RakAssert(ml3.IsEmpty()==true);
01470     for (int i=0; i < 512; i++)
01471     ml3.Push(i);
01472     RakAssert(ml3.GetIndexOf(200)==200);
01473     RakAssert(ml3.PeekOpposite()==511);
01474     RakAssert(ml3.PopOpposite()==511);
01475     RakAssert(ml3.PeekOpposite()==510);
01476     RakAssert(ml3.Peek()==0);
01477     ml3.ReverseList();
01478     for (int i=0; i < 511; i++)
01479     RakAssert(ml3[i]==511-1-i);
01480     RakAssert(ml3.PeekOpposite()==0);
01481     RakAssert(ml3.Peek()==510);
01482     oldSize = ml3.GetSize();
01483     ml3.RemoveAtIndex(0);
01484     RakAssert(ml3.GetSize()==oldSize-1);
01485     RakAssert(ml3.Peek()==509);
01486     RakAssert(ml3.PeekOpposite()==0);
01487     ml3.Clear(_FILE_AND_LINE_);
01488     RakAssert(ml3.IsEmpty()==true);
01489 
01490     ml3.PushOpposite(100);
01491     ml3.PushOpposite(50);
01492     ml3.PushOpposite(150);
01493     ml3.PushOpposite(25);
01494     ml3.PushOpposite(175);
01495     ml3.Sort(true);
01496     RakAssert(ml3[0]==25);
01497     RakAssert(ml3[1]==50);
01498     RakAssert(ml3[2]==100);
01499     RakAssert(ml3[3]==150);
01500     RakAssert(ml3[4]==175);
01501     RakAssert(ml3.GetIndexOf(25)==0);
01502     RakAssert(ml3.GetIndexOf(50)==1);
01503     RakAssert(ml3.GetIndexOf(100)==2);
01504     RakAssert(ml3.GetIndexOf(150)==3);
01505     RakAssert(ml3.GetIndexOf(175)==4);
01506     ml3.Clear(_FILE_AND_LINE_);
01507 
01508     ml3.PushOpposite(1);
01509     ml3.PushOpposite(2);
01510     ml3.PushOpposite(3);
01511     ml3.PushOpposite(4);
01512     ml3.PushOpposite(5);
01513     ml3.Sort(true);
01514     RakAssert(ml3[0]==1);
01515     RakAssert(ml3[1]==2);
01516     RakAssert(ml3[2]==3);
01517     RakAssert(ml3[3]==4);
01518     RakAssert(ml3[4]==5);
01519     RakAssert(ml3.GetIndexOf(1)==0);
01520     RakAssert(ml3.GetIndexOf(2)==1);
01521     RakAssert(ml3.GetIndexOf(3)==2);
01522     RakAssert(ml3.GetIndexOf(4)==3);
01523     RakAssert(ml3.GetIndexOf(5)==4);
01524     ml3.Clear(_FILE_AND_LINE_);
01525 
01526     ml3.PushOpposite(5);
01527     ml3.PushOpposite(4);
01528     ml3.PushOpposite(3);
01529     ml3.PushOpposite(2);
01530     ml3.PushOpposite(1);
01531     ml3.Sort(true);
01532     RakAssert(ml3[0]==1);
01533     RakAssert(ml3[1]==2);
01534     RakAssert(ml3[2]==3);
01535     RakAssert(ml3[3]==4);
01536     RakAssert(ml3[4]==5);
01537     RakAssert(ml3.GetIndexOf(1)==0);
01538     RakAssert(ml3.GetIndexOf(2)==1);
01539     RakAssert(ml3.GetIndexOf(3)==2);
01540     RakAssert(ml3.GetIndexOf(4)==3);
01541     RakAssert(ml3.GetIndexOf(5)==4);
01542     ml3.Sort(true);
01543     RakAssert(ml3[0]==1);
01544     RakAssert(ml3[1]==2);
01545     RakAssert(ml3[2]==3);
01546     RakAssert(ml3[3]==4);
01547     RakAssert(ml3[4]==5);
01548     RakAssert(ml3.GetIndexOf(1)==0);
01549     RakAssert(ml3.GetIndexOf(2)==1);
01550     RakAssert(ml3.GetIndexOf(3)==2);
01551     RakAssert(ml3.GetIndexOf(4)==3);
01552     RakAssert(ml3.GetIndexOf(5)==4);
01553 
01554     ml3.SetSortOrder(false);
01555     ml3.Sort(false);
01556     RakAssert(ml3[0]==5);
01557     RakAssert(ml3[1]==4);
01558     RakAssert(ml3[2]==3);
01559     RakAssert(ml3[3]==2);
01560     RakAssert(ml3[4]==1);
01561     RakAssert(ml3.GetIndexOf(1)==4);
01562     RakAssert(ml3.GetIndexOf(2)==3);
01563     RakAssert(ml3.GetIndexOf(3)==2);
01564     RakAssert(ml3.GetIndexOf(4)==1);
01565     RakAssert(ml3.GetIndexOf(5)==0);
01566 
01567     ml3.Clear(_FILE_AND_LINE_);
01568 
01569     DataStructures::Multilist<ML_ORDERED_LIST, int> ml4;
01570     ml4.Reallocate(64);
01571     RakAssert(ml4.IsEmpty());
01572     ml4.Push(53);
01573     RakAssert(ml4.Peek()==53);
01574     RakAssert(ml4.IsEmpty()==false);
01575     RakAssert(ml4.Pop()==53);
01576     RakAssert(ml4.IsEmpty()==true);
01577     for (int i=0; i < 512; i++)
01578     ml4.Push(i);
01579     RakAssert(ml4.GetIndexOf(200)==200);
01580     RakAssert(ml4.PeekOpposite()==0);
01581     RakAssert(ml4.PopOpposite()==0);
01582     RakAssert(ml4.PeekOpposite()==1);
01583     RakAssert(ml4.Peek()==511);
01584     ml4.ReverseList();
01585     for (int i=0; i < 511; i++)
01586     RakAssert(ml4[i]==511-i);
01587     RakAssert(ml4.PeekOpposite()==511);
01588     RakAssert(ml4.Peek()==1);
01589     oldSize = ml4.GetSize();
01590     ml4.RemoveAtIndex(0);
01591     RakAssert(ml4.GetSize()==oldSize-1);
01592     RakAssert(ml4.Peek()==1);
01593     RakAssert(ml4.PeekOpposite()==510);
01594     ml4.Clear(_FILE_AND_LINE_);
01595     RakAssert(ml4.IsEmpty()==true);
01596 
01597     DataStructures::Multilist<ML_ORDERED_LIST, KeyAndValue*, int> ml5;
01598 
01599     for (int i=0; i < 16; i++)
01600     {
01601         KeyAndValue *kav = new KeyAndValue;
01602         kav->key=i;
01603         kav->value=i+100;
01604         ml5.Push(kav,kav->key);
01605     }
01606 
01607     RakAssert(ml5.GetIndexOf(0)==0);
01608     RakAssert(ml5.GetIndexOf(5)==5);
01609     RakAssert(ml5.GetIndexOf(15)==15);
01610     RakAssert(ml5.GetIndexOf(16)==-1);
01611     ml5.RemoveAtKey(0,true);
01612     RakAssert(ml5.GetIndexOf(1)==0);
01613     KeyAndValue *iPtr = ml5.GetPtr(5);
01614     RakAssert(iPtr);
01615     RakAssert(iPtr->value=105);
01616     iPtr = ml5.GetPtr(1234);
01617     RakAssert(iPtr==0);
01618     ml5.ForEach(DataStructures::DeletePtr<KeyAndValue*>);
01619 
01620 
01621     DataStructures::Multilist<ML_VARIABLE_DURING_RUNTIME, int> ml6;
01622     ml6.Push(2);
01623     ml6.Push(1);
01624     ml6.Push(6);
01625     ml6.Push(3);
01626     RakAssert(ml6.Peek()==3);
01627     ml6.SetMultilistType(ML_STACK);
01628     RakAssert(ml6.Peek()==3);
01629     ml6.SetMultilistType(ML_QUEUE);
01630     RakAssert(ml6.Peek()==2);
01631     ml6.SetMultilistType(ML_ORDERED_LIST);
01632     RakAssert(ml6.Peek()=6);
01633     ml6.SetMultilistType(ML_STACK);
01634     RakAssert(ml6.Peek()==6);
01635     ml6.SetMultilistType(ML_QUEUE);
01636     RakAssert(ml6.Peek()==1);
01637 }
01638 
01639 #ifdef _MSC_VER
01640 #pragma warning( pop )
01641 #endif
01642 */
01643 
01644 #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