| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- /// \file DS_Multilist.h
- /// \internal
- /// \brief ADT that can represent an unordered list, ordered list, stack, or queue with a common interface
- ///
- #ifndef __MULTILIST_H
- #define __MULTILIST_H
- #include "RakAssert.h"
- #include <string.h> // memmove
- #include "Export.h"
- #include "RakMemoryOverride.h"
- #include "NativeTypes.h"
- #ifdef _MSC_VER
- #pragma warning( push )
- #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
- #pragma warning( disable : 4512 ) // warning C4512: assignment operator could not be generated
- #endif
- /// What algorithm to use to store the data for the Multilist
- enum MultilistType
- {
- /// Removing from the middle of the list will swap the end of the list rather than shift the elements. Push and Pop operate on the tail.
- ML_UNORDERED_LIST,
- /// A normal list, with the list order preserved. Push and Pop operate on the tail.
- ML_STACK,
- /// A queue. Push and Pop operate on the head
- ML_QUEUE,
- /// A list that is always kept in order. Elements must be unique, and compare against each other consistently using <, ==, and >
- ML_ORDERED_LIST,
- /// A list whose type can change at runtime
- ML_VARIABLE_DURING_RUNTIME
- };
- /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
- /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
- namespace DataStructures
- {
- /// Can be used with Multilist::ForEach
- /// Assuming the Multilist holds pointers, will delete those pointers
- template <class templateType>
- void DeletePtr_RakNet(templateType &ptr, const char *file, unsigned int line ) {RakNet::OP_DELETE(ptr, file, line);}
- /// Can be used with Multilist::ForEach
- /// Assuming the Multilist holds pointers, will delete those pointers
- template <class templateType>
- void DeletePtr(templateType &ptr) {delete ptr;}
- /// The following is invalid.
- /// bool operator<( const MyClass *myClass, const int &inputKey ) {return myClass->value < inputKey;}
- /// At least one type has to be a reference to a class
- /// MLKeyRef is a helper class to turn a native type into a class, so you can compare that native type against a pointer to a different class
- /// Used for he Multilist, when _DataType != _KeyType
- template < class templateType >
- class MLKeyRef
- {
- public:
- MLKeyRef(const templateType& input) : val(input) {}
- const templateType &Get(void) const {return val;}
- bool operator<( const templateType &right ) {return val < right;}
- bool operator>( const templateType &right ) {return val > right;}
- bool operator==( const templateType &right ) {return val == right;}
- protected:
- const templateType &val;
- };
- /// For the Multilist, when _DataType != _KeyType, you must define the comparison operators between the key and the data
- /// This is non-trivial due to the need to use MLKeyRef in case the type held is a pointer to a structure or class and the key type is not a class
- /// For convenience, this macro will implement the comparison operators under the following conditions
- /// 1. _DataType is a pointer to a class or structure
- /// 2. The key is a member variable of _DataType
- #define DEFINE_MULTILIST_PTR_TO_MEMBER_COMPARISONS( _CLASS_NAME_, _KEY_TYPE_, _MEMBER_VARIABLE_NAME_ ) \
- bool operator<( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() < cls->_MEMBER_VARIABLE_NAME_;} \
- bool operator>( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() > cls->_MEMBER_VARIABLE_NAME_;} \
- bool operator==( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() == cls->_MEMBER_VARIABLE_NAME_;}
- typedef uint32_t DefaultIndexType;
- /// \brief The multilist, representing an abstract data type that generally holds lists.
- /// \param[in] _MultilistType What type of list this is, \sa MultilistType
- /// \param[in] _DataType What type of data this list holds.
- /// \param[in] _KeyType If a function takes a key to sort on, what type of key this is. The comparison operator between _DataType and _KeyType must be defined
- /// \param[in] _IndexType What variable type to use for indices
- template <const MultilistType _MultilistType, class _DataType, class _KeyType=_DataType, class _IndexType=DefaultIndexType>
- class RAK_DLL_EXPORT Multilist
- {
- public:
- Multilist();
- ~Multilist();
- Multilist( const Multilist& source );
- Multilist& operator= ( const Multilist& source );
- _DataType& operator[] ( const _IndexType position ) const;
- /// Unordered list, stack is LIFO
- /// QUEUE is FIFO
- /// Ordered list is inserted in order
- void Push(const _DataType &d, const char *file=__FILE__, unsigned int line=__LINE__ );
- void Push(const _DataType &d, const _KeyType &key, const char *file=__FILE__, unsigned int line=__LINE__ );
- /// \brief Gets or removes and gets an element from the list, according to the same rules as Push().
- /// Ordered list is LIFO for the purposes of Pop and Peek.
- _DataType &Pop(const char *file=__FILE__, unsigned int line=__LINE__);
- _DataType &Peek(void) const;
- /// \brief Same as Push(), except FIFO and LIFO are reversed.
- /// Ordered list still inserts in order.
- void PushOpposite(const _DataType &d, const char *file=__FILE__, unsigned int line=__LINE__ );
- void PushOpposite(const _DataType &d, const _KeyType &key, const char *file=__FILE__, unsigned int line=__LINE__ );
- /// \brief Same as Pop() and Peek(), except FIFO and LIFO are reversed.
- _DataType &PopOpposite(const char *file=__FILE__, unsigned int line=__LINE__);
- _DataType &PeekOpposite(void) const;
- /// \brief Stack,Queue: Inserts at index indicated, elements are shifted.
- /// Ordered list: Inserts, position is ignored
- void InsertAtIndex(const _DataType &d, _IndexType index, const char *file=__FILE__, unsigned int line=__LINE__);
-
- /// \brief Unordered list, removes at index indicated, swaps last element with that element.
- /// Otherwise, array is shifted left to overwrite removed element
- /// \details Index[0] returns the same as Pop() for a queue.
- /// Same as PopOpposite() for the list and ordered list
- void RemoveAtIndex(_IndexType position, const char *file=__FILE__, unsigned int line=__LINE__);
- /// \brief Find the index of \a key, and remove at that index.
- bool RemoveAtKey(_KeyType key, bool assertIfDoesNotExist, const char *file=__FILE__, unsigned int line=__LINE__);
- /// \brief Finds the index of \a key. Return -1 if the key is not found.
- _IndexType GetIndexOf(_KeyType key) const;
- /// \brief Returns where in the list we should insert the item, to preserve list order.
- /// Returns -1 if the item is already in the list
- _IndexType GetInsertionIndex(_KeyType key) const;
- /// \brief Finds the index of \a key. Return 0 if the key is not found. Useful if _DataType is always non-zero pointers.
- _DataType GetPtr(_KeyType key) const;
- /// \brief Iterate over the list, calling the function pointer on each element.
- void ForEach(void (*func)(_DataType &item, const char *file, unsigned int line), const char *file, unsigned int line);
- void ForEach(void (*func)(_DataType &item));
- /// \brief Returns if the list is empty.
- bool IsEmpty(void) const;
- /// \brief Returns the number of elements used in the list.
- _IndexType GetSize(void) const;
- /// \brief Empties the list. The list is not deallocated if it is small,
- /// unless \a deallocateSmallBlocks is true
- void Clear( bool deallocateSmallBlocks=true, const char *file=__FILE__, unsigned int line=__LINE__ );
- /// \brief Empties the list, first calling RakNet::OP_Delete on all items.
- /// \details The list is not deallocated if it is small, unless \a deallocateSmallBlocks is true
- void ClearPointers( bool deallocateSmallBlocks=true, const char *file=__FILE__, unsigned int line=__LINE__ );
- /// \brief Empty one item from the list, first calling RakNet::OP_Delete on that item.
- void ClearPointer( _KeyType key, const char *file=__FILE__, unsigned int line=__LINE__ );
- /// \brief Reverses the elements in the list, and flips the sort order
- /// returned by GetSortOrder() if IsSorted() returns true at the time the function is called
- void ReverseList(void);
- /// \brief Reallocates the list to a larger size.
- /// If \a size is smaller than the value returned by GetSize(), the call does nothing.
- void Reallocate(_IndexType size, const char *file=__FILE__, unsigned int line=__LINE__);
- /// \brief Sorts the list unless it is an ordered list, in which it does nothing as the list is assumed to already be sorted.
- /// \details However, if \a force is true, it will also resort the ordered list, useful if the comparison operator between _KeyType and _DataType would now return different results
- /// Once the list is sorted, further operations to lookup by key will be log2(n) until the list is modified
- void Sort(bool force);
- /// \brief Sets the list to be remembered as sorted.
- /// \details Optimization if the source is sorted already
- void TagSorted(void);
- /// \brief Defaults to ascending.
- /// \details Used by Sort(), and by ML_ORDERED_LIST
- void SetSortOrder(bool ascending);
- /// \brief Returns true if ascending.
- bool GetSortOrder(void) const;
- /// \brief Returns true if the list is currently believed to be in a sorted state.
- /// \details Doesn't actually check for sortedness, just if Sort()
- /// was recently called, or MultilistType is ML_ORDERED_LIST
- bool IsSorted(void) const;
- /// Returns what type of list this is
- MultilistType GetMultilistType(void) const;
- /// \brief Changes what type of list this is.
- /// \pre Template must be defined with ML_VARIABLE_DURING_RUNTIME for this to do anything
- /// \param[in] mlType Any value of the enum MultilistType, except ML_VARIABLE_DURING_RUNTIME
- void SetMultilistType(MultilistType newType);
- /// \brief Returns the intersection of two lists.
- /// Intersection is items common to both lists.
- static void FindIntersection(
- Multilist& source1,
- Multilist& source2,
- Multilist& intersection,
- Multilist& uniqueToSource1,
- Multilist& uniqueToSource2);
- protected:
- void ReallocateIfNeeded(const char *file, unsigned int line);
- void DeallocateIfNeeded(const char *file, unsigned int line);
- void ReallocToSize(_IndexType newAllocationSize, const char *file, unsigned int line);
- void ReverseListInternal(void);
- void InsertInOrderedList(const _DataType &d, const _KeyType &key);
- _IndexType GetIndexFromKeyInSortedList(const _KeyType &key, bool *objectExists) const;
- void InsertShiftArrayRight(const _DataType &d, _IndexType index);
- void DeleteShiftArrayLeft(_IndexType index);
- void QSortAscending(_IndexType left, _IndexType right);
- void QSortDescending(_IndexType left, _IndexType right);
- void CopySource( const Multilist& source );
- /// An array of user values
- _DataType* data;
-
- /// Number of elements in the list
- _IndexType dataSize;
-
- /// Size of \a array
- _IndexType allocationSize;
- /// Array index for the head of the queue
- _IndexType queueHead;
- /// Array index for the tail of the queue
- _IndexType queueTail;
- /// How many bytes the user chose to preallocate
- /// Won't automatically deallocate below this
- _IndexType preallocationSize;
- enum
- {
- ML_UNSORTED,
- ML_SORTED_ASCENDING,
- ML_SORTED_DESCENDING
- } sortState;
- bool ascendingSort;
- // In case we are using the variable type multilist
- MultilistType variableMultilistType;
- };
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Multilist()
- {
- data=0;
- dataSize=0;
- allocationSize=0;
- ascendingSort=true;
- sortState=ML_UNSORTED;
- queueHead=0;
- queueTail=0;
- preallocationSize=0;
- if (_MultilistType==ML_ORDERED_LIST)
- sortState=ML_SORTED_ASCENDING;
- else
- sortState=ML_UNSORTED;
- if (_MultilistType==ML_VARIABLE_DURING_RUNTIME)
- variableMultilistType=ML_UNORDERED_LIST;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::~Multilist()
- {
- if (data!=0)
- RakNet::OP_DELETE_ARRAY(data, _FILE_AND_LINE_);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Multilist( const Multilist& source )
- {
- CopySource(source);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- Multilist<_MultilistType, _DataType, _KeyType, _IndexType>& Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::operator= ( const Multilist& source )
- {
- Clear(true);
- CopySource(source);
- return *this;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::CopySource( const Multilist& source )
- {
- dataSize=source.GetSize();
- ascendingSort=source.ascendingSort;
- sortState=source.sortState;
- queueHead=0;
- queueTail=dataSize;
- preallocationSize=source.preallocationSize;
- variableMultilistType=source.variableMultilistType;
- if (source.data==0)
- {
- data=0;
- allocationSize=0;
- }
- else
- {
- allocationSize=dataSize;
- data = RakNet::OP_NEW_ARRAY<_DataType>(dataSize,_FILE_AND_LINE_);
- _IndexType i;
- for (i=0; i < dataSize; i++)
- data[i]=source[i];
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _DataType& Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::operator[] ( const _IndexType position ) const
- {
- RakAssert(position<GetSize());
- if (GetMultilistType()==ML_QUEUE)
- {
- if ( queueHead + position >= allocationSize )
- return data[ queueHead + position - allocationSize ];
- else
- return data[ queueHead + position ];
- }
-
- return data[position];
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Push(const _DataType &d, const char *file, unsigned int line )
- {
- Push(d,d,file,line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Push(const _DataType &d, const _KeyType &key, const char *file, unsigned int line )
- {
- ReallocateIfNeeded(file,line);
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
- {
- data[dataSize]=d;
- dataSize++;
- }
- else if (GetMultilistType()==ML_QUEUE)
- {
- data[queueTail++] = d;
- if ( queueTail == allocationSize )
- queueTail = 0;
- dataSize++;
- }
- else
- {
- RakAssert(GetMultilistType()==ML_ORDERED_LIST);
- InsertInOrderedList(d,key);
- }
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_QUEUE)
- {
- // Break sort if no longer sorted
- if (sortState!=ML_UNSORTED && dataSize>1)
- {
- if (ascendingSort)
- {
- if ( MLKeyRef<_KeyType>(key) < operator[](dataSize-2) )
- sortState=ML_UNSORTED;
- }
- else
- {
- if ( MLKeyRef<_KeyType>(key) > operator[](dataSize-2) )
- sortState=ML_UNSORTED;
- }
- sortState=ML_UNSORTED;
- }
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Pop(const char *file, unsigned int line)
- {
- RakAssert(IsEmpty()==false);
- DeallocateIfNeeded(file,line);
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
- {
- dataSize--;
- return data[dataSize];
- }
- else
- {
- RakAssert(GetMultilistType()==ML_QUEUE);
- if ( ++queueHead == allocationSize )
- queueHead = 0;
- if ( queueHead == 0 )
- return data[ allocationSize -1 ];
- dataSize--;
- return data[ queueHead -1 ];
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Peek(void) const
- {
- RakAssert(IsEmpty()==false);
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
- {
- return data[dataSize-1];
- }
- else
- {
- RakAssert(GetMultilistType()==ML_QUEUE);
- return data[ queueHead ];
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PushOpposite(const _DataType &d, const char *file, unsigned int line )
- {
- PushOpposite(d,d,file,line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PushOpposite(const _DataType &d, const _KeyType &key, const char *file, unsigned int line )
- {
- ReallocateIfNeeded(file,line);
- // Unordered list Push at back
- if (GetMultilistType()==ML_UNORDERED_LIST)
- {
- data[dataSize]=d;
- dataSize++;
- }
- else if (GetMultilistType()==ML_STACK)
- {
- // Stack push at front of the list, instead of back as normal
- InsertAtIndex(d,0,file,line);
- }
- else if (GetMultilistType()==ML_QUEUE)
- {
- // Queue push at front of the list, instead of back as normal
- InsertAtIndex(d,0,file,line);
- }
- else
- {
- RakAssert(GetMultilistType()==ML_ORDERED_LIST);
- InsertInOrderedList(d,key);
- }
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_QUEUE)
- {
- // Break sort if no longer sorted
- if (sortState!=ML_UNSORTED && dataSize>1)
- {
- if (ascendingSort)
- {
- if ( MLKeyRef<_KeyType>(key) > operator[](1) )
- sortState=ML_UNSORTED;
- }
- else
- {
- if ( MLKeyRef<_KeyType>(key) < operator[](1) )
- sortState=ML_UNSORTED;
- }
- }
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PopOpposite(const char *file, unsigned int line)
- {
- RakAssert(IsEmpty()==false);
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
- {
- // Copy leftmost to end
- ReallocateIfNeeded(file,line);
- data[dataSize]=data[0];
- DeleteShiftArrayLeft(0);
- --dataSize;
- // Assuming still leaves at least one element past the end of the list allocated
- DeallocateIfNeeded(file,line);
- // Return end
- return data[dataSize+1];
- }
- else
- {
- RakAssert(GetMultilistType()==ML_QUEUE);
- // Deallocate first, since we are returning off the existing list
- DeallocateIfNeeded(file,line);
- dataSize--;
- if (queueTail==0)
- queueTail=allocationSize-1;
- else
- --queueTail;
- return data[queueTail];
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PeekOpposite(void) const
- {
- RakAssert(IsEmpty()==false);
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
- {
- return data[0];
- }
- else
- {
- RakAssert(GetMultilistType()==ML_QUEUE);
- _IndexType priorIndex;
- if (queueTail==0)
- priorIndex=allocationSize-1;
- else
- priorIndex=queueTail-1;
- return data[priorIndex];
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertAtIndex(const _DataType &d, _IndexType index, const char *file, unsigned int line)
- {
- ReallocateIfNeeded(file,line);
- if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
- {
- if (index>=dataSize)
- {
- // insert at end
- data[dataSize]=d;
- dataSize++;
- }
- else
- {
- // insert at index
- InsertShiftArrayRight(d,index);
- }
- }
- else
- {
- data[queueTail++] = d;
- if ( queueTail == allocationSize )
- queueTail = 0;
- ++dataSize;
- if (dataSize==1)
- return;
- _IndexType writeIndex, readIndex, trueWriteIndex, trueReadIndex;
- writeIndex=dataSize-1;
- readIndex=writeIndex-1;
- while (readIndex >= index)
- {
- if ( queueHead + writeIndex >= allocationSize )
- trueWriteIndex = queueHead + writeIndex - allocationSize;
- else
- trueWriteIndex = queueHead + writeIndex;
- if ( queueHead + readIndex >= allocationSize )
- trueReadIndex = queueHead + readIndex - allocationSize;
- else
- trueReadIndex = queueHead + readIndex;
- data[trueWriteIndex]=data[trueReadIndex];
- if (readIndex==0)
- break;
- writeIndex--;
- readIndex--;
- }
- if ( queueHead + index >= allocationSize )
- trueWriteIndex = queueHead + index - allocationSize;
- else
- trueWriteIndex = queueHead + index;
- data[trueWriteIndex]=d;
- }
- if (_MultilistType!=ML_ORDERED_LIST)
- sortState=ML_UNSORTED;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::RemoveAtIndex(_IndexType position, const char *file, unsigned int line)
- {
- RakAssert(position < dataSize);
- RakAssert(IsEmpty()==false);
- if (GetMultilistType()==ML_UNORDERED_LIST)
- {
- // Copy tail to current
- data[position]=data[dataSize-1];
- }
- else if (GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
- {
- DeleteShiftArrayLeft(position);
- }
- else
- {
- RakAssert(GetMultilistType()==ML_QUEUE);
- _IndexType index, next;
- if ( queueHead + position >= allocationSize )
- index = queueHead + position - allocationSize;
- else
- index = queueHead + position;
- next = index + 1;
- if ( next == allocationSize )
- next = 0;
- while ( next != queueTail )
- {
- // Overwrite the previous element
- data[ index ] = data[ next ];
- index = next;
- //next = (next + 1) % allocationSize;
- if ( ++next == allocationSize )
- next = 0;
- }
- // Move the queueTail back
- if ( queueTail == 0 )
- queueTail = allocationSize - 1;
- else
- --queueTail;
- }
-
-
- dataSize--;
- DeallocateIfNeeded(file,line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::RemoveAtKey(_KeyType key, bool assertIfDoesNotExist, const char *file, unsigned int line)
- {
- _IndexType index = GetIndexOf(key);
- if (index==(_IndexType)-1)
- {
- RakAssert(assertIfDoesNotExist==false && "RemoveAtKey element not found");
- return false;
- }
- RemoveAtIndex(index,file,line);
- return true;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetIndexOf(_KeyType key) const
- {
- _IndexType i;
- if (IsSorted())
- {
- bool objectExists;
- i=GetIndexFromKeyInSortedList(key, &objectExists);
- if (objectExists)
- return i;
- return (_IndexType)-1;
- }
- else if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
- {
- for (i=0; i < dataSize; i++)
- {
- if (MLKeyRef<_KeyType>(key)==data[i])
- return i;
- }
- return (_IndexType)-1;
- }
- else
- {
- RakAssert( GetMultilistType()==ML_QUEUE );
- for (i=0; i < dataSize; i++)
- {
- if (MLKeyRef<_KeyType>(key)==operator[](i))
- return i;
- }
- return (_IndexType)-1;
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetInsertionIndex(_KeyType key) const
- {
- _IndexType i;
- if (IsSorted())
- {
- bool objectExists;
- i=GetIndexFromKeyInSortedList(key, &objectExists);
- if (objectExists)
- return (_IndexType)-1;
- return i;
- }
- else if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
- {
- for (i=0; i < dataSize; i++)
- {
- if (MLKeyRef<_KeyType>(key)==data[i])
- return (_IndexType)-1;
- }
- return dataSize;
- }
- else
- {
- RakAssert( GetMultilistType()==ML_QUEUE );
- for (i=0; i < dataSize; i++)
- {
- if (MLKeyRef<_KeyType>(key)==operator[](i))
- return (_IndexType)-1;
- }
- return dataSize;
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _DataType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetPtr(_KeyType key) const
- {
- _IndexType i = GetIndexOf(key);
- if (i==(_IndexType)-1)
- return 0;
- return data[i];
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ForEach(void (*func)(_DataType &item, const char *file, unsigned int line), const char *file, unsigned int line)
- {
- _IndexType i;
- for (i=0; i < dataSize; i++)
- func(operator[](i), file, line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ForEach(void (*func)(_DataType &item))
- {
- _IndexType i;
- for (i=0; i < dataSize; i++)
- func(operator[](i));
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::IsEmpty(void) const
- {
- return dataSize==0;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetSize(void) const
- {
- return dataSize;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Clear( bool deallocateSmallBlocks, const char *file, unsigned int line )
- {
- dataSize=0;
- if (GetMultilistType()==ML_ORDERED_LIST)
- if (ascendingSort)
- sortState=ML_SORTED_ASCENDING;
- else
- sortState=ML_SORTED_DESCENDING;
- else
- sortState=ML_UNSORTED;
- queueHead=0;
- queueTail=0;
- if (deallocateSmallBlocks && allocationSize < 128 && data)
- {
- RakNet::OP_DELETE_ARRAY(data,file,line);
- data=0;
- allocationSize=0;
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ClearPointers( bool deallocateSmallBlocks, const char *file, unsigned int line )
- {
- _IndexType i;
- for (i=0; i < dataSize; i++)
- RakNet::OP_DELETE(operator[](i), file, line);
- Clear(deallocateSmallBlocks, file, line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ClearPointer( _KeyType key, const char *file, unsigned int line )
- {
- _IndexType i;
- i = GetIndexOf(key);
- if (i!=-1)
- {
- RakNet::OP_DELETE(operator[](i), file, line);
- RemoveAtIndex(i);
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReverseList(void)
- {
- if (IsSorted())
- ascendingSort=!ascendingSort;
- ReverseListInternal();
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Reallocate(_IndexType size, const char *file, unsigned int line)
- {
- _IndexType newAllocationSize;
- if (size < dataSize)
- newAllocationSize=dataSize;
- else
- newAllocationSize=size;
- preallocationSize=size;
- ReallocToSize(newAllocationSize,file,line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Sort(bool force)
- {
- if (IsSorted() && force==false)
- return;
- if (dataSize>1)
- {
- if (ascendingSort)
- QSortAscending(0,dataSize-1);
- else
- QSortDescending(0,dataSize-1);
- }
- TagSorted();
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::TagSorted(void)
- {
- if (ascendingSort)
- sortState=ML_SORTED_ASCENDING;
- else
- sortState=ML_SORTED_DESCENDING;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::QSortAscending(_IndexType leftEdge, _IndexType rightEdge)
- {
- _DataType temp;
- _IndexType left=leftEdge;
- _IndexType right=rightEdge;
- _IndexType pivotIndex=left++;
- while (left<right)
- {
- if (data[left] <= data[pivotIndex])
- {
- ++left;
- }
- else
- {
- temp=data[left];
- data[left]=data[right];
- data[right]=temp;
- --right;
- }
- }
- temp=data[pivotIndex];
- // Move pivot to center
- if (data[left] > data[pivotIndex])
- {
- --left;
- data[pivotIndex]=data[left];
- data[left]=temp;
- }
- else
- {
- data[pivotIndex]=data[left];
- data[left]=temp;
- --left;
- }
- if (left!=leftEdge)
- QSortAscending(leftEdge, left);
- if (right!=rightEdge)
- QSortAscending(right, rightEdge);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::QSortDescending(_IndexType leftEdge, _IndexType rightEdge)
- {
- _DataType temp;
- _IndexType left=leftEdge;
- _IndexType right=rightEdge;
- _IndexType pivotIndex=left++;
- while (left<right)
- {
- if (data[left] >= data[pivotIndex])
- {
- ++left;
- }
- else
- {
- temp=data[left];
- data[left]=data[right];
- data[right]=temp;
- --right;
- }
- }
- temp=data[pivotIndex];
- // Move pivot to center
- if (data[left] < data[pivotIndex])
- {
- --left;
- data[pivotIndex]=data[left];
- data[left]=temp;
- }
- else
- {
- data[pivotIndex]=data[left];
- data[left]=temp;
- --left;
- }
- if (left!=leftEdge)
- QSortDescending(leftEdge, left);
- if (right!=rightEdge)
- QSortDescending(right, rightEdge);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::SetSortOrder(bool ascending)
- {
- if (ascendingSort!=ascending && IsSorted())
- {
- ascendingSort=ascending;
- // List is sorted, and the sort order has changed. So reverse the list
- ReverseListInternal();
- }
- else
- ascendingSort=ascending;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetSortOrder(void) const
- {
- return ascendingSort;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::IsSorted(void) const
- {
- return GetMultilistType()==ML_ORDERED_LIST || sortState!=ML_UNSORTED;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- MultilistType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetMultilistType(void) const
- {
- if (_MultilistType==ML_VARIABLE_DURING_RUNTIME)
- return variableMultilistType;
- return _MultilistType;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::SetMultilistType(MultilistType newType)
- {
- RakAssert(_MultilistType==ML_VARIABLE_DURING_RUNTIME);
- switch (variableMultilistType)
- {
- case ML_UNORDERED_LIST:
- switch (newType)
- {
- case ML_UNORDERED_LIST:
- // No change
- break;
- case ML_STACK:
- // Same data format
- break;
- case ML_QUEUE:
- queueHead=0;
- queueTail=dataSize;
- break;
- case ML_ORDERED_LIST:
- Sort(false);
- break;
- }
- break;
- case ML_STACK:
- switch (newType)
- {
- case ML_UNORDERED_LIST:
- // Same data format
- break;
- case ML_STACK:
- // No change
- break;
- case ML_QUEUE:
- queueHead=0;
- queueTail=dataSize;
- break;
- case ML_ORDERED_LIST:
- Sort(false);
- break;
- }
- break;
- case ML_QUEUE:
- switch (newType)
- {
- case ML_UNORDERED_LIST:
- case ML_STACK:
- case ML_ORDERED_LIST:
- if (queueTail < queueHead)
- {
- // Realign data if wrapped
- ReallocToSize(dataSize, _FILE_AND_LINE_);
- }
- else
- {
- // Else can just copy starting at head
- _IndexType i;
- for (i=0; i < dataSize; i++)
- data[i]=operator[](i);
- }
- if (newType==ML_ORDERED_LIST)
- Sort(false);
- break;
- case ML_QUEUE:
- // No change
- break;
- }
- break;
- case ML_ORDERED_LIST:
- switch (newType)
- {
- case ML_UNORDERED_LIST:
- case ML_STACK:
- case ML_QUEUE:
- // Same data format
- // Tag as sorted
- if (ascendingSort)
- sortState=ML_SORTED_ASCENDING;
- else
- sortState=ML_SORTED_DESCENDING;
- if (newType==ML_QUEUE)
- {
- queueHead=0;
- queueTail=dataSize;
- }
- break;
- case ML_ORDERED_LIST:
- // No change
- break;
- }
- break;
- }
- variableMultilistType=newType;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::FindIntersection(
- Multilist& source1,
- Multilist& source2,
- Multilist& intersection,
- Multilist& uniqueToSource1,
- Multilist& uniqueToSource2)
- {
- _IndexType index1=0, index2=0;
- source1.SetSortOrder(true);
- source2.SetSortOrder(true);
- source1.Sort(false);
- source2.Sort(false);
- intersection.Clear(true,_FILE_AND_LINE_);
- uniqueToSource1.Clear(true,_FILE_AND_LINE_);
- uniqueToSource2.Clear(true,_FILE_AND_LINE_);
-
- while (index1 < source1.GetSize() && index2 < source2.GetSize())
- {
- if (source1[index1]<source2[index2])
- {
- uniqueToSource1.Push(source1[index1],_FILE_AND_LINE_);
- index1++;
- }
- else if (source1[index1]==source2[index2])
- {
- intersection.Push(source1[index1],_FILE_AND_LINE_);
- index1++;
- index2++;
- }
- else
- {
- uniqueToSource2.Push(source2[index2],_FILE_AND_LINE_);
- index2++;
- }
- }
- while (index1 < source1.GetSize())
- {
- uniqueToSource1.Push(source1[index1],_FILE_AND_LINE_);
- index1++;
- }
- while (index2 < source2.GetSize())
- {
- uniqueToSource2.Push(source2[index2],_FILE_AND_LINE_);
- index2++;
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReallocateIfNeeded(const char *file, unsigned int line)
- {
- if (dataSize<allocationSize)
- return;
- _IndexType newAllocationSize;
- if (allocationSize<16)
- newAllocationSize=32;
- else if (allocationSize>65536)
- newAllocationSize=allocationSize+65536;
- else
- {
- newAllocationSize=allocationSize<<1; // * 2
- // Protect against underflow
- if (newAllocationSize < allocationSize)
- newAllocationSize=allocationSize+65536;
- }
- ReallocToSize(newAllocationSize,file,line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::DeallocateIfNeeded(const char *file, unsigned int line)
- {
- if (allocationSize<512)
- return;
- if (dataSize >= allocationSize/3 )
- return;
- if (dataSize <= preallocationSize )
- return;
-
- _IndexType newAllocationSize = dataSize<<1; // * 2
- ReallocToSize(newAllocationSize,file,line);
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReallocToSize(_IndexType newAllocationSize, const char *file, unsigned int line)
- {
- _DataType* newData = RakNet::OP_NEW_ARRAY<_DataType>(newAllocationSize,file,line);
- _IndexType i;
- for (i=0; i < dataSize; i++)
- newData[i]=operator[](i);
- if (dataSize>0)
- {
- RakNet::OP_DELETE_ARRAY(data,file,line);
- if (GetMultilistType()==ML_QUEUE)
- {
- queueHead=0;
- queueTail=dataSize;
- }
- }
- data=newData;
- allocationSize=newAllocationSize;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReverseListInternal(void)
- {
- _DataType temp;
- _IndexType i;
- for (i=0; i < dataSize/2; i++)
- {
- temp=operator[](i);
- operator[](i)=operator[](dataSize-1-i);
- operator[](dataSize-1-i)=temp;
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertInOrderedList(const _DataType &d, const _KeyType &key)
- {
- RakAssert(GetMultilistType()==ML_ORDERED_LIST);
- bool objectExists;
- _IndexType index;
- index = GetIndexFromKeyInSortedList(key, &objectExists);
- // if (objectExists)
- // {
- // Ordered list only allows unique insertions
- // RakAssert("Duplicate insertion into ordered list" && false);
- // return;
- // }
- if (index>=dataSize)
- {
- // insert at end
- data[dataSize]=d;
- dataSize++;
- }
- else
- {
- // insert at index
- InsertShiftArrayRight(d,index);
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetIndexFromKeyInSortedList(const _KeyType &key, bool *objectExists) const
- {
- RakAssert(IsSorted());
- _IndexType index, upperBound, lowerBound;
- if (dataSize==0)
- {
- *objectExists=false;
- return 0;
- }
- upperBound=dataSize-1;
- lowerBound=0;
- index = dataSize/2;
- #ifdef _MSC_VER
- #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
- #endif
- while (1)
- {
- if (MLKeyRef<_KeyType>(key) > operator[](index) )
- {
- if (ascendingSort)
- lowerBound=index+1;
- else
- upperBound=index-1;
- }
- else if (MLKeyRef<_KeyType>(key) < operator[](index) )
- {
- if (ascendingSort)
- upperBound=index-1;
- else
- lowerBound=index+1;
- }
- else
- {
- // ==
- *objectExists=true;
- return index;
- }
- index=lowerBound+(upperBound-lowerBound)/2;
- if (lowerBound>upperBound || upperBound==(_IndexType)-1)
- {
- *objectExists=false;
- return lowerBound; // No match
- }
- }
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertShiftArrayRight(const _DataType &d, _IndexType index)
- {
- RakAssert(_MultilistType!=ML_QUEUE);
- // Move the elements in the list to make room
- _IndexType i;
- for ( i = dataSize; i != index; i-- )
- data[ i ] = data[ i - 1 ];
- // Insert the new item at the correct spot
- data[ index ] = d;
- ++dataSize;
- }
- template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
- void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::DeleteShiftArrayLeft( _IndexType index )
- {
- RakAssert(index < dataSize);
- RakAssert(_MultilistType!=ML_QUEUE);
- _IndexType i;
- for ( i = index; i < dataSize-1; i++ )
- data[i]=data[i+1];
- }
- };
- /*
- struct KeyAndValue
- {
- int key;
- short value;
- };
- DEFINE_MULTILIST_PTR_TO_MEMBER_COMPARISONS(KeyAndValue,int,key)
- void MultilistUnitTest(void)
- {
- DataStructures::DefaultIndexType oldSize;
- DataStructures::Multilist<ML_UNORDERED_LIST, int> ml1;
- ml1.Reallocate(64);
- RakAssert(ml1.IsEmpty());
- ml1.Push(53);
- RakAssert(ml1.Peek()==53);
- RakAssert(ml1.IsEmpty()==false);
- RakAssert(ml1.Pop()==53);
- RakAssert(ml1.IsEmpty()==true);
- for (int i=0; i < 512; i++)
- ml1.Push(i);
- RakAssert(ml1.GetIndexOf(200)==200);
- RakAssert(ml1.PeekOpposite()==0);
- RakAssert(ml1.PopOpposite()==0);
- RakAssert(ml1.PeekOpposite()==1);
- RakAssert(ml1.Peek()==511);
- ml1.ReverseList();
- for (int i=0; i < 511; i++)
- RakAssert(ml1[i]==511-i);
- RakAssert(ml1.PeekOpposite()==511);
- RakAssert(ml1.Peek()==1);
- oldSize = ml1.GetSize();
- ml1.RemoveAtIndex(0);
- RakAssert(ml1.GetSize()==oldSize-1);
- RakAssert(ml1.PeekOpposite()==1);
- ml1.Clear(_FILE_AND_LINE_);
- RakAssert(ml1.IsEmpty()==true);
- ml1.Sort(true);
- ml1.Clear(_FILE_AND_LINE_);
- ml1.Push(100);
- ml1.Sort(true);
- ml1.Clear(_FILE_AND_LINE_);
- ml1.Push(50);
- ml1.Push(100);
- ml1.Sort(true);
- ml1.Clear(_FILE_AND_LINE_);
- ml1.Push(100);
- ml1.Push(50);
- ml1.Sort(true);
- ml1.Clear(_FILE_AND_LINE_);
- ml1.Push(100);
- ml1.Push(50);
- ml1.Push(150);
- ml1.Push(25);
- ml1.Push(175);
- ml1.Sort(true);
- RakAssert(ml1[0]==25);
- RakAssert(ml1[1]==50);
- RakAssert(ml1[2]==100);
- RakAssert(ml1[3]==150);
- RakAssert(ml1[4]==175);
- RakAssert(ml1.GetIndexOf(25)==0);
- RakAssert(ml1.GetIndexOf(50)==1);
- RakAssert(ml1.GetIndexOf(100)==2);
- RakAssert(ml1.GetIndexOf(150)==3);
- RakAssert(ml1.GetIndexOf(175)==4);
- ml1.Clear(_FILE_AND_LINE_);
- ml1.Push(1);
- ml1.Push(2);
- ml1.Push(3);
- ml1.Push(4);
- ml1.Push(5);
- ml1.Sort(true);
- RakAssert(ml1[0]==1);
- RakAssert(ml1[1]==2);
- RakAssert(ml1[2]==3);
- RakAssert(ml1[3]==4);
- RakAssert(ml1[4]==5);
- RakAssert(ml1.GetIndexOf(1)==0);
- RakAssert(ml1.GetIndexOf(2)==1);
- RakAssert(ml1.GetIndexOf(3)==2);
- RakAssert(ml1.GetIndexOf(4)==3);
- RakAssert(ml1.GetIndexOf(5)==4);
- ml1.Clear(_FILE_AND_LINE_);
- ml1.Push(5);
- ml1.Push(4);
- ml1.Push(3);
- ml1.Push(2);
- ml1.Push(1);
- ml1.Sort(true);
- RakAssert(ml1[0]==1);
- RakAssert(ml1[1]==2);
- RakAssert(ml1[2]==3);
- RakAssert(ml1[3]==4);
- RakAssert(ml1[4]==5);
- RakAssert(ml1.GetIndexOf(1)==0);
- RakAssert(ml1.GetIndexOf(2)==1);
- RakAssert(ml1.GetIndexOf(3)==2);
- RakAssert(ml1.GetIndexOf(4)==3);
- RakAssert(ml1.GetIndexOf(5)==4);
- ml1.Sort(true);
- RakAssert(ml1[0]==1);
- RakAssert(ml1[1]==2);
- RakAssert(ml1[2]==3);
- RakAssert(ml1[3]==4);
- RakAssert(ml1[4]==5);
- RakAssert(ml1.GetIndexOf(1)==0);
- RakAssert(ml1.GetIndexOf(2)==1);
- RakAssert(ml1.GetIndexOf(3)==2);
- RakAssert(ml1.GetIndexOf(4)==3);
- RakAssert(ml1.GetIndexOf(5)==4);
- ml1.Clear(_FILE_AND_LINE_);
- DataStructures::Multilist<ML_STACK, int> ml2;
- ml2.Reallocate(64);
- RakAssert(ml2.IsEmpty());
- ml2.Push(53);
- RakAssert(ml2.Peek()==53);
- RakAssert(ml2.IsEmpty()==false);
- RakAssert(ml2.Pop()==53);
- RakAssert(ml2.IsEmpty()==true);
- for (int i=0; i < 512; i++)
- ml2.Push(i);
- RakAssert(ml2.GetIndexOf(200)==200);
- RakAssert(ml2.PeekOpposite()==0);
- RakAssert(ml2.PopOpposite()==0);
- RakAssert(ml2.PeekOpposite()==1);
- RakAssert(ml2.Peek()==511);
- ml2.ReverseList();
- for (int i=0; i < 511; i++)
- RakAssert(ml2[i]==511-i);
- RakAssert(ml2.PeekOpposite()==511);
- RakAssert(ml2.Peek()==1);
- oldSize = ml2.GetSize();
- ml2.RemoveAtIndex(0);
- RakAssert(ml2.GetSize()==oldSize-1);
- RakAssert(ml2.Peek()==1);
- RakAssert(ml2.PeekOpposite()==510);
- ml2.Clear(_FILE_AND_LINE_);
- RakAssert(ml2.IsEmpty()==true);
- DataStructures::Multilist<ML_QUEUE, int> ml3;
- RakAssert(ml3.IsEmpty());
- ml3.Push(53);
- RakAssert(ml3.Peek()==53);
- RakAssert(ml3.IsEmpty()==false);
- RakAssert(ml3.Pop()==53);
- RakAssert(ml3.IsEmpty()==true);
- for (int i=0; i < 512; i++)
- ml3.Push(i);
- RakAssert(ml3.GetIndexOf(200)==200);
- RakAssert(ml3.PeekOpposite()==511);
- RakAssert(ml3.PopOpposite()==511);
- RakAssert(ml3.PeekOpposite()==510);
- RakAssert(ml3.Peek()==0);
- ml3.ReverseList();
- for (int i=0; i < 511; i++)
- RakAssert(ml3[i]==511-1-i);
- RakAssert(ml3.PeekOpposite()==0);
- RakAssert(ml3.Peek()==510);
- oldSize = ml3.GetSize();
- ml3.RemoveAtIndex(0);
- RakAssert(ml3.GetSize()==oldSize-1);
- RakAssert(ml3.Peek()==509);
- RakAssert(ml3.PeekOpposite()==0);
- ml3.Clear(_FILE_AND_LINE_);
- RakAssert(ml3.IsEmpty()==true);
- ml3.PushOpposite(100);
- ml3.PushOpposite(50);
- ml3.PushOpposite(150);
- ml3.PushOpposite(25);
- ml3.PushOpposite(175);
- ml3.Sort(true);
- RakAssert(ml3[0]==25);
- RakAssert(ml3[1]==50);
- RakAssert(ml3[2]==100);
- RakAssert(ml3[3]==150);
- RakAssert(ml3[4]==175);
- RakAssert(ml3.GetIndexOf(25)==0);
- RakAssert(ml3.GetIndexOf(50)==1);
- RakAssert(ml3.GetIndexOf(100)==2);
- RakAssert(ml3.GetIndexOf(150)==3);
- RakAssert(ml3.GetIndexOf(175)==4);
- ml3.Clear(_FILE_AND_LINE_);
- ml3.PushOpposite(1);
- ml3.PushOpposite(2);
- ml3.PushOpposite(3);
- ml3.PushOpposite(4);
- ml3.PushOpposite(5);
- ml3.Sort(true);
- RakAssert(ml3[0]==1);
- RakAssert(ml3[1]==2);
- RakAssert(ml3[2]==3);
- RakAssert(ml3[3]==4);
- RakAssert(ml3[4]==5);
- RakAssert(ml3.GetIndexOf(1)==0);
- RakAssert(ml3.GetIndexOf(2)==1);
- RakAssert(ml3.GetIndexOf(3)==2);
- RakAssert(ml3.GetIndexOf(4)==3);
- RakAssert(ml3.GetIndexOf(5)==4);
- ml3.Clear(_FILE_AND_LINE_);
- ml3.PushOpposite(5);
- ml3.PushOpposite(4);
- ml3.PushOpposite(3);
- ml3.PushOpposite(2);
- ml3.PushOpposite(1);
- ml3.Sort(true);
- RakAssert(ml3[0]==1);
- RakAssert(ml3[1]==2);
- RakAssert(ml3[2]==3);
- RakAssert(ml3[3]==4);
- RakAssert(ml3[4]==5);
- RakAssert(ml3.GetIndexOf(1)==0);
- RakAssert(ml3.GetIndexOf(2)==1);
- RakAssert(ml3.GetIndexOf(3)==2);
- RakAssert(ml3.GetIndexOf(4)==3);
- RakAssert(ml3.GetIndexOf(5)==4);
- ml3.Sort(true);
- RakAssert(ml3[0]==1);
- RakAssert(ml3[1]==2);
- RakAssert(ml3[2]==3);
- RakAssert(ml3[3]==4);
- RakAssert(ml3[4]==5);
- RakAssert(ml3.GetIndexOf(1)==0);
- RakAssert(ml3.GetIndexOf(2)==1);
- RakAssert(ml3.GetIndexOf(3)==2);
- RakAssert(ml3.GetIndexOf(4)==3);
- RakAssert(ml3.GetIndexOf(5)==4);
- ml3.SetSortOrder(false);
- ml3.Sort(false);
- RakAssert(ml3[0]==5);
- RakAssert(ml3[1]==4);
- RakAssert(ml3[2]==3);
- RakAssert(ml3[3]==2);
- RakAssert(ml3[4]==1);
- RakAssert(ml3.GetIndexOf(1)==4);
- RakAssert(ml3.GetIndexOf(2)==3);
- RakAssert(ml3.GetIndexOf(3)==2);
- RakAssert(ml3.GetIndexOf(4)==1);
- RakAssert(ml3.GetIndexOf(5)==0);
- ml3.Clear(_FILE_AND_LINE_);
- DataStructures::Multilist<ML_ORDERED_LIST, int> ml4;
- ml4.Reallocate(64);
- RakAssert(ml4.IsEmpty());
- ml4.Push(53);
- RakAssert(ml4.Peek()==53);
- RakAssert(ml4.IsEmpty()==false);
- RakAssert(ml4.Pop()==53);
- RakAssert(ml4.IsEmpty()==true);
- for (int i=0; i < 512; i++)
- ml4.Push(i);
- RakAssert(ml4.GetIndexOf(200)==200);
- RakAssert(ml4.PeekOpposite()==0);
- RakAssert(ml4.PopOpposite()==0);
- RakAssert(ml4.PeekOpposite()==1);
- RakAssert(ml4.Peek()==511);
- ml4.ReverseList();
- for (int i=0; i < 511; i++)
- RakAssert(ml4[i]==511-i);
- RakAssert(ml4.PeekOpposite()==511);
- RakAssert(ml4.Peek()==1);
- oldSize = ml4.GetSize();
- ml4.RemoveAtIndex(0);
- RakAssert(ml4.GetSize()==oldSize-1);
- RakAssert(ml4.Peek()==1);
- RakAssert(ml4.PeekOpposite()==510);
- ml4.Clear(_FILE_AND_LINE_);
- RakAssert(ml4.IsEmpty()==true);
- DataStructures::Multilist<ML_ORDERED_LIST, KeyAndValue*, int> ml5;
- for (int i=0; i < 16; i++)
- {
- KeyAndValue *kav = new KeyAndValue;
- kav->key=i;
- kav->value=i+100;
- ml5.Push(kav,kav->key);
- }
- RakAssert(ml5.GetIndexOf(0)==0);
- RakAssert(ml5.GetIndexOf(5)==5);
- RakAssert(ml5.GetIndexOf(15)==15);
- RakAssert(ml5.GetIndexOf(16)==-1);
- ml5.RemoveAtKey(0,true);
- RakAssert(ml5.GetIndexOf(1)==0);
- KeyAndValue *iPtr = ml5.GetPtr(5);
- RakAssert(iPtr);
- RakAssert(iPtr->value=105);
- iPtr = ml5.GetPtr(1234);
- RakAssert(iPtr==0);
- ml5.ForEach(DataStructures::DeletePtr<KeyAndValue*>);
- DataStructures::Multilist<ML_VARIABLE_DURING_RUNTIME, int> ml6;
- ml6.Push(2);
- ml6.Push(1);
- ml6.Push(6);
- ml6.Push(3);
- RakAssert(ml6.Peek()==3);
- ml6.SetMultilistType(ML_STACK);
- RakAssert(ml6.Peek()==3);
- ml6.SetMultilistType(ML_QUEUE);
- RakAssert(ml6.Peek()==2);
- ml6.SetMultilistType(ML_ORDERED_LIST);
- RakAssert(ml6.Peek()=6);
- ml6.SetMultilistType(ML_STACK);
- RakAssert(ml6.Peek()==6);
- ml6.SetMultilistType(ML_QUEUE);
- RakAssert(ml6.Peek()==1);
- }
- #ifdef _MSC_VER
- #pragma warning( pop )
- #endif
- */
- #endif
|