SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_Multilist.h
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
20
21 #ifndef __MULTILIST_H
22 #define __MULTILIST_H
23
24 #include "assert.h"
25 #include <string.h> // memmove
26 #include "Export.h"
27 #include "memoryoverride.h"
28 #include "NativeTypes.h"
29
30
32 enum MultilistType
33 {
35 ML_UNORDERED_LIST,
37 ML_STACK,
39 ML_QUEUE,
41 ML_ORDERED_LIST,
43 ML_VARIABLE_DURING_RUNTIME
44 };
45
48 namespace DataStructures
49 {
52 template <class templateType>
53 void DeletePtr_RakNet(templateType &ptr, const char *file, unsigned int line ) { SLNet::OP_DELETE(ptr, file, line);}
54
57 template <class templateType>
58 void DeletePtr(templateType &ptr) {delete ptr;}
59
65 template < class templateType >
66 class MLKeyRef
67 {
68 public:
69 MLKeyRef(const templateType& input) : val(input) {}
70 const templateType &Get(void) const {return val;}
71 bool operator<( const templateType &right ) {return val < right;}
72 bool operator>( const templateType &right ) {return val > right;}
73 bool operator==( const templateType &right ) {return val == right;}
74 protected:
75 const templateType &val;
76 private:
77 // MLKeyRef is not copy-assignable
78 MLKeyRef& operator=(const MLKeyRef& master);
79 };
80
86 #define DEFINE_MULTILIST_PTR_TO_MEMBER_COMPARISONS( _CLASS_NAME_, _KEY_TYPE_, _MEMBER_VARIABLE_NAME_ ) \
87 bool operator<( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() < cls->_MEMBER_VARIABLE_NAME_;} \
88 bool operator>( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() > cls->_MEMBER_VARIABLE_NAME_;} \
89 bool operator==( const DataStructures::MLKeyRef<_KEY_TYPE_> &inputKey, const _CLASS_NAME_ *cls ) {return inputKey.Get() == cls->_MEMBER_VARIABLE_NAME_;}
90
91 typedef uint32_t DefaultIndexType;
92
98 template <const MultilistType _MultilistType, class _DataType, class _KeyType=_DataType, class _IndexType=DefaultIndexType>
99 class RAK_DLL_EXPORT Multilist
100 {
101 public:
102 Multilist();
103 ~Multilist();
104 Multilist( const Multilist& source );
105 Multilist& operator= ( const Multilist& source );
106 _DataType& operator[] ( const _IndexType position ) const;
110 void Push(const _DataType &d, const char *file=__FILE__, unsigned int line=__LINE__ );
111 void Push(const _DataType &d, const _KeyType &key, const char *file=__FILE__, unsigned int line=__LINE__ );
112
115 _DataType &Pop(const char *file=__FILE__, unsigned int line=__LINE__);
116 _DataType &Peek(void) const;
117
120 void PushOpposite(const _DataType &d, const char *file=__FILE__, unsigned int line=__LINE__ );
121 void PushOpposite(const _DataType &d, const _KeyType &key, const char *file=__FILE__, unsigned int line=__LINE__ );
122
124 _DataType &PopOpposite(const char *file=__FILE__, unsigned int line=__LINE__);
125 _DataType &PeekOpposite(void) const;
126
129 void InsertAtIndex(const _DataType &d, _IndexType index, const char *file=__FILE__, unsigned int line=__LINE__);
130
135 void RemoveAtIndex(_IndexType position, const char *file=__FILE__, unsigned int line=__LINE__);
136
138 bool RemoveAtKey(_KeyType key, bool assertIfDoesNotExist, const char *file=__FILE__, unsigned int line=__LINE__);
139
141 _IndexType GetIndexOf(_KeyType key) const;
142
145 _IndexType GetInsertionIndex(_KeyType key) const;
146
148 _DataType GetPtr(_KeyType key) const;
149
151 void ForEach(void (*func)(_DataType &item, const char *file, unsigned int line), const char *file, unsigned int line);
152 void ForEach(void (*func)(_DataType &item));
153
155 bool IsEmpty(void) const;
156
158 _IndexType GetSize(void) const;
159
162 void Clear( bool deallocateSmallBlocks=true, const char *file=__FILE__, unsigned int line=__LINE__ );
163
166 void ClearPointers( bool deallocateSmallBlocks=true, const char *file=__FILE__, unsigned int line=__LINE__ );
167
169 void ClearPointer( _KeyType key, const char *file=__FILE__, unsigned int line=__LINE__ );
170
173 void ReverseList(void);
174
177 void Reallocate(_IndexType size, const char *file=__FILE__, unsigned int line=__LINE__);
178
182 void Sort(bool force);
183
186 void TagSorted(void);
187
190 void SetSortOrder(bool ascending);
191
193 bool GetSortOrder(void) const;
194
198 bool IsSorted(void) const;
199
201 MultilistType GetMultilistType(void) const;
202
206 void SetMultilistType(MultilistType newType);
207
210 static void FindIntersection(
211 Multilist& source1,
212 Multilist& source2,
213 Multilist& intersection,
214 Multilist& uniqueToSource1,
215 Multilist& uniqueToSource2);
216
217 protected:
218 void ReallocateIfNeeded(const char *file, unsigned int line);
219 void DeallocateIfNeeded(const char *file, unsigned int line);
220 void ReallocToSize(_IndexType newAllocationSize, const char *file, unsigned int line);
221 void ReverseListInternal(void);
222 void InsertInOrderedList(const _DataType &d, const _KeyType &key);
223 _IndexType GetIndexFromKeyInSortedList(const _KeyType &key, bool *objectExists) const;
224 void InsertShiftArrayRight(const _DataType &d, _IndexType index);
225 void DeleteShiftArrayLeft(_IndexType index);
226 void QSortAscending(_IndexType left, _IndexType right);
227 void QSortDescending(_IndexType left, _IndexType right);
228 void CopySource( const Multilist& source );
229
231 _DataType* data;
232
234 _IndexType dataSize;
235
237 _IndexType allocationSize;
238
240 _IndexType queueHead;
241
243 _IndexType queueTail;
244
247 _IndexType preallocationSize;
248
249 enum
250 {
251 ML_UNSORTED,
252 ML_SORTED_ASCENDING,
253 ML_SORTED_DESCENDING
254 } sortState;
255
256 bool ascendingSort;
257
258 // In case we are using the variable type multilist
259 MultilistType variableMultilistType;
260 };
261
262 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
263 Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Multilist()
264 {
265 data=0;
266 dataSize=0;
267 allocationSize=0;
268 ascendingSort=true;
269 sortState=ML_UNSORTED;
270 queueHead=0;
271 queueTail=0;
272 preallocationSize=0;
273
274 #pragma warning( push )
275 #pragma warning(disable:4127) // conditional expression is constant
276 if (_MultilistType==ML_ORDERED_LIST)
277 sortState=ML_SORTED_ASCENDING;
278 else
279 sortState=ML_UNSORTED;
280
281 if (_MultilistType==ML_VARIABLE_DURING_RUNTIME)
282 variableMultilistType=ML_UNORDERED_LIST;
283 #pragma warning( pop )
284 }
285
286 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
287 Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::~Multilist()
288 {
289 if (data!=0)
290 SLNet::OP_DELETE_ARRAY(data, _FILE_AND_LINE_);
291 }
292
293 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
294 Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Multilist( const Multilist& source )
295 {
296 CopySource(source);
297 }
298
299 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
300 Multilist<_MultilistType, _DataType, _KeyType, _IndexType>& Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::operator= ( const Multilist& source )
301 {
302 Clear(true);
303 CopySource(source);
304 return *this;
305 }
306
307 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
308 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::CopySource( const Multilist& source )
309 {
310 dataSize=source.GetSize();
311 ascendingSort=source.ascendingSort;
312 sortState=source.sortState;
313 queueHead=0;
314 queueTail=dataSize;
315 preallocationSize=source.preallocationSize;
316 variableMultilistType=source.variableMultilistType;
317 if (source.data==0)
318 {
319 data=0;
320 allocationSize=0;
321 }
322 else
323 {
324 allocationSize=dataSize;
325 data = SLNet::OP_NEW_ARRAY<_DataType>(dataSize,_FILE_AND_LINE_);
326 _IndexType i;
327 for (i=0; i < dataSize; i++)
328 data[i]=source[i];
329 }
330 }
331
332 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
333 _DataType& Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::operator[] ( const _IndexType position ) const
334 {
335 RakAssert(position<GetSize());
336
337 if (GetMultilistType()==ML_QUEUE)
338 {
339 if ( queueHead + position >= allocationSize )
340 return data[ queueHead + position - allocationSize ];
341 else
342 return data[ queueHead + position ];
343 }
344
345 return data[position];
346 }
347
348 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
349 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Push(const _DataType &d, const char *file, unsigned int line )
350 {
351 Push(d,d,file,line);
352 }
353
354 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
355 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Push(const _DataType &d, const _KeyType &key, const char *file, unsigned int line )
356 {
357 ReallocateIfNeeded(file,line);
358
359 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
360 {
361 data[dataSize]=d;
362 dataSize++;
363 }
364 else if (GetMultilistType()==ML_QUEUE)
365 {
366 data[queueTail++] = d;
367
368 if ( queueTail == allocationSize )
369 queueTail = 0;
370 dataSize++;
371 }
372 else
373 {
374 RakAssert(GetMultilistType()==ML_ORDERED_LIST);
375 InsertInOrderedList(d,key);
376 }
377
378 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_QUEUE)
379 {
380 // Break sort if no longer sorted
381 if (sortState!=ML_UNSORTED && dataSize>1)
382 {
383 if (ascendingSort)
384 {
385 if ( MLKeyRef<_KeyType>(key) < operator[](dataSize-2) )
386 sortState=ML_UNSORTED;
387 }
388 else
389 {
390 if ( MLKeyRef<_KeyType>(key) > operator[](dataSize-2) )
391 sortState=ML_UNSORTED;
392 }
393
394 sortState=ML_UNSORTED;
395 }
396 }
397 }
398
399 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
400 _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Pop(const char *file, unsigned int line)
401 {
402 RakAssert(IsEmpty()==false);
403 DeallocateIfNeeded(file,line);
404 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
405 {
406 dataSize--;
407 return data[dataSize];
408 }
409 else
410 {
411 RakAssert(GetMultilistType()==ML_QUEUE);
412
413 if ( ++queueHead == allocationSize )
414 queueHead = 0;
415
416 if ( queueHead == 0 )
417 return data[ allocationSize -1 ];
418
419 dataSize--;
420 return data[ queueHead -1 ];
421 }
422 }
423
424 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
425 _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Peek(void) const
426 {
427 RakAssert(IsEmpty()==false);
428 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
429 {
430 return data[dataSize-1];
431 }
432 else
433 {
434 RakAssert(GetMultilistType()==ML_QUEUE);
435 return data[ queueHead ];
436 }
437 }
438
439 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
440 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PushOpposite(const _DataType &d, const char *file, unsigned int line )
441 {
442 PushOpposite(d,d,file,line);
443 }
444
445 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
446 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PushOpposite(const _DataType &d, const _KeyType &key, const char *file, unsigned int line )
447 {
448 ReallocateIfNeeded(file,line);
449
450 // Unordered list Push at back
451 if (GetMultilistType()==ML_UNORDERED_LIST)
452 {
453 data[dataSize]=d;
454 dataSize++;
455 }
456 else if (GetMultilistType()==ML_STACK)
457 {
458 // Stack push at front of the list, instead of back as normal
459 InsertAtIndex(d,0,file,line);
460 }
461 else if (GetMultilistType()==ML_QUEUE)
462 {
463 // Queue push at front of the list, instead of back as normal
464 InsertAtIndex(d,0,file,line);
465 }
466 else
467 {
468 RakAssert(GetMultilistType()==ML_ORDERED_LIST);
469 InsertInOrderedList(d,key);
470 }
471
472 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_QUEUE)
473 {
474 // Break sort if no longer sorted
475 if (sortState!=ML_UNSORTED && dataSize>1)
476 {
477 if (ascendingSort)
478 {
479 if ( MLKeyRef<_KeyType>(key) > operator[](1) )
480 sortState=ML_UNSORTED;
481 }
482 else
483 {
484 if ( MLKeyRef<_KeyType>(key) < operator[](1) )
485 sortState=ML_UNSORTED;
486 }
487 }
488 }
489 }
490
491 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
492 _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PopOpposite(const char *file, unsigned int line)
493 {
494 RakAssert(IsEmpty()==false);
495 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
496 {
497 // Copy leftmost to end
498 ReallocateIfNeeded(file,line);
499 data[dataSize]=data[0];
500 DeleteShiftArrayLeft(0);
501 --dataSize;
502 // Assuming still leaves at least one element past the end of the list allocated
503 DeallocateIfNeeded(file,line);
504 // Return end
505 return data[dataSize+1];
506 }
507 else
508 {
509 RakAssert(GetMultilistType()==ML_QUEUE);
510 // Deallocate first, since we are returning off the existing list
511 DeallocateIfNeeded(file,line);
512 dataSize--;
513
514 if (queueTail==0)
515 queueTail=allocationSize-1;
516 else
517 --queueTail;
518
519 return data[queueTail];
520 }
521 }
522
523 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
524 _DataType &Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::PeekOpposite(void) const
525 {
526 RakAssert(IsEmpty()==false);
527 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
528 {
529 return data[0];
530 }
531 else
532 {
533 RakAssert(GetMultilistType()==ML_QUEUE);
534 _IndexType priorIndex;
535 if (queueTail==0)
536 priorIndex=allocationSize-1;
537 else
538 priorIndex=queueTail-1;
539
540 return data[priorIndex];
541 }
542 }
543
544 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
545 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertAtIndex(const _DataType &d, _IndexType index, const char *file, unsigned int line)
546 {
547 ReallocateIfNeeded(file,line);
548
549 if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
550 {
551 if (index>=dataSize)
552 {
553 // insert at end
554 data[dataSize]=d;
555
556 dataSize++;
557 }
558 else
559 {
560 // insert at index
561 InsertShiftArrayRight(d,index);
562 }
563 }
564 else
565 {
566 data[queueTail++] = d;
567
568 if ( queueTail == allocationSize )
569 queueTail = 0;
570
571 ++dataSize;
572
573 if (dataSize==1)
574 return;
575
576 _IndexType writeIndex, readIndex, trueWriteIndex, trueReadIndex;
577 writeIndex=dataSize-1;
578 readIndex=writeIndex-1;
579 while (readIndex >= index)
580 {
581 if ( queueHead + writeIndex >= allocationSize )
582 trueWriteIndex = queueHead + writeIndex - allocationSize;
583 else
584 trueWriteIndex = queueHead + writeIndex;
585
586 if ( queueHead + readIndex >= allocationSize )
587 trueReadIndex = queueHead + readIndex - allocationSize;
588 else
589 trueReadIndex = queueHead + readIndex;
590
591 data[trueWriteIndex]=data[trueReadIndex];
592
593 if (readIndex==0)
594 break;
595 writeIndex--;
596 readIndex--;
597 }
598
599 if ( queueHead + index >= allocationSize )
600 trueWriteIndex = queueHead + index - allocationSize;
601 else
602 trueWriteIndex = queueHead + index;
603
604 data[trueWriteIndex]=d;
605 }
606
607 if (_MultilistType!=ML_ORDERED_LIST)
608 sortState=ML_UNSORTED;
609 }
610
611 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
612 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::RemoveAtIndex(_IndexType position, const char *file, unsigned int line)
613 {
614 RakAssert(position < dataSize);
615 RakAssert(IsEmpty()==false);
616
617 if (GetMultilistType()==ML_UNORDERED_LIST)
618 {
619 // Copy tail to current
620 data[position]=data[dataSize-1];
621 }
622 else if (GetMultilistType()==ML_STACK || GetMultilistType()==ML_ORDERED_LIST)
623 {
624 DeleteShiftArrayLeft(position);
625 }
626 else
627 {
628 RakAssert(GetMultilistType()==ML_QUEUE);
629
630 _IndexType index, next;
631
632 if ( queueHead + position >= allocationSize )
633 index = queueHead + position - allocationSize;
634 else
635 index = queueHead + position;
636
637 next = index + 1;
638
639 if ( next == allocationSize )
640 next = 0;
641
642 while ( next != queueTail )
643 {
644 // Overwrite the previous element
645 data[ index ] = data[ next ];
646 index = next;
647 //next = (next + 1) % allocationSize;
648
649 if ( ++next == allocationSize )
650 next = 0;
651 }
652
653 // Move the queueTail back
654 if ( queueTail == 0 )
655 queueTail = allocationSize - 1;
656 else
657 --queueTail;
658 }
659
660
661 dataSize--;
662 DeallocateIfNeeded(file,line);
663 }
664
665 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
666 bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::RemoveAtKey(_KeyType key, bool assertIfDoesNotExist, const char *file, unsigned int line)
667 {
668 _IndexType index = GetIndexOf(key);
669 if (index==(_IndexType)-1)
670 {
671 RakAssert(assertIfDoesNotExist==false && "RemoveAtKey element not found");
672 return false;
673 }
674 RemoveAtIndex(index,file,line);
675 return true;
676 }
677
678 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
679 _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetIndexOf(_KeyType key) const
680 {
681 _IndexType i;
682 if (IsSorted())
683 {
684 bool objectExists;
685 i=GetIndexFromKeyInSortedList(key, &objectExists);
686 if (objectExists)
687 return i;
688 return (_IndexType)-1;
689 }
690 else if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
691 {
692 for (i=0; i < dataSize; i++)
693 {
694 if (MLKeyRef<_KeyType>(key)==data[i])
695 return i;
696 }
697 return (_IndexType)-1;
698 }
699 else
700 {
701 RakAssert( GetMultilistType()==ML_QUEUE );
702
703 for (i=0; i < dataSize; i++)
704 {
705 if (MLKeyRef<_KeyType>(key)==operator[](i))
706 return i;
707 }
708 return (_IndexType)-1;
709 }
710 }
711
712 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
713 _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetInsertionIndex(_KeyType key) const
714 {
715 _IndexType i;
716 if (IsSorted())
717 {
718 bool objectExists;
719 i=GetIndexFromKeyInSortedList(key, &objectExists);
720 if (objectExists)
721 return (_IndexType)-1;
722 return i;
723 }
724 else if (GetMultilistType()==ML_UNORDERED_LIST || GetMultilistType()==ML_STACK)
725 {
726 for (i=0; i < dataSize; i++)
727 {
728 if (MLKeyRef<_KeyType>(key)==data[i])
729 return (_IndexType)-1;
730 }
731 return dataSize;
732 }
733 else
734 {
735 RakAssert( GetMultilistType()==ML_QUEUE );
736
737 for (i=0; i < dataSize; i++)
738 {
739 if (MLKeyRef<_KeyType>(key)==operator[](i))
740 return (_IndexType)-1;
741 }
742 return dataSize;
743 }
744 }
745
746 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
747 _DataType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetPtr(_KeyType key) const
748 {
749 _IndexType i = GetIndexOf(key);
750 if (i==(_IndexType)-1)
751 return 0;
752 return data[i];
753 }
754
755 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
756 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ForEach(void (*func)(_DataType &item, const char *file, unsigned int line), const char *file, unsigned int line)
757 {
758 _IndexType i;
759 for (i=0; i < dataSize; i++)
760 func(operator[](i), file, line);
761 }
762
763 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
764 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ForEach(void (*func)(_DataType &item))
765 {
766 _IndexType i;
767 for (i=0; i < dataSize; i++)
768 func(operator[](i));
769 }
770
771 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
772 bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::IsEmpty(void) const
773 {
774 return dataSize==0;
775 }
776
777 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
778 _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetSize(void) const
779 {
780 return dataSize;
781 }
782
783 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
784 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Clear( bool deallocateSmallBlocks, const char *file, unsigned int line )
785 {
786 dataSize=0;
787 if (GetMultilistType()==ML_ORDERED_LIST)
788 if (ascendingSort)
789 sortState=ML_SORTED_ASCENDING;
790 else
791 sortState=ML_SORTED_DESCENDING;
792 else
793 sortState=ML_UNSORTED;
794 queueHead=0;
795 queueTail=0;
796
797 if (deallocateSmallBlocks && allocationSize < 128 && data)
798 {
799 SLNet::OP_DELETE_ARRAY(data,file,line);
800 data=0;
801 allocationSize=0;
802 }
803 }
804
805 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
806 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ClearPointers( bool deallocateSmallBlocks, const char *file, unsigned int line )
807 {
808 _IndexType i;
809 for (i=0; i < dataSize; i++)
810 SLNet::OP_DELETE(operator[](i), file, line);
811 Clear(deallocateSmallBlocks, file, line);
812 }
813
814 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
815 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ClearPointer( _KeyType key, const char *file, unsigned int line )
816 {
817 _IndexType i;
818 i = GetIndexOf(key);
819 if (i!=-1)
820 {
821 SLNet::OP_DELETE(operator[](i), file, line);
822 RemoveAtIndex(i);
823 }
824 }
825
826 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
827 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReverseList(void)
828 {
829 if (IsSorted())
830 ascendingSort=!ascendingSort;
831
832 ReverseListInternal();
833 }
834
835 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
836 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Reallocate(_IndexType size, const char *file, unsigned int line)
837 {
838 _IndexType newAllocationSize;
839 if (size < dataSize)
840 newAllocationSize=dataSize;
841 else
842 newAllocationSize=size;
843 preallocationSize=size;
844 ReallocToSize(newAllocationSize,file,line);
845 }
846
847 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
848 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::Sort(bool force)
849 {
850 if (IsSorted() && force==false)
851 return;
852
853 if (dataSize>1)
854 {
855 if (ascendingSort)
856 QSortAscending(0,dataSize-1);
857 else
858 QSortDescending(0,dataSize-1);
859 }
860
861 TagSorted();
862 }
863
864 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
865 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::TagSorted(void)
866 {
867 if (ascendingSort)
868 sortState=ML_SORTED_ASCENDING;
869 else
870 sortState=ML_SORTED_DESCENDING;
871 }
872
873 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
874 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::QSortAscending(_IndexType leftEdge, _IndexType rightEdge)
875 {
876 _DataType temp;
877 _IndexType left=leftEdge;
878 _IndexType right=rightEdge;
879 _IndexType pivotIndex=left++;
880
881 while (left<right)
882 {
883 if (data[left] <= data[pivotIndex])
884 {
885 ++left;
886 }
887 else
888 {
889 temp=data[left];
890 data[left]=data[right];
891 data[right]=temp;
892 --right;
893 }
894 }
895
896 temp=data[pivotIndex];
897
898 // Move pivot to center
899 if (data[left] > data[pivotIndex])
900 {
901 --left;
902
903 data[pivotIndex]=data[left];
904 data[left]=temp;
905 }
906 else
907 {
908 data[pivotIndex]=data[left];
909 data[left]=temp;
910
911 --left;
912 }
913
914 if (left!=leftEdge)
915 QSortAscending(leftEdge, left);
916
917 if (right!=rightEdge)
918 QSortAscending(right, rightEdge);
919 }
920
921 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
922 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::QSortDescending(_IndexType leftEdge, _IndexType rightEdge)
923 {
924 _DataType temp;
925 _IndexType left=leftEdge;
926 _IndexType right=rightEdge;
927 _IndexType pivotIndex=left++;
928
929 while (left<right)
930 {
931 if (data[left] >= data[pivotIndex])
932 {
933 ++left;
934 }
935 else
936 {
937 temp=data[left];
938 data[left]=data[right];
939 data[right]=temp;
940 --right;
941 }
942 }
943
944 temp=data[pivotIndex];
945
946 // Move pivot to center
947 if (data[left] < data[pivotIndex])
948 {
949 --left;
950
951 data[pivotIndex]=data[left];
952 data[left]=temp;
953 }
954 else
955 {
956 data[pivotIndex]=data[left];
957 data[left]=temp;
958
959 --left;
960 }
961
962 if (left!=leftEdge)
963 QSortDescending(leftEdge, left);
964
965 if (right!=rightEdge)
966 QSortDescending(right, rightEdge);
967 }
968
969 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
970 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::SetSortOrder(bool ascending)
971 {
972 if (ascendingSort!=ascending && IsSorted())
973 {
974 ascendingSort=ascending;
975 // List is sorted, and the sort order has changed. So reverse the list
976 ReverseListInternal();
977 }
978 else
979 ascendingSort=ascending;
980 }
981
982 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
983 bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetSortOrder(void) const
984 {
985 return ascendingSort;
986 }
987
988 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
989 bool Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::IsSorted(void) const
990 {
991 return GetMultilistType()==ML_ORDERED_LIST || sortState!=ML_UNSORTED;
992 }
993
994 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
995 MultilistType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetMultilistType(void) const
996 {
997 #pragma warning( push )
998 #pragma warning(disable:4127) // conditional expression is constant
999 if (_MultilistType==ML_VARIABLE_DURING_RUNTIME)
1000 #pragma warning( pop )
1001 return variableMultilistType;
1002 return _MultilistType;
1003 }
1004
1005 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1006 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::SetMultilistType(MultilistType newType)
1007 {
1008 RakAssert(_MultilistType==ML_VARIABLE_DURING_RUNTIME);
1009 switch (variableMultilistType)
1010 {
1011 case ML_UNORDERED_LIST:
1012 switch (newType)
1013 {
1014 case ML_UNORDERED_LIST:
1015 // No change
1016 break;
1017 case ML_STACK:
1018 // Same data format
1019 break;
1020 case ML_QUEUE:
1021 queueHead=0;
1022 queueTail=dataSize;
1023 break;
1024 case ML_ORDERED_LIST:
1025 Sort(false);
1026 break;
1027 }
1028 break;
1029 case ML_STACK:
1030 switch (newType)
1031 {
1032 case ML_UNORDERED_LIST:
1033 // Same data format
1034 break;
1035 case ML_STACK:
1036 // No change
1037 break;
1038 case ML_QUEUE:
1039 queueHead=0;
1040 queueTail=dataSize;
1041 break;
1042 case ML_ORDERED_LIST:
1043 Sort(false);
1044 break;
1045 }
1046 break;
1047 case ML_QUEUE:
1048 switch (newType)
1049 {
1050 case ML_UNORDERED_LIST:
1051 case ML_STACK:
1052 case ML_ORDERED_LIST:
1053 if (queueTail < queueHead)
1054 {
1055 // Realign data if wrapped
1056 ReallocToSize(dataSize, _FILE_AND_LINE_);
1057 }
1058 else
1059 {
1060 // Else can just copy starting at head
1061 _IndexType i;
1062 for (i=0; i < dataSize; i++)
1063 data[i]=operator[](i);
1064 }
1065 if (newType==ML_ORDERED_LIST)
1066 Sort(false);
1067 break;
1068 case ML_QUEUE:
1069 // No change
1070 break;
1071 }
1072 break;
1073 case ML_ORDERED_LIST:
1074 switch (newType)
1075 {
1076 case ML_UNORDERED_LIST:
1077 case ML_STACK:
1078 case ML_QUEUE:
1079 // Same data format
1080 // Tag as sorted
1081 if (ascendingSort)
1082 sortState=ML_SORTED_ASCENDING;
1083 else
1084 sortState=ML_SORTED_DESCENDING;
1085 if (newType==ML_QUEUE)
1086 {
1087 queueHead=0;
1088 queueTail=dataSize;
1089 }
1090 break;
1091 case ML_ORDERED_LIST:
1092 // No change
1093 break;
1094 }
1095 break;
1096 }
1097
1098 variableMultilistType=newType;
1099 }
1100
1101 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1102 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::FindIntersection(
1103 Multilist& source1,
1104 Multilist& source2,
1105 Multilist& intersection,
1106 Multilist& uniqueToSource1,
1107 Multilist& uniqueToSource2)
1108 {
1109 _IndexType index1=0, index2=0;
1110 source1.SetSortOrder(true);
1111 source2.SetSortOrder(true);
1112 source1.Sort(false);
1113 source2.Sort(false);
1114 intersection.Clear(true,_FILE_AND_LINE_);
1115 uniqueToSource1.Clear(true,_FILE_AND_LINE_);
1116 uniqueToSource2.Clear(true,_FILE_AND_LINE_);
1117
1118 while (index1 < source1.GetSize() && index2 < source2.GetSize())
1119 {
1120 if (source1[index1]<source2[index2])
1121 {
1122 uniqueToSource1.Push(source1[index1],_FILE_AND_LINE_);
1123 index1++;
1124 }
1125 else if (source1[index1]==source2[index2])
1126 {
1127 intersection.Push(source1[index1],_FILE_AND_LINE_);
1128 index1++;
1129 index2++;
1130 }
1131 else
1132 {
1133 uniqueToSource2.Push(source2[index2],_FILE_AND_LINE_);
1134 index2++;
1135 }
1136 }
1137 while (index1 < source1.GetSize())
1138 {
1139 uniqueToSource1.Push(source1[index1],_FILE_AND_LINE_);
1140 index1++;
1141 }
1142 while (index2 < source2.GetSize())
1143 {
1144 uniqueToSource2.Push(source2[index2],_FILE_AND_LINE_);
1145 index2++;
1146 }
1147 }
1148
1149 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1150 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReallocateIfNeeded(const char *file, unsigned int line)
1151 {
1152 if (dataSize<allocationSize)
1153 return;
1154
1155 _IndexType newAllocationSize;
1156 if (allocationSize<16)
1157 newAllocationSize=32;
1158 else if (allocationSize>65536)
1159 newAllocationSize=allocationSize+65536;
1160 else
1161 {
1162 newAllocationSize=allocationSize<<1; // * 2
1163 // Protect against underflow
1164 if (newAllocationSize < allocationSize)
1165 newAllocationSize=allocationSize+65536;
1166 }
1167
1168 ReallocToSize(newAllocationSize,file,line);
1169 }
1170
1171 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1172 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::DeallocateIfNeeded(const char *file, unsigned int line)
1173 {
1174 if (allocationSize<512)
1175 return;
1176 if (dataSize >= allocationSize/3 )
1177 return;
1178 if (dataSize <= preallocationSize )
1179 return;
1180
1181 _IndexType newAllocationSize = dataSize<<1; // * 2
1182
1183 ReallocToSize(newAllocationSize,file,line);
1184 }
1185
1186 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1187 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReallocToSize(_IndexType newAllocationSize, const char *file, unsigned int line)
1188 {
1189 _DataType* newData = SLNet::OP_NEW_ARRAY<_DataType>(newAllocationSize,file,line);
1190 _IndexType i;
1191 for (i=0; i < dataSize; i++)
1192 newData[i]=operator[](i);
1193 if (dataSize>0)
1194 {
1195 SLNet::OP_DELETE_ARRAY(data,file,line);
1196 if (GetMultilistType()==ML_QUEUE)
1197 {
1198 queueHead=0;
1199 queueTail=dataSize;
1200 }
1201 }
1202 data=newData;
1203 allocationSize=newAllocationSize;
1204 }
1205
1206 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1207 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::ReverseListInternal(void)
1208 {
1209 _DataType temp;
1210 _IndexType i;
1211 for (i=0; i < dataSize/2; i++)
1212 {
1213 temp=operator[](i);
1214 operator[](i)=operator[](dataSize-1-i);
1215 operator[](dataSize-1-i)=temp;
1216 }
1217 }
1218
1219 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1220 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertInOrderedList(const _DataType &d, const _KeyType &key)
1221 {
1222 RakAssert(GetMultilistType()==ML_ORDERED_LIST);
1223
1224 bool objectExists;
1225 _IndexType index;
1226 index = GetIndexFromKeyInSortedList(key, &objectExists);
1227
1228 // if (objectExists)
1229 // {
1230 // Ordered list only allows unique insertions
1231 // RakAssert("Duplicate insertion into ordered list" && false);
1232 // return;
1233 // }
1234
1235 if (index>=dataSize)
1236 {
1237 // insert at end
1238 data[dataSize]=d;
1239 dataSize++;
1240 }
1241 else
1242 {
1243 // insert at index
1244 InsertShiftArrayRight(d,index);
1245 }
1246 }
1247
1248 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1249 _IndexType Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::GetIndexFromKeyInSortedList(const _KeyType &key, bool *objectExists) const
1250 {
1251 RakAssert(IsSorted());
1252 _IndexType index, upperBound, lowerBound;
1253
1254 if (dataSize==0)
1255 {
1256 *objectExists=false;
1257 return 0;
1258 }
1259
1260 upperBound=dataSize-1;
1261 lowerBound=0;
1262 index = dataSize/2;
1263
1264 for(;;)
1265 {
1266 if (MLKeyRef<_KeyType>(key) > operator[](index) )
1267 {
1268 if (ascendingSort)
1269 lowerBound=index+1;
1270 else
1271 upperBound=index-1;
1272 }
1273 else if (MLKeyRef<_KeyType>(key) < operator[](index) )
1274 {
1275 if (ascendingSort)
1276 upperBound=index-1;
1277 else
1278 lowerBound=index+1;
1279 }
1280 else
1281 {
1282 // ==
1283 *objectExists=true;
1284 return index;
1285 }
1286
1287 index=lowerBound+(upperBound-lowerBound)/2;
1288
1289 if (lowerBound>upperBound || upperBound==(_IndexType)-1)
1290 {
1291 *objectExists=false;
1292 return lowerBound; // No match
1293 }
1294 }
1295 }
1296
1297 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1298 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::InsertShiftArrayRight(const _DataType &d, _IndexType index)
1299 {
1300 RakAssert(_MultilistType!=ML_QUEUE);
1301
1302 // Move the elements in the list to make room
1303 _IndexType i;
1304 for ( i = dataSize; i != index; i-- )
1305 data[ i ] = data[ i - 1 ];
1306
1307 // Insert the new item at the correct spot
1308 data[ index ] = d;
1309
1310 ++dataSize;
1311 }
1312
1313 template <const MultilistType _MultilistType, class _DataType, class _KeyType, class _IndexType>
1314 void Multilist<_MultilistType, _DataType, _KeyType, _IndexType>::DeleteShiftArrayLeft( _IndexType index )
1315 {
1316 RakAssert(index < dataSize);
1317 RakAssert(_MultilistType!=ML_QUEUE);
1318
1319 _IndexType i;
1320 for ( i = index; i < dataSize-1; i++ )
1321 data[i]=data[i+1];
1322 }
1323 };
1324
1325 /*
1326 struct KeyAndValue
1327 {
1328 int key;
1329 short value;
1330 };
1331
1332 DEFINE_MULTILIST_PTR_TO_MEMBER_COMPARISONS(KeyAndValue,int,key)
1333
1334 void MultilistUnitTest(void)
1335 {
1336 DataStructures::DefaultIndexType oldSize;
1337 DataStructures::Multilist<ML_UNORDERED_LIST, int> ml1;
1338 ml1.Reallocate(64);
1339 RakAssert(ml1.IsEmpty());
1340 ml1.Push(53);
1341 RakAssert(ml1.Peek()==53);
1342 RakAssert(ml1.IsEmpty()==false);
1343 RakAssert(ml1.Pop()==53);
1344 RakAssert(ml1.IsEmpty()==true);
1345 for (int i=0; i < 512; i++)
1346 ml1.Push(i);
1347 RakAssert(ml1.GetIndexOf(200)==200);
1348 RakAssert(ml1.PeekOpposite()==0);
1349 RakAssert(ml1.PopOpposite()==0);
1350 RakAssert(ml1.PeekOpposite()==1);
1351 RakAssert(ml1.Peek()==511);
1352 ml1.ReverseList();
1353 for (int i=0; i < 511; i++)
1354 RakAssert(ml1[i]==511-i);
1355 RakAssert(ml1.PeekOpposite()==511);
1356 RakAssert(ml1.Peek()==1);
1357 oldSize = ml1.GetSize();
1358 ml1.RemoveAtIndex(0);
1359 RakAssert(ml1.GetSize()==oldSize-1);
1360 RakAssert(ml1.PeekOpposite()==1);
1361 ml1.Clear(_FILE_AND_LINE_);
1362 RakAssert(ml1.IsEmpty()==true);
1363
1364 ml1.Sort(true);
1365 ml1.Clear(_FILE_AND_LINE_);
1366
1367 ml1.Push(100);
1368 ml1.Sort(true);
1369 ml1.Clear(_FILE_AND_LINE_);
1370
1371 ml1.Push(50);
1372 ml1.Push(100);
1373 ml1.Sort(true);
1374 ml1.Clear(_FILE_AND_LINE_);
1375
1376 ml1.Push(100);
1377 ml1.Push(50);
1378 ml1.Sort(true);
1379 ml1.Clear(_FILE_AND_LINE_);
1380
1381 ml1.Push(100);
1382 ml1.Push(50);
1383 ml1.Push(150);
1384 ml1.Push(25);
1385 ml1.Push(175);
1386 ml1.Sort(true);
1387 RakAssert(ml1[0]==25);
1388 RakAssert(ml1[1]==50);
1389 RakAssert(ml1[2]==100);
1390 RakAssert(ml1[3]==150);
1391 RakAssert(ml1[4]==175);
1392 RakAssert(ml1.GetIndexOf(25)==0);
1393 RakAssert(ml1.GetIndexOf(50)==1);
1394 RakAssert(ml1.GetIndexOf(100)==2);
1395 RakAssert(ml1.GetIndexOf(150)==3);
1396 RakAssert(ml1.GetIndexOf(175)==4);
1397 ml1.Clear(_FILE_AND_LINE_);
1398
1399 ml1.Push(1);
1400 ml1.Push(2);
1401 ml1.Push(3);
1402 ml1.Push(4);
1403 ml1.Push(5);
1404 ml1.Sort(true);
1405 RakAssert(ml1[0]==1);
1406 RakAssert(ml1[1]==2);
1407 RakAssert(ml1[2]==3);
1408 RakAssert(ml1[3]==4);
1409 RakAssert(ml1[4]==5);
1410 RakAssert(ml1.GetIndexOf(1)==0);
1411 RakAssert(ml1.GetIndexOf(2)==1);
1412 RakAssert(ml1.GetIndexOf(3)==2);
1413 RakAssert(ml1.GetIndexOf(4)==3);
1414 RakAssert(ml1.GetIndexOf(5)==4);
1415 ml1.Clear(_FILE_AND_LINE_);
1416
1417 ml1.Push(5);
1418 ml1.Push(4);
1419 ml1.Push(3);
1420 ml1.Push(2);
1421 ml1.Push(1);
1422 ml1.Sort(true);
1423 RakAssert(ml1[0]==1);
1424 RakAssert(ml1[1]==2);
1425 RakAssert(ml1[2]==3);
1426 RakAssert(ml1[3]==4);
1427 RakAssert(ml1[4]==5);
1428 RakAssert(ml1.GetIndexOf(1)==0);
1429 RakAssert(ml1.GetIndexOf(2)==1);
1430 RakAssert(ml1.GetIndexOf(3)==2);
1431 RakAssert(ml1.GetIndexOf(4)==3);
1432 RakAssert(ml1.GetIndexOf(5)==4);
1433 ml1.Sort(true);
1434 RakAssert(ml1[0]==1);
1435 RakAssert(ml1[1]==2);
1436 RakAssert(ml1[2]==3);
1437 RakAssert(ml1[3]==4);
1438 RakAssert(ml1[4]==5);
1439 RakAssert(ml1.GetIndexOf(1)==0);
1440 RakAssert(ml1.GetIndexOf(2)==1);
1441 RakAssert(ml1.GetIndexOf(3)==2);
1442 RakAssert(ml1.GetIndexOf(4)==3);
1443 RakAssert(ml1.GetIndexOf(5)==4);
1444 ml1.Clear(_FILE_AND_LINE_);
1445
1446 DataStructures::Multilist<ML_STACK, int> ml2;
1447 ml2.Reallocate(64);
1448 RakAssert(ml2.IsEmpty());
1449 ml2.Push(53);
1450 RakAssert(ml2.Peek()==53);
1451 RakAssert(ml2.IsEmpty()==false);
1452 RakAssert(ml2.Pop()==53);
1453 RakAssert(ml2.IsEmpty()==true);
1454 for (int i=0; i < 512; i++)
1455 ml2.Push(i);
1456 RakAssert(ml2.GetIndexOf(200)==200);
1457 RakAssert(ml2.PeekOpposite()==0);
1458 RakAssert(ml2.PopOpposite()==0);
1459 RakAssert(ml2.PeekOpposite()==1);
1460 RakAssert(ml2.Peek()==511);
1461 ml2.ReverseList();
1462 for (int i=0; i < 511; i++)
1463 RakAssert(ml2[i]==511-i);
1464 RakAssert(ml2.PeekOpposite()==511);
1465 RakAssert(ml2.Peek()==1);
1466 oldSize = ml2.GetSize();
1467 ml2.RemoveAtIndex(0);
1468 RakAssert(ml2.GetSize()==oldSize-1);
1469 RakAssert(ml2.Peek()==1);
1470 RakAssert(ml2.PeekOpposite()==510);
1471 ml2.Clear(_FILE_AND_LINE_);
1472 RakAssert(ml2.IsEmpty()==true);
1473
1474 DataStructures::Multilist<ML_QUEUE, int> ml3;
1475 RakAssert(ml3.IsEmpty());
1476 ml3.Push(53);
1477 RakAssert(ml3.Peek()==53);
1478 RakAssert(ml3.IsEmpty()==false);
1479 RakAssert(ml3.Pop()==53);
1480 RakAssert(ml3.IsEmpty()==true);
1481 for (int i=0; i < 512; i++)
1482 ml3.Push(i);
1483 RakAssert(ml3.GetIndexOf(200)==200);
1484 RakAssert(ml3.PeekOpposite()==511);
1485 RakAssert(ml3.PopOpposite()==511);
1486 RakAssert(ml3.PeekOpposite()==510);
1487 RakAssert(ml3.Peek()==0);
1488 ml3.ReverseList();
1489 for (int i=0; i < 511; i++)
1490 RakAssert(ml3[i]==511-1-i);
1491 RakAssert(ml3.PeekOpposite()==0);
1492 RakAssert(ml3.Peek()==510);
1493 oldSize = ml3.GetSize();
1494 ml3.RemoveAtIndex(0);
1495 RakAssert(ml3.GetSize()==oldSize-1);
1496 RakAssert(ml3.Peek()==509);
1497 RakAssert(ml3.PeekOpposite()==0);
1498 ml3.Clear(_FILE_AND_LINE_);
1499 RakAssert(ml3.IsEmpty()==true);
1500
1501 ml3.PushOpposite(100);
1502 ml3.PushOpposite(50);
1503 ml3.PushOpposite(150);
1504 ml3.PushOpposite(25);
1505 ml3.PushOpposite(175);
1506 ml3.Sort(true);
1507 RakAssert(ml3[0]==25);
1508 RakAssert(ml3[1]==50);
1509 RakAssert(ml3[2]==100);
1510 RakAssert(ml3[3]==150);
1511 RakAssert(ml3[4]==175);
1512 RakAssert(ml3.GetIndexOf(25)==0);
1513 RakAssert(ml3.GetIndexOf(50)==1);
1514 RakAssert(ml3.GetIndexOf(100)==2);
1515 RakAssert(ml3.GetIndexOf(150)==3);
1516 RakAssert(ml3.GetIndexOf(175)==4);
1517 ml3.Clear(_FILE_AND_LINE_);
1518
1519 ml3.PushOpposite(1);
1520 ml3.PushOpposite(2);
1521 ml3.PushOpposite(3);
1522 ml3.PushOpposite(4);
1523 ml3.PushOpposite(5);
1524 ml3.Sort(true);
1525 RakAssert(ml3[0]==1);
1526 RakAssert(ml3[1]==2);
1527 RakAssert(ml3[2]==3);
1528 RakAssert(ml3[3]==4);
1529 RakAssert(ml3[4]==5);
1530 RakAssert(ml3.GetIndexOf(1)==0);
1531 RakAssert(ml3.GetIndexOf(2)==1);
1532 RakAssert(ml3.GetIndexOf(3)==2);
1533 RakAssert(ml3.GetIndexOf(4)==3);
1534 RakAssert(ml3.GetIndexOf(5)==4);
1535 ml3.Clear(_FILE_AND_LINE_);
1536
1537 ml3.PushOpposite(5);
1538 ml3.PushOpposite(4);
1539 ml3.PushOpposite(3);
1540 ml3.PushOpposite(2);
1541 ml3.PushOpposite(1);
1542 ml3.Sort(true);
1543 RakAssert(ml3[0]==1);
1544 RakAssert(ml3[1]==2);
1545 RakAssert(ml3[2]==3);
1546 RakAssert(ml3[3]==4);
1547 RakAssert(ml3[4]==5);
1548 RakAssert(ml3.GetIndexOf(1)==0);
1549 RakAssert(ml3.GetIndexOf(2)==1);
1550 RakAssert(ml3.GetIndexOf(3)==2);
1551 RakAssert(ml3.GetIndexOf(4)==3);
1552 RakAssert(ml3.GetIndexOf(5)==4);
1553 ml3.Sort(true);
1554 RakAssert(ml3[0]==1);
1555 RakAssert(ml3[1]==2);
1556 RakAssert(ml3[2]==3);
1557 RakAssert(ml3[3]==4);
1558 RakAssert(ml3[4]==5);
1559 RakAssert(ml3.GetIndexOf(1)==0);
1560 RakAssert(ml3.GetIndexOf(2)==1);
1561 RakAssert(ml3.GetIndexOf(3)==2);
1562 RakAssert(ml3.GetIndexOf(4)==3);
1563 RakAssert(ml3.GetIndexOf(5)==4);
1564
1565 ml3.SetSortOrder(false);
1566 ml3.Sort(false);
1567 RakAssert(ml3[0]==5);
1568 RakAssert(ml3[1]==4);
1569 RakAssert(ml3[2]==3);
1570 RakAssert(ml3[3]==2);
1571 RakAssert(ml3[4]==1);
1572 RakAssert(ml3.GetIndexOf(1)==4);
1573 RakAssert(ml3.GetIndexOf(2)==3);
1574 RakAssert(ml3.GetIndexOf(3)==2);
1575 RakAssert(ml3.GetIndexOf(4)==1);
1576 RakAssert(ml3.GetIndexOf(5)==0);
1577
1578 ml3.Clear(_FILE_AND_LINE_);
1579
1580 DataStructures::Multilist<ML_ORDERED_LIST, int> ml4;
1581 ml4.Reallocate(64);
1582 RakAssert(ml4.IsEmpty());
1583 ml4.Push(53);
1584 RakAssert(ml4.Peek()==53);
1585 RakAssert(ml4.IsEmpty()==false);
1586 RakAssert(ml4.Pop()==53);
1587 RakAssert(ml4.IsEmpty()==true);
1588 for (int i=0; i < 512; i++)
1589 ml4.Push(i);
1590 RakAssert(ml4.GetIndexOf(200)==200);
1591 RakAssert(ml4.PeekOpposite()==0);
1592 RakAssert(ml4.PopOpposite()==0);
1593 RakAssert(ml4.PeekOpposite()==1);
1594 RakAssert(ml4.Peek()==511);
1595 ml4.ReverseList();
1596 for (int i=0; i < 511; i++)
1597 RakAssert(ml4[i]==511-i);
1598 RakAssert(ml4.PeekOpposite()==511);
1599 RakAssert(ml4.Peek()==1);
1600 oldSize = ml4.GetSize();
1601 ml4.RemoveAtIndex(0);
1602 RakAssert(ml4.GetSize()==oldSize-1);
1603 RakAssert(ml4.Peek()==1);
1604 RakAssert(ml4.PeekOpposite()==510);
1605 ml4.Clear(_FILE_AND_LINE_);
1606 RakAssert(ml4.IsEmpty()==true);
1607
1608 DataStructures::Multilist<ML_ORDERED_LIST, KeyAndValue*, int> ml5;
1609
1610 for (int i=0; i < 16; i++)
1611 {
1612 KeyAndValue *kav = new KeyAndValue;
1613 kav->key=i;
1614 kav->value=i+100;
1615 ml5.Push(kav,kav->key);
1616 }
1617
1618 RakAssert(ml5.GetIndexOf(0)==0);
1619 RakAssert(ml5.GetIndexOf(5)==5);
1620 RakAssert(ml5.GetIndexOf(15)==15);
1621 RakAssert(ml5.GetIndexOf(16)==-1);
1622 ml5.RemoveAtKey(0,true);
1623 RakAssert(ml5.GetIndexOf(1)==0);
1624 KeyAndValue *iPtr = ml5.GetPtr(5);
1625 RakAssert(iPtr);
1626 RakAssert(iPtr->value=105);
1627 iPtr = ml5.GetPtr(1234);
1628 RakAssert(iPtr==0);
1629 ml5.ForEach(DataStructures::DeletePtr<KeyAndValue*>);
1630
1631
1632 DataStructures::Multilist<ML_VARIABLE_DURING_RUNTIME, int> ml6;
1633 ml6.Push(2);
1634 ml6.Push(1);
1635 ml6.Push(6);
1636 ml6.Push(3);
1637 RakAssert(ml6.Peek()==3);
1638 ml6.SetMultilistType(ML_STACK);
1639 RakAssert(ml6.Peek()==3);
1640 ml6.SetMultilistType(ML_QUEUE);
1641 RakAssert(ml6.Peek()==2);
1642 ml6.SetMultilistType(ML_ORDERED_LIST);
1643 RakAssert(ml6.Peek()=6);
1644 ml6.SetMultilistType(ML_STACK);
1645 RakAssert(ml6.Peek()==6);
1646 ml6.SetMultilistType(ML_QUEUE);
1647 RakAssert(ml6.Peek()==1);
1648 }
1649
1650 */
1651
1652 #endif