kipp fb1503758e moved to pub
git-svn-id: svn://10.0.0.236/trunk@165 18797224-902f-48f8-a5cc-f745e15eee43
1998-04-13 20:24:54 +00:00

227 lines
6.5 KiB
C++

/* -*- 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 "nsToken.h"
const PRInt32 kGrowthDelta = 10;
/**-------------------------------------------------------
* Standard constructor
*
* @updated gess 28Feb98
* @param
* @return
*------------------------------------------------------*/
CDeque::CDeque() {
mCapacity=kGrowthDelta;
mOrigin=mSize=0;
mTokens=new CToken*[mCapacity];
}
/**-------------------------------------------------------
* Standard destructor
*
* @updated gess 28Feb98
* @param
* @return
*------------------------------------------------------*/
CDeque::~CDeque() {
Erase();
delete [] mTokens;
}
/*-------------------------------------------------------
* Remove all items from the queue without destroying them.
* @updated gess 28Feb98
* @param
* @return
*------------------------------------------------------*/
void CDeque::Empty() {
for(PRInt32 i=0;i<mCapacity;i++)
mTokens[i]=0;
mSize=0;
mOrigin=0;
}
/*-------------------------------------------------------
* Remove AND DELETE! all items from the queue
* @updated gess 28Feb98
* @param
* @return
*------------------------------------------------------*/
void CDeque::Erase() {
CDequeIterator iter1=Begin();
CDequeIterator iter2=End();
CToken* temp;
while(iter1!=iter2) {
temp=(iter1++);
delete temp;
}
Empty();
}
/*-------------------------------------------------------
* This method adds a token to the end of the queue.
* This operation has the potential to cause the
* underlying buffer to resize.
*
* @updated gess 28Feb98
* @param aToken: new token to be added to queue
* @return nada
*------------------------------------------------------*/
void CDeque::Push(CToken* aToken) {
if(mSize==mCapacity) {
CToken** temp=new CToken*[mCapacity+kGrowthDelta];
//so here's the problem. 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.
PRInt32 tempi=0;
for(PRInt32 i=mOrigin;i<mCapacity;i++) temp[tempi++]=mTokens[i]; //copy the leading elements...
for(PRInt32 j=0;j<mOrigin;j++) temp[tempi++]=mTokens[j]; //copy the trailing elements...
mCapacity+=kGrowthDelta;
mOrigin=0; //now realign the origin...
delete[]mTokens;
mTokens=temp;
}
PRInt32 offset=mOrigin+mSize;
if(offset<mCapacity)
mTokens[offset]=aToken;
else mTokens[offset-mCapacity]=aToken;
mSize++;
}
/*-------------------------------------------------------
* This method gets called when a caller wants
* to remove the first element from the queue.
* Pop() never causes the underlying buffer to resize.
*
* @updated gess 28Feb98
* @param nada
* @return first token in queue (if any) or null
*------------------------------------------------------*/
CToken* CDeque::Pop() {
CToken* result=0;
if(mSize>0) {
result=mTokens[mOrigin];
mTokens[mOrigin++]=0; //zero it out for debugging purposes.
mSize--;
if(0==mSize)
mOrigin=0;
}
return result;
}
/*-------------------------------------------------------
* Get the ith element (in relative terms) not absolute
* index pos. Don't forget the origin may be anywhere.
*
* @updated gess 28Feb98
* @param anIndex: 0 relative index
* @return CToken* or null.
*------------------------------------------------------*/
CToken* CDeque::ObjectAt(PRInt32 anIndex) {
CToken* result=0;
if((anIndex>=0) && (anIndex<mSize))
{
PRInt32 pos=mOrigin+anIndex;
if(pos<mCapacity)
result=mTokens[pos];
else result=mTokens[anIndex-1];
}
return result;
}
/*-------------------------------------------------------
* Create and return an iterator pointing to
* the beginning of the queue. Note that this
* takes the circular buffer semantics into account.
*
* @updated gess 28Feb98
* @param none
* @return a newly created CDequeIterator()
*------------------------------------------------------*/
CDequeIterator CDeque::Begin(void) {
return CDequeIterator(*this,0);
}
/*-------------------------------------------------------
* Create and return an iterator pointing to
* the end of the queue. Note that this takes the
* circular buffer semantics into account.
*
* @updated gess 28Feb98
* @param none
* @return a newly created CDequeIterator()
*------------------------------------------------------*/
CDequeIterator CDeque::End(void) {
return CDequeIterator(*this,mSize);
}
/**-------------------------------------------------------
* @updated gess 28Feb98
* @param
* @return
*------------------------------------------------------*/
void CDeque::SelfTest(void) {
#ifdef _DEBUG
CDeque* theDeck= new CDeque();
CToken* a=new CToken(nsAutoString("")); a->SetOrdinal(10);
CToken* b=new CToken(nsAutoString("")); b->SetOrdinal(20);
CToken* c=new CToken(nsAutoString("")); c->SetOrdinal(30);
CToken* d=new CToken(nsAutoString("")); d->SetOrdinal(40);
CToken* e=new CToken(nsAutoString("")); e->SetOrdinal(50);
CToken* f=new CToken(nsAutoString("")); f->SetOrdinal(60);
theDeck->Push(a);
theDeck->Push(b);
theDeck->Push(c);
CToken* temp=theDeck->Pop(); //temp should == a
temp=theDeck->Pop(); //temp should == b
theDeck->Push(d);
theDeck->Push(e);
CDequeIterator iter1=theDeck->Begin();
CDequeIterator iter2=theDeck->End();
while(iter1!=iter2) {
temp=(iter1++);
cout << temp->GetOrdinal();
}
theDeck->Push(f); //should cause queue to resize and resequence.
CDequeIterator iter3=theDeck->Begin();
CDequeIterator iter4=theDeck->End();
while(iter3!=iter4) {
temp=(iter3++);
cout << temp->GetOrdinal();
}
delete a;
delete b;
delete c;
delete d;
delete e;
delete f;
delete theDeck;
#endif
}