home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sys / mac / oop / macapp3 / 219 < prev    next >
Encoding:
Internet Message Format  |  1992-12-16  |  4.5 KB

  1. Path: sparky!uunet!stanford.edu!apple!applelink.apple.com
  2. From: AMERICA@PRL.PHILIPS.NL
  3. Newsgroups: comp.sys.mac.oop.macapp3
  4. Subject: bugs in CArrayIterator
  5. Message-ID: <9212161015.AA00359@istw80.prl.philips.nl>
  6. Date: 16 Dec 92 11:15:00 GMT
  7. Sender: daemon@Apple.COM
  8. Organization: AppleLink Gateway
  9. Lines: 107
  10.  
  11. Dear Colleagues,
  12.  
  13. There is a bug in CArrayIterator::DeleteElementAt, which causes improper
  14. behavior when a whole range of elements is deleted at a time (theCount > 1)
  15. and the lower bound, the upper bound, or the current index is in that range.
  16. (I found this bug when halfway through the iteration I deleted all array
  17. elements and suddenly found out that the current index had become negative.)
  18.  
  19. Here is my version of the method, which fixes the problem:
  20.  
  21. void CArrayIterator::DeleteElementAt(ArrayIndex theIndex, ArrayIndex theCount)
  22. {
  23.         // tuck the endpoints of the iteration in to match
  24.         if (theIndex < fLowBound)
  25.                 fLowBound = Max (fLowBound - theCount, theIndex);
  26.                 // This is equivalent to:
  27.                 //      if (theIndex + theCount <= fLowBound)
  28.                 //              fLowBound -= theCount;
  29.                 //              // whole deleted range is below fLowBound
  30.                 //      else
  31.                 //              fLowBound = theIndex;
  32.                 //              // new index of the first element not deleted
  33.  
  34.         if (theIndex <= fHighBound)
  35.                 fHighBound = Max (fHighBound - theCount, theIndex - 1);
  36.                 // Similar: theIndex - 1 is the last element not deleted.
  37.  
  38.         // Now bend the fCurrentIndex to account for the deletion.
  39.         // In case the current item is deleted, we give fCurrentIndex such a
  40.         // value that AFTER calling the method advance it will point to the n
  41. ext
  42.         // element to be processed.
  43.         if (fIterateForward) {
  44.             if (theIndex <= fCurrentIndex)
  45.                 fCurrentIndex = Max (fCurrentIndex - theCount, theIndex - 1);
  46.         }
  47.         else {  // Iterating backwards
  48.             if (theIndex < fCurrentIndex)
  49.                 fCurrentIndex = Max (fCurrentIndex - theCount, theIndex);
  50.         }
  51.  
  52.         // hand off control to the next link until you hit the last link in t
  53. he circular chain
  54.         if (fNextLink != fDynamicArray->fIteratorPtr)
  55.                 fNextLink->DeleteElementAt(theIndex, theCount);
  56. } // CArrayIterator::DeleteElementAt
  57.  
  58.  
  59. There is another bug in CArrayIterator::IArrayIterator, which turns up if you
  60. specify a lower bound that is higher than the upper bound. In this case, the
  61. iteration should be empty, but instead the element at the upper bound will be
  62. processed. The following version of the method corrects the problem:
  63.  
  64. void CArrayIterator::IArrayIterator(TDynamicArray* itsDynamicArray,
  65.                                     ArrayIndex itsLowBound,
  66.                                     ArrayIndex itsHighBound,
  67.                                     Boolean itsForward)
  68. {
  69.         fNextLink = this;
  70.         fPreviousLink = this;
  71.         fIterateForward = itsForward;
  72.         fDynamicArray = itsDynamicArray;
  73.  
  74.         // Trim the iteration bounds to the array bounds, but allow empty ran
  75. ge.
  76.         fHighBound= MinMax(kEmptyIndex,itsHighBound,itsDynamicArray->GetSize(
  77. ));
  78.         fLowBound = MinMax(1, itsLowBound, fHighBound + 1);
  79.  
  80.         if (fLowBound > fHighBound) {   // empty iteration
  81.                 fLowBound = kEmptyIndex;
  82.                 fHighBound = kEmptyIndex;
  83.         }
  84.  
  85.         // set the initial value of the current index based on the direction
  86. of the iteration.
  87.         else if (fIterateForward)
  88.                 fCurrentIndex = fLowBound;
  89.         else
  90.                 fCurrentIndex = fHighBound;
  91.  
  92.         // Make sure that the fCurrentIndex counter and Iteration direction f
  93. lag from
  94.         // an Iterator are used so that the fCurrentIndex counter can be "ben
  95. t" if anyone
  96.         // else deletes or inserts elements while the iteration is in progres
  97. s. Pretty slick, eh?
  98.  
  99.         // link me in to the list of iterations in progress
  100.         fDynamicArray->fIteratorPtr = this->AppendToList(fDynamicArray->fIter
  101. atorPtr);
  102.  
  103.         // Setup the FailInfo to catch any failures while this object is in s
  104. cope
  105.         // giving control to the HandleFailure method
  106.         CatchFailures(this->fFailInfo, (CatchFailuresType) & CArrayIterator::
  107. HandleFailure, this);
  108. } // CArrayIterator::IArrayIterator
  109.  
  110.  
  111. Pierre America
  112. Philips Research Laboratories
  113. P. O. Box 80.000
  114. 5600 JA Eindhoven
  115. The Netherlands
  116.  
  117. Internet: america@prl.philips.nl
  118.