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>
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
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__, __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__,__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
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
00440 if (GetMultilistType()==ML_UNORDERED_LIST)
00441 {
00442 data[dataSize]=d;
00443 dataSize++;
00444 }
00445 else if (GetMultilistType()==ML_STACK)
00446 {
00447
00448 InsertAtIndex(d,0,file,line);
00449 }
00450 else if (GetMultilistType()==ML_QUEUE)
00451 {
00452
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
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
00487 ReallocateIfNeeded(file,line);
00488 data[dataSize]=data[0];
00489 DeleteShiftArrayLeft(0);
00490 --dataSize;
00491
00492 DeallocateIfNeeded(file,line);
00493
00494 return data[dataSize+1];
00495 }
00496 else
00497 {
00498 RakAssert(GetMultilistType()==ML_QUEUE);
00499
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
00543 data[dataSize]=d;
00544
00545 dataSize++;
00546 }
00547 else
00548 {
00549
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
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
00634 data[ index ] = data[ next ];
00635 index = next;
00636
00637
00638 if ( ++next == allocationSize )
00639 next = 0;
00640 }
00641
00642
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
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
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
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
01002 break;
01003 case ML_STACK:
01004
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
01020 break;
01021 case ML_STACK:
01022
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
01042 ReallocToSize(dataSize, __FILE__, __LINE__);
01043 }
01044 else
01045 {
01046
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
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
01066
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
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__, __LINE__);
01101 uniqueToSource1.Clear(true,__FILE__, __LINE__);
01102 uniqueToSource2.Clear(true,__FILE__, __LINE__);
01103
01104 while (index1 < source1.GetSize() && index2 < source2.GetSize())
01105 {
01106 if (source1[index1]<source2[index2])
01107 {
01108 uniqueToSource1.Push(source1[index1],__FILE__,__LINE__);
01109 index1++;
01110 }
01111 else if (source1[index1]==source2[index2])
01112 {
01113 intersection.Push(source1[index1],__FILE__,__LINE__);
01114 index1++;
01115 index2++;
01116 }
01117 else
01118 {
01119 uniqueToSource2.Push(source2[index2],__FILE__,__LINE__);
01120 index2++;
01121 }
01122 }
01123 while (index1 < source1.GetSize())
01124 {
01125 uniqueToSource1.Push(source1[index1],__FILE__,__LINE__);
01126 index1++;
01127 }
01128 while (index2 < source2.GetSize())
01129 {
01130 uniqueToSource2.Push(source2[index2],__FILE__,__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;
01149
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;
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
01215
01216
01217
01218
01219
01220
01221 if (index>=dataSize)
01222 {
01223
01224 data[dataSize]=d;
01225 dataSize++;
01226 }
01227 else
01228 {
01229
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;
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
01292 _IndexType i;
01293 for ( i = dataSize; i != index; i-- )
01294 data[ i ] = data[ i - 1 ];
01295
01296
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
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644 #endif