Thread View: comp.sys.mac.oop.macapp3
1 messages
1 total messages
Started by AMERICA
Wed, 16 Dec 1992 11:15
bugs in CArrayIterator
Author: AMERICA
Date: Wed, 16 Dec 1992 11:15
Date: Wed, 16 Dec 1992 11:15
107 lines
4686 bytes
4686 bytes
Dear Colleagues,
There is a bug in CArrayIterator::DeleteElementAt, which causes improper
behavior when a whole range of elements is deleted at a time (theCount > 1)
and the lower bound, the upper bound, or the current index is in that range.
(I found this bug when halfway through the iteration I deleted all array
elements and suddenly found out that the current index had become negative.)
Here is my version of the method, which fixes the problem:
void CArrayIterator::DeleteElementAt(ArrayIndex theIndex, ArrayIndex theCount)
{
// tuck the endpoints of the iteration in to match
if (theIndex < fLowBound)
fLowBound = Max (fLowBound - theCount, theIndex);
// This is equivalent to:
// if (theIndex + theCount <= fLowBound)
// fLowBound -= theCount;
// // whole deleted range is below fLowBound
// else
// fLowBound = theIndex;
// // new index of the first element not deleted
if (theIndex <= fHighBound)
fHighBound = Max (fHighBound - theCount, theIndex - 1);
// Similar: theIndex - 1 is the last element not deleted.
// Now bend the fCurrentIndex to account for the deletion.
// In case the current item is deleted, we give fCurrentIndex such a
// value that AFTER calling the method advance it will point to the n
ext
// element to be processed.
if (fIterateForward) {
if (theIndex <= fCurrentIndex)
fCurrentIndex = Max (fCurrentIndex - theCount, theIndex - 1);
}
else { // Iterating backwards
if (theIndex < fCurrentIndex)
fCurrentIndex = Max (fCurrentIndex - theCount, theIndex);
}
// hand off control to the next link until you hit the last link in t
he circular chain
if (fNextLink != fDynamicArray->fIteratorPtr)
fNextLink->DeleteElementAt(theIndex, theCount);
} // CArrayIterator::DeleteElementAt
There is another bug in CArrayIterator::IArrayIterator, which turns up if you
specify a lower bound that is higher than the upper bound. In this case, the
iteration should be empty, but instead the element at the upper bound will be
processed. The following version of the method corrects the problem:
void CArrayIterator::IArrayIterator(TDynamicArray* itsDynamicArray,
ArrayIndex itsLowBound,
ArrayIndex itsHighBound,
Boolean itsForward)
{
fNextLink = this;
fPreviousLink = this;
fIterateForward = itsForward;
fDynamicArray = itsDynamicArray;
// Trim the iteration bounds to the array bounds, but allow empty ran
ge.
fHighBound= MinMax(kEmptyIndex,itsHighBound,itsDynamicArray->GetSize(
));
fLowBound = MinMax(1, itsLowBound, fHighBound + 1);
if (fLowBound > fHighBound) { // empty iteration
fLowBound = kEmptyIndex;
fHighBound = kEmptyIndex;
}
// set the initial value of the current index based on the direction
of the iteration.
else if (fIterateForward)
fCurrentIndex = fLowBound;
else
fCurrentIndex = fHighBound;
// Make sure that the fCurrentIndex counter and Iteration direction f
lag from
// an Iterator are used so that the fCurrentIndex counter can be "ben
t" if anyone
// else deletes or inserts elements while the iteration is in progres
s. Pretty slick, eh?
// link me in to the list of iterations in progress
fDynamicArray->fIteratorPtr = this->AppendToList(fDynamicArray->fIter
atorPtr);
// Setup the FailInfo to catch any failures while this object is in s
cope
// giving control to the HandleFailure method
CatchFailures(this->fFailInfo, (CatchFailuresType) & CArrayIterator::
HandleFailure, this);
} // CArrayIterator::IArrayIterator
Pierre America
Philips Research Laboratories
P. O. Box 80.000
5600 JA Eindhoven
The Netherlands
Internet: america@prl.philips.nl
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads