home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tlx501.zip
/
TEMPLATE
/
QUEUE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-05
|
13KB
|
429 lines
/****************************************************************************
$Id: queue.cpp 501.0 1995/03/07 12:27:00 RON Exp $
Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
Project: Tarma Library for C++ V5.0
Author: Ron van der Wal
Implementation of class TLQueue<T>.
$Log: queue.cpp $
Revision 501.0 1995/03/07 12:27:00 RON
Updated for TLX 5.01
Revision 1.6 1995/01/31 16:30:48 RON
Update for release 012
Added partial support for SunPro C++ compiler
Revision 1.5 1994/09/28 14:41:39 ron
Removed Macintosh-style #include references
Revision 1.4 1994/09/27 20:27:29 ron
Changed path separator from / to \
Revision 1.3 1994/09/26 15:33:53 ron
Changed include file references
Revision 1.2 1994/09/07 15:47:32 ron
Corrected subtle but deadly mistakes in the assumptions about mLeft and
mRight w.r.t. insertion and extraction
Revision 1.1 1994/08/16 18:15:30 ron
Initial revision
****************************************************************************/
#ifndef _TLX_QUEUE_CPP
#define _TLX_QUEUE_CPP
//----- Project headers
#ifndef _TLX_ARRAYS_H
#include <tlx\501\arrays.h>
#endif
#ifndef _TLX_DEBUG_H
#include <tlx\501\debug.h>
#endif
#ifndef _TLX_EXCEPT_H
#include <tlx\501\except.h>
#endif
#ifndef _TLX_SEQBASE_CPP
#include <tlx\501\template\seqbase.cpp>
#endif
/*-------------------------------------------------------------------------*/
template<class T> TLQueue<T>::TLQueue(size_t size, size_t delta)
/* Constructor, creating a queue with the given initial capacity and
expansion factor.
---------------------------------------------------------------------------*/
: TLSeqBase<T>(size, delta)
{
RemoveAll();
}
/*-------------------------------------------------------------------------*/
template<class T> TLQueue<T>::TLQueue(const T &t)
/* Constructor creating a single element queue. The queue cannot be
expanded initially.
---------------------------------------------------------------------------*/
: TLSeqBase<T>(t)
{
mLeft = 0;
mRight = mSize;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::AddLeft(const T &t)
/* Adds a new element at the left end of the queue.
---------------------------------------------------------------------------*/
{
if (IsFull())
Expand();
TLX_ASSERT(Available() >= 1);
if (--mLeft < 0)
mLeft = mSize - 1;
mVect[mLeft] = t;
mCount++;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::AddRight(const T &t)
/* Adds a new element at the right end of the queue.
---------------------------------------------------------------------------*/
{
if (IsFull())
Expand();
TLX_ASSERT(Available() >= 1);
mVect[mRight] = t;
if (++mRight >= mSize)
mRight = 0;
mCount++;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::CompactStorage()
/* Function to adjust the physical storage for the queue to exactly fit
its logical contents. Not implemented currently.
---------------------------------------------------------------------------*/
{
TLX_NOTIMPLEMENTED(TLQueue<T>::CompactStorage());
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::EnqueueUnique(const T &t)
/* Enqueues a new element if it doesn't yet appear in the queue.
---------------------------------------------------------------------------*/
{
if (!Contains(t))
Enqueue(t);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::Expand()
/* Expands the queue by mDelta elements. If the queue cannot be expanded
for some reason, a TLXFull exception is thrown.
---------------------------------------------------------------------------*/
{
// The ExpandBy() function creates room at the end of the underlying
// vector. In order to be useful for the circular queue, we must move
// the newly created gap to the mRight position, which isn't necessarily
// at the end of the vector. The gap is mDelta elements long.
//
// We assume that this function is only called when the queue is full,
// i.e. mLeft == mRight and mCount == mSize.
TLX_ASSERT(mLeft == mRight);
TLX_ASSERT(mCount == mSize);
size_t oldsize = mSize;
if (mDelta == 0)
THROW(TLXFull(LOCUS));
ExpandBy(mDelta);
if (mLeft > 0) // Gap must be somewhere in the middle
{
TLX_ASSERT(oldsize > mLeft);
TLX_ASSERT(oldsize + mDelta == mSize);
for (size_t i = oldsize - 1; i >= mLeft; --i)
mVect[i + mDelta] = mVect[i];
mLeft += mDelta;
}
else // Gap must go at the end
mRight = oldsize;
}
/*-------------------------------------------------------------------------*/
template<class T> T TLQueue<T>::ExtractLeft()
/* Removes and returns the leftmost element from the queue.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
index_t lft = mLeft;
if (++mLeft >= mSize)
mLeft = 0;
TLX_ASSERT(mCount > 0);
mCount--;
return mVect[lft];
}
/*-------------------------------------------------------------------------*/
template<class T> T TLQueue<T>::ExtractRight()
/* Removes and returns the rightmost element from the queue.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
if (--mRight < 0)
mRight = mSize - 1;
TLX_ASSERT(mCount > 0);
mCount--;
return mVect[mRight];
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLQueue<T>::IterFirst(iter_t &i) const
/* Initializes the iterator to address the first item in the queue.
Returns nonzero if the iterator is valid after the operation, else
zero.
---------------------------------------------------------------------------*/
{
i.ix = mLeft;
return !IsEmpty();
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLQueue<T>::IterLast(iter_t &i) const
/* Initializes the iterator to address the last item in the queue.
Returns nonzero if the iterator is valid after the operation, else
zero.
---------------------------------------------------------------------------*/
{
i.ix = mRight - 1;
if (i.ix < 0)
i.ix = mSize - 1;
return !IsEmpty();
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLQueue<T>::IterNext(iter_t &i) const
/* Advances the iterator to address the next (rightward moving) item in
the queue. Returns nonzero if the iterator is valid after the operation,
else zero.
---------------------------------------------------------------------------*/
{
if (++i.ix >= mSize)
i.ix = 0;
// Note: we use the '> mLeft' test to ensure termination
if (mRight >= mLeft)
return i.ix < mRight;
else
return i.ix > mLeft || i.ix < mRight;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLQueue<T>::IterPrev(iter_t &i) const
/* Advances the iterator to address the previous (leftward moving) item in
the queue. Returns nonzero if the iterator is valid after the operation,
else zero.
---------------------------------------------------------------------------*/
{
if (--i.ix < 0)
i.ix = mSize - 1;
if (mRight >= mLeft)
return i.ix >= mLeft;
else
return i.ix >= mLeft || i.ix < mRight;
}
/*-------------------------------------------------------------------------*/
template<class T> index_t TLQueue<T>::MapIndex(index_t i) const
/* Converts logical indices to physical indices for the queue. The
logical indices range from 1 to Count(), while the physical start
at mLeft and end at mRight. We must be careful to take the effects
of wrap-around into account.
---------------------------------------------------------------------------*/
{
// Watch out for integer overflow!
if (--i > mSize - mLeft)
return i - (mSize - mLeft);
else
return i + mLeft;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLQueue<T>::OK() const
/* Checks the class invariants.
---------------------------------------------------------------------------*/
{
return TLSeqBase<T>::OK() && mLeft < mSize && mRight < mSize;
}
/*-------------------------------------------------------------------------*/
template<class T> TLQueue<T> &TLQueue<T>::operator =(const T &t)
/* Overloading of the assignment operator that assigns a single element
to the queue. The previous queue elements are lost.
---------------------------------------------------------------------------*/
{
RemoveAll();
Enqueue(t);
return *this;
}
/*-------------------------------------------------------------------------*/
template<class T> TLQueue<T> &TLQueue<T>::operator =(const TLQueue<T> &s)
/* Overloading of the assignment operator.
---------------------------------------------------------------------------*/
{
if (this != &s)
{
TLSeqBase<T>::operator =(s);
mLeft = s.mLeft;
mRight = s.mRight;
}
return *this;
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLQueue<T>::PeekLeft()
/* Returns a reference to the leftmost element in the queue. If the queue
is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return mVect[mLeft];
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLQueue<T>::PeekLeft() const
/* Returns a reference to the leftmost element in the queue. If the queue
is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return mVect[mLeft];
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLQueue<T>::PeekRight()
/* Returns a reference to the rightmost element in the queue. If the queue
is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return mVect[mRight > 0 ? mRight - 1 : mSize - 1];
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLQueue<T>::PeekRight() const
/* Returns a reference to the rightmost element in the queue. If the queue
is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return mVect[mRight > 0 ? mRight - 1 : mSize - 1];
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::RemoveAll()
/* Removes all elements from the queue.
---------------------------------------------------------------------------*/
{
TLSeqBase<T>::RemoveAll();
mLeft = mRight = 0;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::RemoveLeft()
/* Removes the leftmost element from the queue.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
if (++mLeft >= mSize)
mLeft = 0;
TLX_ASSERT(mCount > 0);
mCount--;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLQueue<T>::RemoveRight()
/* Removes and returns the rightmost element from the queue.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
if (--mRight < 0)
mRight = mSize - 1;
TLX_ASSERT(mCount > 0);
mCount--;
}
/*-------------------------------------------------------------------------*/
template<class T> index_t TLQueue<T>::UnmapIndex(index_t i) const
/* Converts physical indices to logical indices for the queue. The
logical indices range from 1 to Count(), while the physical start
at mLeft and end at mRight. We must be careful to take the effects
of wrap-around into account.
---------------------------------------------------------------------------*/
{
// Watch out for integer overflow!
if (i >= mLeft)
return i - mLeft + 1;
else
return i + (mSize - mLeft) + 1;
}
#endif // _TLX_QUEUE_CPP