/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "nsDeque.h" #include "nsCRT.h" //#define _SELFTEST_DEQUE 1 #undef _SELFTEST_DEQUE /** * Standard constructor * @update gess4/18/98 * @return new deque */ nsDeque::nsDeque(nsDequeFunctor& aMemDestroyer) : mMemDestroyer(aMemDestroyer) { mMemDestroyer=aMemDestroyer; mCapacity=eGrowthDelta; mOrigin=mSize=0; mData=new void*[mCapacity]; } /** * Destructor * @update gess4/18/98 */ nsDeque::~nsDeque() { Erase(); delete [] mData; mData=0; } /** * Returns the number of elements currently stored in * this deque. * * @update gess4/18/98 * @param * @return int contains element count */ PRInt32 nsDeque::GetSize(void) const { return mSize; } /** * Remove all items from container without destroying them. * * @update gess4/18/98 * @param * @return */ nsDeque& nsDeque::Empty() { nsCRT::zero(mData,mCapacity*sizeof(mData)); mSize=0; mOrigin=0; return *this; } /** * Remove and delete all items from container * * @update gess4/18/98 * @return this */ nsDeque& nsDeque::Erase() { ForEach(mMemDestroyer); return Empty(); } /** * This method adds an item to the end of the deque. * This operation has the potential to cause the * underlying buffer to resize. * * @update gess4/18/98 * @param anItem: new item to be added to deque * @return nada */ nsDeque& nsDeque::Push(void* anItem) { if(mSize==mCapacity) { void** temp=new void*[mCapacity+eGrowthDelta]; //Here's the interesting part: You can't just move the elements //directy (in situ) from the old buffer to the new one. //Since capacity has changed, the old origin doesn't make //sense anymore. It's better to resequence the elements now. int tempi=0; int i=0; int j=0; for(i=mOrigin;i0) { mOrigin-=1; mData[mOrigin]=anItem; mSize++; } else { Push(anItem); mOrigin=mSize-1; } return *this; } /** * Remove and return the last item in the container. * * @update gess4/18/98 * @param none * @return ptr to last item in container */ void* nsDeque::Pop(void) { void* result=0; if(mSize>0) { int offset=mOrigin+mSize-1; if(offset>=mCapacity) offset-=mCapacity; result=mData[offset]; mData[offset]=0; mSize--; if(0==mSize) mOrigin=0; } return result; } /** * This method gets called you want to remove and return * the first member in the container. * * @update gess4/18/98 * @param nada * @return last item in container */ void* nsDeque::PopFront() { void* result=0; if(mSize>0) { result=mData[mOrigin]; mData[mOrigin++]=0; //zero it out for debugging purposes. mSize--; if(mCapacity==mOrigin) //you popped off the end, so cycle back around... mOrigin=0; if(0==mSize) mOrigin=0; } NS_ASSERTION(mOrigin0) { result=mData[mOrigin]; } return result; } /** * Call this to retrieve the ith element from this container. * Keep in mind that accessing the underlying elements is * done in a relative fashion. Object 0 is not necessarily * the first element (the first element is at mOrigin). * * @update gess4/18/98 * @param anIndex : 0 relative offset of item you want * @return void* or null */ void* nsDeque::ObjectAt(PRInt32 anIndex) const { void* result=0; if((anIndex>=0) && (anIndexoperator==(anIter)); } /** * Compare 2 iterators for equivalence. * * @update gess4/18/98 * @param anIter is the other iterator to be compared to * @return TRUE if EQUAL */ PRBool nsDequeIterator::operator<(nsDequeIterator& anIter) { return PRBool(((mIndex=(nsDequeIterator& anIter) { return PRBool(((mIndex>=anIter.mIndex) && (&mDeque==&anIter.mDeque))); } /** * Pre-increment operator * * @update gess4/18/98 * @return object at preincremented index */ void* nsDequeIterator::operator++() { return mDeque.ObjectAt(++mIndex); } /** * Post-increment operator * * @update gess4/18/98 * @param param is ignored * @return object at post-incremented index */ void* nsDequeIterator::operator++(int) { return mDeque.ObjectAt(mIndex++); } /** * Pre-decrement operator * * @update gess4/18/98 * @return object at pre-decremented index */ void* nsDequeIterator::operator--() { return mDeque.ObjectAt(--mIndex); } /** * Post-decrement operator * * @update gess4/18/98 * @param param is ignored * @return object at post-decremented index */ void* nsDequeIterator::operator--(int) { return mDeque.ObjectAt(mIndex--); } /** * Dereference operator * * @update gess4/18/98 * @return object at ith index */ void* nsDequeIterator::GetCurrent(void) { return mDeque.ObjectAt(mIndex); } /** * Call this method when you wanto to iterate all the * members of the container, passing a functor along * to call your code. * * @update gess4/20/98 * @param aFunctor object to call for each member * @return *this */ void nsDequeIterator::ForEach(nsDequeFunctor& aFunctor) const{ mDeque.ForEach(aFunctor); } /** * Call this method when you wanto to iterate all the * members of the container, passing a functor along * to call your code. * * @update gess4/20/98 * @param aFunctor object to call for each member * @return *this */ const void* nsDequeIterator::FirstThat(nsDequeFunctor& aFunctor) const{ return mDeque.FirstThat(aFunctor); } #ifdef _SELFTEST_DEQUE /************************************************************** Now define the token deallocator class... **************************************************************/ class _SelfTestDeallocator: public nsDequeFunctor{ public: _SelfTestDeallocator::_SelfTestDeallocator() { nsDeque::SelfTest(); } virtual void* operator()(void* anObject) { return 0; } }; static _SelfTestDeallocator gDeallocator; #endif /** * conduct automated self test for this class * * @update gess4/18/98 * @param * @return */ void nsDeque::SelfTest(void) { #ifdef _SELFTEST_DEQUE { nsDeque theDeque(gDeallocator); //construct a simple one... int ints[200]; int count=sizeof(ints)/sizeof(int); int i=0; for(i=0;i