00001
00002
00003 #ifndef MuscleQueue_h
00004 #define MuscleQueue_h
00005
00006 #include "support/MuscleSupport.h"
00007
00008 BEGIN_NAMESPACE(muscle);
00009
00010 #ifndef SMALL_QUEUE_SIZE
00011 # define SMALL_QUEUE_SIZE 3
00012 #endif
00013
00018 template <class ItemType> class Queue
00019 {
00020 public:
00022 Queue();
00023
00027 explicit Queue(uint32 initialSlots);
00028
00030 Queue(const Queue& copyMe);
00031
00033 virtual ~Queue();
00034
00036 Queue &operator=(const Queue &from);
00037
00040 bool operator==(const Queue &rhs) const;
00041
00043 bool operator!=(const Queue &rhs) const {return !(*this == rhs);}
00044
00049 status_t CopyFrom(const Queue<ItemType> & rhs);
00050
00055 status_t AddTail(const ItemType & item = ItemType());
00056
00068 status_t AddTail(const Queue<ItemType> & queue, uint32 startIndex = 0, uint32 numItems = MUSCLE_NO_LIMIT);
00069
00077 status_t AddTail(const ItemType * items, uint32 numItems);
00078
00083 status_t AddHead(const ItemType &item = ItemType());
00084
00096 status_t AddHead(const Queue<ItemType> & queue, uint32 startIndex = 0, uint32 numItems = MUSCLE_NO_LIMIT);
00097
00104 status_t AddHead(const ItemType * items, uint32 numItems);
00105
00109 status_t RemoveHead();
00110
00115 status_t RemoveHead(ItemType & returnItem);
00116
00120 status_t RemoveTail();
00121
00126 status_t RemoveTail(ItemType & returnItem);
00127
00135 status_t RemoveItemAt(uint32 index);
00136
00143 status_t RemoveItemAt(uint32 index, ItemType & returnItem);
00144
00151 status_t GetItemAt(uint32 index, ItemType & returnItem) const;
00152
00159 ItemType * GetItemAt(uint32 index) const;
00160
00167 status_t ReplaceItemAt(uint32 index, const ItemType & newItem = ItemType());
00168
00176 status_t InsertItemAt(uint32 index, const ItemType & newItem = ItemType());
00177
00189 status_t InsertItemsAt(uint32 index, const Queue<ItemType> & queue, uint32 startIndex = 0, uint32 numNewItems = MUSCLE_NO_LIMIT);
00190
00201 status_t InsertItemsAt(uint32 index, const ItemType * items, uint32 numNewItems);
00202
00207 void Clear(bool releaseCachedBuffers = false);
00208
00210 uint32 GetNumItems() const {return _itemCount;}
00211
00216 uint32 GetNumAllocatedItemSlots() const {return _queueSize;}
00217
00219 bool IsEmpty() const {return (_itemCount == 0);}
00220
00222 bool HasItems() const {return (_itemCount > 0);}
00223
00225 const ItemType & Head() const {return *GetItemAt(0);}
00226
00228 const ItemType & Tail() const {return *GetItemAt(_itemCount-1);}
00229
00231 ItemType & Head() {return *GetItemAt(0);}
00232
00234 ItemType & Tail() {return *GetItemAt(_itemCount-1);}
00235
00237 ItemType * HeadPointer() const {return (_itemCount > 0) ? GetItemAt(0) : NULL;}
00238
00240 ItemType * TailPointer() const {return (_itemCount > 0) ? GetItemAt(_itemCount-1) : NULL;}
00241
00243 const ItemType & operator [](uint32 Index) const;
00244
00246 ItemType & operator [](uint32 Index);
00247
00251 ItemType * GetItemPointer(uint32 index) const {return GetItemAt(index);}
00252
00268 status_t EnsureSize(uint32 numSlots, bool setNumItems = false, uint32 extraReallocItems = 0);
00269
00275 int32 IndexOf(const ItemType & item) const;
00276
00283 void Swap(uint32 fromIndex, uint32 toIndex);
00284
00293 void ReverseItemOrdering(uint32 from=0, uint32 to = MUSCLE_NO_LIMIT);
00294
00305 typedef int (*ItemCompareFunc)(const ItemType & item1, const ItemType & item2, void * cookie);
00306
00320 void Sort(ItemCompareFunc compareFunc, uint32 from=0, uint32 to = MUSCLE_NO_LIMIT, void * optCookie = NULL);
00321
00326 void SwapContents(Queue<ItemType> & that);
00327
00333 uint32 RemoveAllInstancesOf(const ItemType & val);
00334
00340 status_t RemoveFirstInstanceOf(const ItemType & val);
00341
00347 status_t RemoveLastInstanceOf(const ItemType & val);
00348
00350 bool StartsWith(const ItemType & prefix) const {return ((HasItems())&&(Head() == prefix));}
00351
00353 bool StartsWith(const Queue<ItemType> & prefixQueue) const;
00354
00356 bool EndsWith(const ItemType & suffix) const {return ((HasItems())&&(Tail() == suffix));}
00357
00359 bool EndsWith(const Queue<ItemType> & suffixQueue) const;
00360
00371 ItemType * GetArrayPointer(uint32 whichArray, uint32 & retLength) {return const_cast<ItemType *>(GetArrayPointerAux(whichArray, retLength));}
00372
00374 const ItemType * GetArrayPointer(uint32 whichArray, uint32 & retLength) const {return GetArrayPointerAux(whichArray, retLength);}
00375
00382 void Normalize();
00383
00384 private:
00385 const ItemType * GetArrayPointerAux(uint32 whichArray, uint32 & retLength) const;
00386 void SwapContentsAux(Queue<ItemType> & that);
00387
00388 inline uint32 NextIndex(uint32 idx) const {return (idx >= _queueSize-1) ? 0 : idx+1;}
00389 inline uint32 PrevIndex(uint32 idx) const {return (idx == 0) ? _queueSize-1 : idx-1;}
00390
00391
00392 inline uint32 InternalizeIndex(uint32 idx) const {return (_headIndex + idx) % _queueSize;}
00393
00394
00395 void Merge(ItemCompareFunc compareFunc, uint32 from, uint32 pivot, uint32 to, uint32 len1, uint32 len2, void * cookie);
00396 uint32 Lower(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const;
00397 uint32 Upper(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const;
00398
00399 ItemType _smallQueue[SMALL_QUEUE_SIZE];
00400 ItemType * _queue;
00401 uint32 _queueSize;
00402 uint32 _itemCount;
00403 uint32 _headIndex;
00404 uint32 _tailIndex;
00405 const uint32 _initialSize;
00406 };
00407
00408 template <class ItemType>
00409 Queue<ItemType>::Queue()
00410 : _queue(NULL), _queueSize(0), _itemCount(0), _initialSize(SMALL_QUEUE_SIZE)
00411 {
00412
00413 }
00414
00415 template <class ItemType>
00416 Queue<ItemType>::Queue(uint32 initialSize)
00417 : _queue(NULL), _queueSize(0), _itemCount(0), _initialSize(initialSize)
00418 {
00419
00420 }
00421
00422 template <class ItemType>
00423 Queue<ItemType>::Queue(const Queue& rhs)
00424 : _queue(NULL), _queueSize(0), _itemCount(0), _initialSize(rhs._initialSize)
00425 {
00426 *this = rhs;
00427 }
00428
00429 template <class ItemType>
00430 bool
00431 Queue<ItemType>::operator ==(const Queue& rhs) const
00432 {
00433 if (this == &rhs) return true;
00434 if (GetNumItems() != rhs.GetNumItems()) return false;
00435
00436 for (int i = GetNumItems()-1; i>=0; i--) if (((*this)[i] == rhs[i]) == false) return false;
00437
00438 return true;
00439 }
00440
00441 template <class ItemType>
00442 Queue<ItemType> &
00443 Queue<ItemType>::operator =(const Queue& rhs)
00444 {
00445 if (this != &rhs)
00446 {
00447 uint32 numItems = rhs.GetNumItems();
00448 if (EnsureSize(numItems, true) == B_NO_ERROR) for (uint32 i=0; i<numItems; i++) (*this)[i] = rhs[i];
00449 }
00450 return *this;
00451 }
00452
00453 template <class ItemType>
00454 status_t
00455 Queue<ItemType>::CopyFrom(const Queue & rhs)
00456 {
00457 if (this == &rhs) return B_NO_ERROR;
00458
00459 uint32 numItems = rhs.GetNumItems();
00460 if (EnsureSize(numItems, true) == B_NO_ERROR)
00461 {
00462 for (uint32 i=0; i<numItems; i++) (*this)[i] = rhs[i];
00463 return B_NO_ERROR;
00464 }
00465 return B_ERROR;
00466 }
00467
00468 template <class ItemType>
00469 ItemType &
00470 Queue<ItemType>::operator[](uint32 i)
00471 {
00472 MASSERT(i<_itemCount, "Invalid index to Queue::[]");
00473 return _queue[InternalizeIndex(i)];
00474 }
00475
00476 template <class ItemType>
00477 const ItemType &
00478 Queue<ItemType>::operator[](uint32 i) const
00479 {
00480 MASSERT(i<_itemCount, "Invalid index to Queue::[]");
00481 return _queue[InternalizeIndex(i)];
00482 }
00483
00484 template <class ItemType>
00485 ItemType *
00486 Queue<ItemType>::GetItemAt(uint32 i) const
00487 {
00488 return &_queue[InternalizeIndex(i)];
00489 }
00490
00491 template <class ItemType>
00492 Queue<ItemType>::~Queue()
00493 {
00494 if (_queue != _smallQueue) delete [] _queue;
00495 }
00496
00497 template <class ItemType>
00498 status_t
00499 Queue<ItemType>::
00500 AddTail(const ItemType &item)
00501 {
00502 if (EnsureSize(_itemCount+1, false, _itemCount+1) == B_ERROR) return B_ERROR;
00503 if (_itemCount == 0) _headIndex = _tailIndex = 0;
00504 else _tailIndex = NextIndex(_tailIndex);
00505 _queue[_tailIndex] = item;
00506 _itemCount++;
00507 return B_NO_ERROR;
00508 }
00509
00510 template <class ItemType>
00511 status_t
00512 Queue<ItemType>::
00513 AddTail(const Queue<ItemType> &queue, uint32 startIndex, uint32 numNewItems)
00514 {
00515 uint32 hisSize = queue.GetNumItems();
00516 numNewItems = muscleMin(numNewItems, (startIndex < hisSize) ? (hisSize-startIndex) : 0);
00517
00518 uint32 mySize = GetNumItems();
00519 uint32 newSize = mySize+numNewItems;
00520
00521 if (EnsureSize(newSize, true) != B_NO_ERROR) return B_ERROR;
00522 for (uint32 i=mySize; i<newSize; i++) (*this)[i] = queue[startIndex++];
00523 return B_NO_ERROR;
00524 }
00525
00526 template <class ItemType>
00527 status_t
00528 Queue<ItemType>::
00529 AddTail(const ItemType * items, uint32 numItems)
00530 {
00531 uint32 mySize = GetNumItems();
00532 uint32 newSize = mySize+numItems;
00533 uint32 rhs = 0;
00534
00535 if (EnsureSize(newSize, true) != B_NO_ERROR) return B_ERROR;
00536 for (uint32 i=mySize; i<newSize; i++) (*this)[i] = items[rhs++];
00537 return B_NO_ERROR;
00538 }
00539
00540 template <class ItemType>
00541 status_t
00542 Queue<ItemType>::
00543 AddHead(const ItemType &item)
00544 {
00545 if (EnsureSize(_itemCount+1, false, _itemCount+1) == B_ERROR) return B_ERROR;
00546 if (_itemCount == 0) _headIndex = _tailIndex = 0;
00547 else _headIndex = PrevIndex(_headIndex);
00548 _queue[_headIndex] = item;
00549 _itemCount++;
00550 return B_NO_ERROR;
00551 }
00552
00553 template <class ItemType>
00554 status_t
00555 Queue<ItemType>::
00556 AddHead(const Queue<ItemType> &queue, uint32 startIndex, uint32 numNewItems)
00557 {
00558 uint32 hisSize = queue.GetNumItems();
00559 numNewItems = muscleMin(numNewItems, (startIndex < hisSize) ? (hisSize-startIndex) : 0);
00560
00561 if (EnsureSize(numNewItems+GetNumItems()) != B_NO_ERROR) return B_ERROR;
00562 for (int i=((int)startIndex+numNewItems)-1; i>=(int32)startIndex; i--) if (AddHead(queue[i]) == B_ERROR) return B_ERROR;
00563 return B_NO_ERROR;
00564 }
00565
00566 template <class ItemType>
00567 status_t
00568 Queue<ItemType>::
00569 AddHead(const ItemType * items, uint32 numItems)
00570 {
00571 if (EnsureSize(_itemCount+numItems) != B_NO_ERROR) return B_ERROR;
00572 for (int i=((int)numItems)-1; i>=0; i--) if (AddHead(items[i]) == B_ERROR) return B_ERROR;
00573 return B_NO_ERROR;
00574 }
00575
00576 template <class ItemType>
00577 status_t
00578 Queue<ItemType>::
00579 RemoveHead(ItemType & returnItem)
00580 {
00581 if (_itemCount == 0) return B_ERROR;
00582 returnItem = _queue[_headIndex];
00583 return RemoveHead();
00584 }
00585
00586 template <class ItemType>
00587 status_t
00588 Queue<ItemType>::
00589 RemoveHead()
00590 {
00591 if (_itemCount == 0) return B_ERROR;
00592 int oldHeadIndex = _headIndex;
00593 _headIndex = NextIndex(_headIndex);
00594 _itemCount--;
00595 _queue[oldHeadIndex] = ItemType();
00596 return B_NO_ERROR;
00597 }
00598
00599 template <class ItemType>
00600 status_t
00601 Queue<ItemType>::
00602 RemoveTail(ItemType & returnItem)
00603 {
00604 if (_itemCount == 0) return B_ERROR;
00605 returnItem = _queue[_tailIndex];
00606 return RemoveTail();
00607 }
00608
00609 template <class ItemType>
00610 status_t
00611 Queue<ItemType>::
00612 RemoveTail()
00613 {
00614 if (_itemCount == 0) return B_ERROR;
00615 int removedItemIndex = _tailIndex;
00616 _tailIndex = PrevIndex(_tailIndex);
00617 _itemCount--;
00618 _queue[removedItemIndex] = ItemType();
00619 return B_NO_ERROR;
00620 }
00621
00622 template <class ItemType>
00623 status_t
00624 Queue<ItemType>::
00625 GetItemAt(uint32 index, ItemType & returnItem) const
00626 {
00627 if (index >= _itemCount) return B_ERROR;
00628 returnItem = _queue[InternalizeIndex(index)];
00629 return B_NO_ERROR;
00630 }
00631
00632 template <class ItemType>
00633 status_t
00634 Queue<ItemType>::
00635 RemoveItemAt(uint32 index, ItemType & returnItem)
00636 {
00637 if (index >= _itemCount) return B_ERROR;
00638 returnItem = _queue[InternalizeIndex(index)];
00639 return RemoveItemAt(index);
00640 }
00641
00642 template <class ItemType>
00643 status_t
00644 Queue<ItemType>::
00645 RemoveItemAt(uint32 index)
00646 {
00647 if (index >= _itemCount) return B_ERROR;
00648
00649 uint32 internalizedIndex = InternalizeIndex(index);
00650 uint32 indexToClear;
00651
00652 if (index < _itemCount/2)
00653 {
00654
00655 while(internalizedIndex != _headIndex)
00656 {
00657 uint32 prev = PrevIndex(internalizedIndex);
00658 _queue[internalizedIndex] = _queue[prev];
00659 internalizedIndex = prev;
00660 }
00661 indexToClear = _headIndex;
00662 _headIndex = NextIndex(_headIndex);
00663 }
00664 else
00665 {
00666
00667 while(internalizedIndex != _tailIndex)
00668 {
00669 uint32 next = NextIndex(internalizedIndex);
00670 _queue[internalizedIndex] = _queue[next];
00671 internalizedIndex = next;
00672 }
00673 indexToClear = _tailIndex;
00674 _tailIndex = PrevIndex(_tailIndex);
00675 }
00676
00677 _itemCount--;
00678 _queue[indexToClear] = ItemType();
00679 return B_NO_ERROR;
00680 }
00681
00682 template <class ItemType>
00683 status_t
00684 Queue<ItemType>::
00685 ReplaceItemAt(uint32 index, const ItemType & newItem)
00686 {
00687 if (index >= _itemCount) return B_ERROR;
00688 _queue[InternalizeIndex(index)] = newItem;
00689 return B_NO_ERROR;
00690 }
00691
00692 template <class ItemType>
00693 status_t
00694 Queue<ItemType>::
00695 InsertItemAt(uint32 index, const ItemType & newItem)
00696 {
00697
00698 if (index > _itemCount) return B_ERROR;
00699 if (index == _itemCount) return AddTail(newItem);
00700 if (index == 0) return AddHead(newItem);
00701
00702
00703 if (index < _itemCount/2)
00704 {
00705
00706 if (AddHead() != B_NO_ERROR) return B_ERROR;
00707 for (uint32 i=0; i<index; i++) ReplaceItemAt(i, *GetItemAt(i+1));
00708 }
00709 else
00710 {
00711
00712 if (AddTail() != B_NO_ERROR) return B_ERROR;
00713 for (int32 i=((int32)_itemCount)-1; i>((int32)index); i--) ReplaceItemAt(i, *GetItemAt(i-1));
00714 }
00715 return ReplaceItemAt(index, newItem);
00716 }
00717
00718 template <class ItemType>
00719 status_t
00720 Queue<ItemType>::
00721 InsertItemsAt(uint32 index, const Queue<ItemType> & queue, uint32 startIndex, uint32 numNewItems)
00722 {
00723 uint32 hisSize = queue.GetNumItems();
00724 numNewItems = muscleMin(numNewItems, (startIndex < hisSize) ? (hisSize-startIndex) : 0);
00725 if (numNewItems == 0) return B_NO_ERROR;
00726 if (index > _itemCount) return B_ERROR;
00727 if (numNewItems == 1)
00728 {
00729 if (index == 0) return AddHead(queue.Head());
00730 if (index == _itemCount) return AddTail(queue.Head());
00731 }
00732
00733 uint32 oldSize = GetNumItems();
00734 uint32 newSize = oldSize+numNewItems;
00735
00736 if (EnsureSize(newSize, true) != B_NO_ERROR) return B_ERROR;
00737 for (uint32 i=index; i<oldSize; i++) (*this)[i+numNewItems] = (*this)[i];
00738 for (uint32 i=index; i<index+numNewItems; i++) (*this)[i] = queue[startIndex++];
00739 return B_NO_ERROR;
00740 }
00741
00742 template <class ItemType>
00743 status_t
00744 Queue<ItemType>::
00745 InsertItemsAt(uint32 index, const ItemType * items, uint32 numNewItems)
00746 {
00747 if (numNewItems == 0) return B_NO_ERROR;
00748 if (index > _itemCount) return B_ERROR;
00749 if (numNewItems == 1)
00750 {
00751 if (index == 0) return AddHead(*items);
00752 if (index == _itemCount) return AddTail(*items);
00753 }
00754
00755 uint32 oldSize = GetNumItems();
00756 uint32 newSize = oldSize+numNewItems;
00757
00758 if (EnsureSize(newSize, true) != B_NO_ERROR) return B_ERROR;
00759 int32 si = 0;
00760 for (uint32 i=index; i<oldSize; i++) (*this)[i+numNewItems] = (*this)[i];
00761 for (uint32 i=index; i<index+numNewItems; i++) (*this)[i] = items[si++];
00762 return B_NO_ERROR;
00763 }
00764
00765 template <class ItemType>
00766 void
00767 Queue<ItemType>::
00768 Clear(bool releaseCachedBuffers)
00769 {
00770 if ((releaseCachedBuffers)&&(_queue != _smallQueue))
00771 {
00772 delete [] _queue;
00773 _queue = NULL;
00774 _queueSize = 0;
00775 _itemCount = 0;
00776 }
00777 else while(RemoveTail() == B_NO_ERROR) {}
00778 }
00779
00780 template <class ItemType>
00781 status_t
00782 Queue<ItemType>::
00783 EnsureSize(uint32 size, bool setNumItems, uint32 extraPreallocs)
00784 {
00785 if ((_queue == NULL)||(_queueSize < size))
00786 {
00787 const uint32 sqLen = ARRAYITEMS(_smallQueue);
00788 uint32 temp = size + extraPreallocs;
00789 uint32 newQLen = muscleMax(_initialSize, ((setNumItems)||(temp <= sqLen)) ? muscleMax(sqLen,temp) : temp);
00790
00791 ItemType * newQueue = ((_queue == _smallQueue)||(newQLen > sqLen)) ? newnothrow_array(ItemType,newQLen) : _smallQueue;
00792 if (newQueue == NULL) {WARN_OUT_OF_MEMORY; return B_ERROR;}
00793 if (newQueue == _smallQueue) newQLen = sqLen;
00794
00795 for (uint32 i=0; i<_itemCount; i++) (void) GetItemAt(i, newQueue[i]);
00796 if (setNumItems) _itemCount = size;
00797 _headIndex = 0;
00798 _tailIndex = _itemCount-1;
00799
00800 if (_queue == _smallQueue)
00801 {
00802 ItemType blank = ItemType();
00803 for (uint32 i=0; i<sqLen; i++) _smallQueue[i] = blank;
00804 }
00805 else delete [] _queue;
00806
00807 _queue = newQueue;
00808 _queueSize = newQLen;
00809 }
00810
00811 if (setNumItems)
00812 {
00813
00814 if (_itemCount < size)
00815 {
00816
00817 _tailIndex = (_tailIndex + (size-_itemCount)) % _queueSize;
00818 _itemCount = size;
00819 }
00820 else while(_itemCount > size) (void) RemoveTail();
00821 }
00822
00823 return B_NO_ERROR;
00824 }
00825
00826 template <class ItemType>
00827 int32
00828 Queue<ItemType>::
00829 IndexOf(const ItemType & item) const
00830 {
00831 if (_queue) for (int i=((int)GetNumItems())-1; i>=0; i--) if (*GetItemAt(i) == item) return i;
00832 return -1;
00833 }
00834
00835
00836 template <class ItemType>
00837 void
00838 Queue<ItemType>::
00839 Swap(uint32 fromIndex, uint32 toIndex)
00840 {
00841 ItemType temp = *(GetItemAt(fromIndex));
00842 ReplaceItemAt(fromIndex, *(GetItemAt(toIndex)));
00843 ReplaceItemAt(toIndex, temp);
00844 }
00845
00846 template <class ItemType>
00847 void
00848 Queue<ItemType>::
00849 Sort(ItemCompareFunc compareFunc, uint32 from, uint32 to, void * cookie)
00850 {
00851 uint32 size = GetNumItems();
00852 if (to > size) to = size;
00853 if (to > from)
00854 {
00855 if (to < from+12)
00856 {
00857
00858 if (to > from+1)
00859 {
00860 for (uint32 i=from+1; i<to; i++)
00861 {
00862 for (uint32 j=i; j>from; j--)
00863 {
00864 int ret = compareFunc(*(GetItemAt(j)), *(GetItemAt(j-1)), cookie);
00865 if (ret < 0) Swap(j, j-1);
00866 else break;
00867 }
00868 }
00869 }
00870 }
00871 else
00872 {
00873
00874 uint32 middle = (from + to)/2;
00875 Sort(compareFunc, from, middle, cookie);
00876 Sort(compareFunc, middle, to, cookie);
00877 Merge(compareFunc, from, middle, to, middle-from, to-middle, cookie);
00878 }
00879 }
00880 }
00881
00882 template <class ItemType>
00883 void
00884 Queue<ItemType>::
00885 ReverseItemOrdering(uint32 from, uint32 to)
00886 {
00887 uint32 size = GetNumItems();
00888 if (size > 0)
00889 {
00890 to--;
00891 if (to >= size) to = size-1;
00892 while (from < to) Swap(from++, to--);
00893 }
00894 }
00895
00896 template <class ItemType>
00897 status_t
00898 Queue<ItemType>::
00899 RemoveFirstInstanceOf(const ItemType & val)
00900 {
00901 uint32 ni = GetNumItems();
00902 for (uint32 i=0; i<ni; i++) if ((*this)[i] == val) return RemoveItemAt(i);
00903 return B_ERROR;
00904 }
00905
00906 template <class ItemType>
00907 status_t
00908 Queue<ItemType>::
00909 RemoveLastInstanceOf(const ItemType & val)
00910 {
00911 for (int32 i=((int32)GetNumItems())-1; i>=0; i--) if ((*this)[i] == val) return RemoveItemAt(i);
00912 return B_ERROR;
00913 }
00914
00915 template <class ItemType>
00916 uint32
00917 Queue<ItemType>::
00918 RemoveAllInstancesOf(const ItemType & val)
00919 {
00920
00921 uint32 ret = 0;
00922 uint32 writeTo = 0;
00923 uint32 origSize = GetNumItems();
00924 for(uint32 readFrom=0; readFrom<origSize; readFrom++)
00925 {
00926 const ItemType & nextRead = (*this)[readFrom];
00927 if (nextRead == val) ret++;
00928 else
00929 {
00930 if (readFrom > writeTo) (*this)[writeTo] = nextRead;
00931 writeTo++;
00932 }
00933 }
00934
00935
00936 for (; writeTo<origSize; writeTo++) RemoveTail();
00937
00938 return ret;
00939 }
00940
00941 template <class ItemType>
00942 void
00943 Queue<ItemType>::
00944 Merge(ItemCompareFunc compareFunc, uint32 from, uint32 pivot, uint32 to, uint32 len1, uint32 len2, void * cookie)
00945 {
00946 if ((len1)&&(len2))
00947 {
00948 if (len1+len2 == 2)
00949 {
00950 if (compareFunc(*(GetItemAt(pivot)), *(GetItemAt(from)), cookie) < 0) Swap(pivot, from);
00951 }
00952 else
00953 {
00954 uint32 first_cut, second_cut;
00955 uint32 len11, len22;
00956 if (len1 > len2)
00957 {
00958 len11 = len1/2;
00959 first_cut = from + len11;
00960 second_cut = Lower(compareFunc, pivot, to, *GetItemAt(first_cut), cookie);
00961 len22 = second_cut - pivot;
00962 }
00963 else
00964 {
00965 len22 = len2/2;
00966 second_cut = pivot + len22;
00967 first_cut = Upper(compareFunc, from, pivot, *GetItemAt(second_cut), cookie);
00968 len11 = first_cut - from;
00969 }
00970
00971
00972 if ((pivot!=first_cut)&&(pivot!=second_cut))
00973 {
00974
00975 uint32 n = pivot-first_cut;
00976 {
00977 uint32 m = second_cut-first_cut;
00978 while(n!=0)
00979 {
00980 uint32 t = m % n;
00981 m=n;
00982 n=t;
00983 }
00984 n = m;
00985 }
00986
00987 while(n--)
00988 {
00989 const ItemType val = *GetItemAt(first_cut+n);
00990 uint32 shift = pivot - first_cut;
00991 uint32 p1 = first_cut+n;
00992 uint32 p2 = p1+shift;
00993 while (p2 != first_cut + n)
00994 {
00995 ReplaceItemAt(p1, *GetItemAt(p2));
00996 p1 = p2;
00997 if (second_cut - p2 > shift) p2 += shift;
00998 else p2 = first_cut + (shift - (second_cut - p2));
00999 }
01000 ReplaceItemAt(p1, val);
01001 }
01002 }
01003
01004 uint32 new_mid = first_cut+len22;
01005 Merge(compareFunc, from, first_cut, new_mid, len11, len22, cookie);
01006 Merge(compareFunc, new_mid, second_cut, to, len1 - len11, len2 - len22, cookie);
01007 }
01008 }
01009 }
01010
01011
01012 template <class ItemType>
01013 uint32
01014 Queue<ItemType>::
01015 Lower(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const
01016 {
01017 if (to > from)
01018 {
01019 uint32 len = to - from;
01020 while (len > 0)
01021 {
01022 uint32 half = len/2;
01023 uint32 mid = from + half;
01024 if (compareFunc(*(GetItemAt(mid)), val, cookie) < 0)
01025 {
01026 from = mid+1;
01027 len = len - half - 1;
01028 }
01029 else len = half;
01030 }
01031 }
01032 return from;
01033 }
01034
01035 template <class ItemType>
01036 uint32
01037 Queue<ItemType>::
01038 Upper(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const
01039 {
01040 if (to > from)
01041 {
01042 uint32 len = to - from;
01043 while (len > 0)
01044 {
01045 uint32 half = len/2;
01046 uint32 mid = from + half;
01047 if (compareFunc(val, *(GetItemAt(mid)), cookie) < 0) len = half;
01048 else
01049 {
01050 from = mid+1;
01051 len = len - half -1;
01052 }
01053 }
01054 }
01055 return from;
01056 }
01057
01058 template <class ItemType>
01059 const ItemType *
01060 Queue<ItemType> :: GetArrayPointerAux(uint32 whichArray, uint32 & retLength) const
01061 {
01062 if (_itemCount > 0)
01063 {
01064 switch(whichArray)
01065 {
01066 case 0:
01067 retLength = (_headIndex <= _tailIndex) ? (_tailIndex-_headIndex)+1 : (_queueSize-_headIndex);
01068 return &_queue[_headIndex];
01069 break;
01070
01071 case 1:
01072 if (_headIndex > _tailIndex)
01073 {
01074 retLength = _tailIndex+1;
01075 return &_queue[0];
01076 }
01077 break;
01078 }
01079 }
01080 return NULL;
01081 }
01082
01083 template <class ItemType>
01084 void
01085 Queue<ItemType>::SwapContents(Queue<ItemType> & that)
01086 {
01087 bool thisSmall = (_queue == _smallQueue);
01088 bool thatSmall = (that._queue == that._smallQueue);
01089
01090 if ((thisSmall)&&(thatSmall))
01091 {
01092
01093 uint32 commonSize = muscleMin(GetNumItems(), that.GetNumItems());
01094 int32 sizeDiff = ((int32)GetNumItems())-((int32)that.GetNumItems());
01095 Queue<ItemType> & copyTo = (sizeDiff > 0) ? that : *this;
01096 Queue<ItemType> & copyFrom = (sizeDiff > 0) ? *this : that;
01097 (void) copyTo.AddTail(copyFrom, commonSize);
01098 (void) copyFrom.EnsureSize(commonSize, true);
01099
01100
01101 for (uint32 i=0; i<commonSize; i++) muscleSwap((*this)[i], that[i]);
01102 }
01103 else if (thisSmall) SwapContentsAux(that);
01104 else if (thatSmall) that.SwapContentsAux(*this);
01105 else
01106 {
01107
01108 muscleSwap(_queue, that._queue);
01109 muscleSwap(_queueSize, that._queueSize);
01110 muscleSwap(_headIndex, that._headIndex);
01111 muscleSwap(_tailIndex, that._tailIndex);
01112 muscleSwap(_itemCount, that._itemCount);
01113 }
01114 }
01115
01116 template <class ItemType>
01117 void
01118 Queue<ItemType>::SwapContentsAux(Queue<ItemType> & largeThat)
01119 {
01120
01121 uint32 ni = GetNumItems();
01122 for (uint32 i=0; i<ni; i++) largeThat._smallQueue[i] = (*this)[i];
01123
01124
01125 _queue = largeThat._queue;
01126 _queueSize = largeThat._queueSize;
01127 _headIndex = largeThat._headIndex;
01128 _tailIndex = largeThat._tailIndex;
01129
01130
01131 if (ni > 0)
01132 {
01133 largeThat._queue = largeThat._smallQueue;
01134 largeThat._queueSize = ARRAYITEMS(largeThat._smallQueue);
01135 largeThat._headIndex = 0;
01136 largeThat._tailIndex = ni-1;
01137 }
01138 else
01139 {
01140 largeThat._queue = NULL;
01141 largeThat._queueSize = 0;
01142
01143 }
01144
01145 muscleSwap(_itemCount, largeThat._itemCount);
01146 }
01147
01148 template <class ItemType>
01149 bool
01150 Queue<ItemType>::StartsWith(const Queue<ItemType> & prefixQueue) const
01151 {
01152 if (prefixQueue.GetNumItems() > GetNumItems()) return false;
01153 uint32 prefixQueueLen = prefixQueue.GetNumItems();
01154 for (uint32 i=0; i<prefixQueueLen; i++) if (!(prefixQueue[i] == (*this)[i])) return false;
01155 return true;
01156 }
01157
01158 template <class ItemType>
01159 bool
01160 Queue<ItemType>::EndsWith(const Queue<ItemType> & suffixQueue) const
01161 {
01162 if (suffixQueue.GetNumItems() > GetNumItems()) return false;
01163 int32 lastToCheck = GetNumItems()-suffixQueue.GetNumItems();
01164 for (int32 i=GetNumItems()-1; i>=lastToCheck; i--) if (!(suffixQueue[i] == (*this)[i])) return false;
01165 return true;
01166 }
01167
01168 template <class ItemType>
01169 void
01170 Queue<ItemType>::Normalize()
01171 {
01172 if ((_itemCount > 0)&&(_headIndex > _tailIndex))
01173 {
01174 if (_itemCount*2 <= _queueSize)
01175 {
01176
01177
01178
01179
01180 uint32 startAt = _tailIndex+1;
01181 for (uint32 i=0; i<_itemCount; i++)
01182 {
01183 ItemType & from = (*this)[i];
01184 _queue[startAt+i] = from;
01185 from = ItemType();
01186 }
01187 _headIndex = startAt;
01188 _tailIndex = startAt+_itemCount-1;
01189 }
01190 else
01191 {
01192
01193
01194
01195
01196 uint32 c = 0;
01197 for (uint32 v = 0; c<_queueSize; v++)
01198 {
01199 uint32 t = v;
01200 uint32 tp = v + _headIndex;
01201 ItemType tmp = _queue[v];
01202 c++;
01203 while(tp != v)
01204 {
01205 _queue[t] = _queue[tp];
01206 t = tp;
01207 tp += _headIndex;
01208 if (tp >= _queueSize) tp -= _queueSize;
01209 c++;
01210 }
01211 _queue[t] = tmp;
01212 }
01213 _headIndex = 0;
01214 _tailIndex = _itemCount-1;
01215 }
01216 }
01217 }
01218
01219 END_NAMESPACE(muscle);
01220
01221 #endif