home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!stanford.edu!apple!applelink.apple.com
- From: AMERICA@PRL.PHILIPS.NL
- Newsgroups: comp.sys.mac.oop.macapp3
- Subject: bugs in CArrayIterator
- Message-ID: <9212161015.AA00359@istw80.prl.philips.nl>
- Date: 16 Dec 92 11:15:00 GMT
- Sender: daemon@Apple.COM
- Organization: AppleLink Gateway
- Lines: 107
-
- 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
-