API 0.9.5
Foundation/CPIndexSet.j
Go to the documentation of this file.
00001 /*
00002  * CPIndexSet.j
00003  * Foundation
00004  *
00005  * Created by Francisco Tolmasky.
00006  * Copyright 2008, 280 North, Inc.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 
00024 #define _CPMaxRange(aRange) ((aRange).location + (aRange).length)
00025 #define _CPMakeRange(aLocation, aLength) { location:(aLocation), length:aLength }
00026 #define _CPMakeRangeCopy(aRange) { location:(aRange).location, length:(aRange).length }
00027 
00036 @implementation CPIndexSet : CPObject
00037 {
00038     unsigned    _count;
00039     CPArray     _ranges;
00040 }
00041 
00042 // Creating an Index Set
00046 + (id)indexSet
00047 {
00048     return [[self alloc] init];
00049 }
00050 
00054 + (id)indexSetWithIndex:(int)anIndex
00055 {
00056     return [[self alloc] initWithIndex:anIndex];
00057 }
00058 
00063 + (id)indexSetWithIndexesInRange:(CPRange)aRange
00064 {
00065     return [[self alloc] initWithIndexesInRange:aRange];
00066 }
00067 
00068 // Initializing and Index Set
00069 
00070 - (id)init
00071 {
00072     return [self initWithIndexesInRange:_CPMakeRange(0, 0)];
00073 }
00074 
00079 - (id)initWithIndex:(CPInteger)anIndex
00080 {
00081     return [self initWithIndexesInRange:_CPMakeRange(anIndex, 1)];
00082 }
00083 
00089 - (id)initWithIndexesInRange:(CPRange)aRange
00090 {
00091     self = [super init];
00092 
00093     if (self)
00094     {
00095         _count = MAX(0, aRange.length);
00096 
00097         if (_count > 0)
00098             _ranges = [aRange];
00099         else
00100             _ranges = [];
00101     }
00102 
00103     return self;
00104 }
00105 
00111 - (id)initWithIndexSet:(CPIndexSet)anIndexSet
00112 {
00113     self = [super init];
00114 
00115     if (self)
00116     {
00117         _count = [anIndexSet count];
00118         _ranges = [];
00119 
00120         var otherRanges = anIndexSet._ranges,
00121             otherRangesCount = otherRanges.length;
00122 
00123         while (otherRangesCount--)
00124             _ranges[otherRangesCount] = _CPMakeRangeCopy(otherRanges[otherRangesCount]);
00125     }
00126 
00127     return self;
00128 }
00129 
00130 - (BOOL)isEqual:(id)anObject
00131 {
00132     if (self === anObject)
00133         return YES;
00134 
00135     if (!anObject || ![anObject isKindOfClass:[CPIndexSet class]])
00136         return NO;
00137 
00138     return [self isEqualToIndexSet:anObject];
00139 }
00140 
00141 // Querying an Index Set
00147 - (BOOL)isEqualToIndexSet:(CPIndexSet)anIndexSet
00148 {
00149     if (!anIndexSet)
00150         return NO;
00151 
00152     // Comparisons to ourself are always return YES.
00153     if (self === anIndexSet)
00154        return YES;
00155 
00156     var rangesCount = _ranges.length,
00157         otherRanges = anIndexSet._ranges;
00158 
00159     // If we have a discrepancy in the number of ranges or the number of indexes,
00160     // simply return NO.
00161     if (rangesCount !== otherRanges.length || _count !== anIndexSet._count)
00162         return NO;
00163 
00164     while (rangesCount--)
00165         if (!CPEqualRanges(_ranges[rangesCount], otherRanges[rangesCount]))
00166             return NO;
00167 
00168     return YES;
00169 }
00170 
00171 - (BOOL)isEqual:(id)anObject
00172 {
00173     return  self === anObject ||
00174             [anObject isKindOfClass:[self class]] &&
00175             [self isEqualToIndexSet:anObject];
00176 }
00177 
00183 - (BOOL)containsIndex:(CPInteger)anIndex
00184 {
00185     return positionOfIndex(_ranges, anIndex) !== CPNotFound;
00186 }
00187 
00192 - (BOOL)containsIndexesInRange:(CPRange)aRange
00193 {
00194     if (aRange.length <= 0)
00195         return NO;
00196 
00197     // If we have less total indexes than aRange, we can't possibly contain aRange.
00198     if (_count < aRange.length)
00199         return NO;
00200 
00201     // Search for first location
00202     var rangeIndex = positionOfIndex(_ranges, aRange.location);
00203 
00204     // If we don't have the first location, then we don't contain aRange.
00205     if (rangeIndex === CPNotFound)
00206         return NO;
00207 
00208     var range = _ranges[rangeIndex];
00209 
00210     // The intersection must contain all the indexes from the original range.
00211     return CPIntersectionRange(range, aRange).length === aRange.length;
00212 }
00213 
00218 - (BOOL)containsIndexes:(CPIndexSet)anIndexSet
00219 {
00220     var otherCount = anIndexSet._count;
00221 
00222     if (otherCount <= 0)
00223         return YES;
00224 
00225     // If we have less total indexes than anIndexSet, we can't possibly contain aRange.
00226     if (_count < otherCount)
00227         return NO;
00228 
00229     var otherRanges = anIndexSet._ranges,
00230         otherRangesCount = otherRanges.length;
00231 
00232     while (otherRangesCount--)
00233         if (![self containsIndexesInRange:otherRanges[otherRangesCount]])
00234             return NO;
00235 
00236     return YES;
00237 }
00238 
00244 - (BOOL)intersectsIndexesInRange:(CPRange)aRange
00245 {
00246     if (_count <= 0)
00247         return NO;
00248 
00249     var lhsRangeIndex = assumedPositionOfIndex(_ranges, aRange.location);
00250 
00251     if (FLOOR(lhsRangeIndex) === lhsRangeIndex)
00252         return YES;
00253 
00254     var rhsRangeIndex = assumedPositionOfIndex(_ranges, _CPMaxRange(aRange) - 1);
00255 
00256     if (FLOOR(rhsRangeIndex) === rhsRangeIndex)
00257         return YES;
00258 
00259     return lhsRangeIndex !== rhsRangeIndex;
00260 }
00261 
00265 - (int)count
00266 {
00267     return _count;
00268 }
00269 
00270 // Accessing Indexes
00274 - (CPInteger)firstIndex
00275 {
00276     if (_count > 0)
00277         return _ranges[0].location;
00278 
00279     return CPNotFound;
00280 }
00281 
00285 - (CPInteger)lastIndex
00286 {
00287     if (_count > 0)
00288         return _CPMaxRange(_ranges[_ranges.length - 1]) - 1;
00289 
00290     return CPNotFound;
00291 }
00292 
00297 - (CPInteger)indexGreaterThanIndex:(CPInteger)anIndex
00298 {
00299     // The first possible index that would satisfy this requirement.
00300     ++anIndex;
00301 
00302     // Attempt to find it or something bigger.
00303     var rangeIndex = assumedPositionOfIndex(_ranges, anIndex);
00304 
00305     // Nothing at all found?
00306     if (rangeIndex === CPNotFound)
00307         return CPNotFound;
00308 
00309     rangeIndex = CEIL(rangeIndex);
00310 
00311     if (rangeIndex >= _ranges.length)
00312         return CPNotFound;
00313 
00314     var range = _ranges[rangeIndex];
00315 
00316     // Check if it's actually in this range.
00317     if (CPLocationInRange(anIndex, range))
00318         return anIndex;
00319 
00320     // If not, it must be the first element of this range.
00321     return range.location;
00322 }
00323 
00328 - (CPInteger)indexLessThanIndex:(CPInteger)anIndex
00329 {
00330     // The first possible index that would satisfy this requirement.
00331     --anIndex;
00332 
00333     // Attempt to find it or something smaller.
00334     var rangeIndex = assumedPositionOfIndex(_ranges, anIndex);
00335 
00336     // Nothing at all found?
00337     if (rangeIndex === CPNotFound)
00338         return CPNotFound;
00339 
00340     rangeIndex = FLOOR(rangeIndex);
00341 
00342     if (rangeIndex < 0)
00343         return CPNotFound;
00344 
00345     var range = _ranges[rangeIndex];
00346 
00347     // Check if it's actually in this range.
00348     if (CPLocationInRange(anIndex, range))
00349         return anIndex;
00350 
00351     // If not, it must be the first element of this range.
00352     return _CPMaxRange(range) - 1;
00353 }
00354 
00359 - (CPInteger)indexGreaterThanOrEqualToIndex:(CPInteger)anIndex
00360 {
00361     return [self indexGreaterThanIndex:anIndex - 1];
00362 }
00363 
00368 - (CPInteger)indexLessThanOrEqualToIndex:(CPInteger)anIndex
00369 {
00370     return [self indexLessThanIndex:anIndex + 1];
00371 }
00372 
00382 - (CPInteger)getIndexes:(CPArray)anArray maxCount:(CPInteger)aMaxCount inIndexRange:(CPRange)aRange
00383 {
00384     if (!_count || aMaxCount === 0 || aRange && !aRange.length)
00385     {
00386         if (aRange)
00387             aRange.length = 0;
00388 
00389         return 0;
00390     }
00391 
00392     var total = 0;
00393 
00394     if (aRange)
00395     {
00396         var firstIndex = aRange.location,
00397             lastIndex = _CPMaxRange(aRange) - 1,
00398             rangeIndex = CEIL(assumedPositionOfIndex(_ranges, firstIndex)),
00399             lastRangeIndex = FLOOR(assumedPositionOfIndex(_ranges, lastIndex));
00400     }
00401     else
00402     {
00403         var firstIndex = [self firstIndex],
00404             lastIndex = [self lastIndex],
00405             rangeIndex = 0,
00406             lastRangeIndex = _ranges.length - 1;
00407     }
00408 
00409     while (rangeIndex <= lastRangeIndex)
00410     {
00411         var range = _ranges[rangeIndex],
00412             index = MAX(firstIndex, range.location),
00413             maxRange = MIN(lastIndex + 1, _CPMaxRange(range));
00414 
00415         for (; index < maxRange; ++index)
00416         {
00417             anArray[total++] = index;
00418 
00419             if (total === aMaxCount)
00420             {
00421                 // Update aRange if it exists...
00422                 if (aRange)
00423                 {
00424                     aRange.location = index + 1;
00425                     aRange.length = lastIndex + 1 - index - 1;
00426                 }
00427 
00428                 return aMaxCount;
00429             }
00430         }
00431 
00432         ++rangeIndex;
00433     }
00434 
00435     // Update aRange if it exists...
00436     if (aRange)
00437     {
00438         aRange.location = CPNotFound;
00439         aRange.length = 0;
00440     }
00441 
00442     return total;
00443 }
00444 
00445 - (CPString)description
00446 {
00447     var description = [super description];
00448 
00449     if (_count)
00450     {
00451         var index = 0,
00452             count = _ranges.length;
00453 
00454         description += "[number of indexes: " + _count + " (in " + count;
00455 
00456         if (count === 1)
00457             description += " range), indexes: (";
00458         else
00459             description += " ranges), indexes: (";
00460 
00461         for (; index < count; ++index)
00462         {
00463             var range = _ranges[index];
00464 
00465             description += range.location;
00466 
00467             if (range.length > 1)
00468                 description += "-" + (CPMaxRange(range) - 1);
00469 
00470             if (index + 1 < count)
00471                 description += " ";
00472         }
00473 
00474         description += ")]";
00475     }
00476 
00477     else
00478         description += "(no indexes)";
00479 
00480     return description;
00481 }
00482 
00483 @end
00484 
00485 @implementation CPIndexSet(CPMutableIndexSet)
00486 
00487 // Adding indexes.
00492 - (void)addIndex:(CPInteger)anIndex
00493 {
00494     [self addIndexesInRange:_CPMakeRange(anIndex, 1)];
00495 }
00496 
00501 - (void)addIndexes:(CPIndexSet)anIndexSet
00502 {
00503     var otherRanges = anIndexSet._ranges,
00504         otherRangesCount = otherRanges.length;
00505 
00506     // Simply add each range within anIndexSet.
00507     while (otherRangesCount--)
00508         [self addIndexesInRange:otherRanges[otherRangesCount]];
00509 }
00510 
00515 - (void)addIndexesInRange:(CPRange)aRange
00516 {
00517     // If empty range, bail.
00518     if (aRange.length <= 0)
00519         return;
00520 
00521     // If we currently don't have any indexes, this represents our entire set.
00522     if (_count <= 0)
00523     {
00524         _count = aRange.length;
00525         _ranges = [aRange];
00526 
00527         return;
00528     }
00529 
00530     var rangeCount = _ranges.length,
00531         lhsRangeIndex = assumedPositionOfIndex(_ranges, aRange.location - 1),
00532         lhsRangeIndexCEIL = CEIL(lhsRangeIndex);
00533 
00534     if (lhsRangeIndexCEIL === lhsRangeIndex && lhsRangeIndexCEIL < rangeCount)
00535         aRange = CPUnionRange(aRange, _ranges[lhsRangeIndexCEIL]);
00536 
00537     var rhsRangeIndex = assumedPositionOfIndex(_ranges, CPMaxRange(aRange)),
00538         rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex);
00539 
00540     if (rhsRangeIndexFLOOR === rhsRangeIndex && rhsRangeIndexFLOOR >= 0)
00541         aRange = CPUnionRange(aRange, _ranges[rhsRangeIndexFLOOR]);
00542 
00543     var removalCount = rhsRangeIndexFLOOR - lhsRangeIndexCEIL + 1;
00544 
00545     if (removalCount === _ranges.length)
00546     {
00547         _ranges = [aRange];
00548         _count = aRange.length;
00549     }
00550 
00551     else if (removalCount === 1)
00552     {
00553         if (lhsRangeIndexCEIL < _ranges.length)
00554             _count -= _ranges[lhsRangeIndexCEIL].length;
00555 
00556         _count += aRange.length;
00557         _ranges[lhsRangeIndexCEIL] = aRange;
00558     }
00559 
00560     else
00561     {
00562         if (removalCount > 0)
00563         {
00564             var removal = lhsRangeIndexCEIL,
00565                 lastRemoval = lhsRangeIndexCEIL + removalCount - 1;
00566 
00567             for (; removal <= lastRemoval; ++removal)
00568                 _count -= _ranges[removal].length;
00569 
00570             [_ranges removeObjectsInRange:_CPMakeRange(lhsRangeIndexCEIL, removalCount)];
00571         }
00572 
00573         [_ranges insertObject:aRange atIndex:lhsRangeIndexCEIL];
00574 
00575         _count += aRange.length;
00576     }
00577 }
00578 
00579 // Removing Indexes
00584 - (void)removeIndex:(CPInteger)anIndex
00585 {
00586     [self removeIndexesInRange:_CPMakeRange(anIndex, 1)];
00587 }
00588 
00594 - (void)removeIndexes:(CPIndexSet)anIndexSet
00595 {
00596     var otherRanges = anIndexSet._ranges,
00597         otherRangesCount = otherRanges.length;
00598 
00599     // Simply remove each index from anIndexSet
00600     while (otherRangesCount--)
00601         [self removeIndexesInRange:otherRanges[otherRangesCount]];
00602 }
00603 
00607 - (void)removeAllIndexes
00608 {
00609     _ranges = [];
00610     _count = 0;
00611 }
00612 
00618 - (void)removeIndexesInRange:(CPRange)aRange
00619 {
00620     // If empty range, bail.
00621     if (aRange.length <= 0)
00622         return;
00623 
00624     // If we currently don't have any indexes, there's nothing to remove.
00625     if (_count <= 0)
00626         return;
00627 
00628     var rangeCount = _ranges.length,
00629         lhsRangeIndex = assumedPositionOfIndex(_ranges, aRange.location),
00630         lhsRangeIndexCEIL = CEIL(lhsRangeIndex);
00631 
00632     // Do we fall on an actual existing range?
00633     if (lhsRangeIndex === lhsRangeIndexCEIL && lhsRangeIndexCEIL < rangeCount)
00634     {
00635         var existingRange = _ranges[lhsRangeIndexCEIL];
00636 
00637         // If these ranges don't start in the same place, we have to cull it.
00638         if (aRange.location !== existingRange.location)
00639         {
00640             var maxRange = CPMaxRange(aRange),
00641                 existingMaxRange = CPMaxRange(existingRange);
00642 
00643             existingRange.length = aRange.location - existingRange.location;
00644 
00645             // If this range is internal to the existing range, we have a unique splitting case.
00646             if (maxRange < existingMaxRange)
00647             {
00648                 _count -= aRange.length;
00649                 [_ranges insertObject:_CPMakeRange(maxRange, existingMaxRange - maxRange) atIndex:lhsRangeIndexCEIL + 1];
00650 
00651                 return;
00652             }
00653             else
00654             {
00655                 _count -= existingMaxRange - aRange.location;
00656                 lhsRangeIndexCEIL += 1;
00657             }
00658         }
00659     }
00660 
00661     var rhsRangeIndex = assumedPositionOfIndex(_ranges, CPMaxRange(aRange) - 1),
00662         rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex);
00663 
00664     if (rhsRangeIndex === rhsRangeIndexFLOOR && rhsRangeIndexFLOOR >= 0)
00665     {
00666         var maxRange = CPMaxRange(aRange),
00667             existingRange = _ranges[rhsRangeIndexFLOOR],
00668             existingMaxRange = CPMaxRange(existingRange);
00669 
00670         if (maxRange !== existingMaxRange)
00671         {
00672             _count -= maxRange - existingRange.location;
00673             rhsRangeIndexFLOOR -= 1; // This is accounted for, and thus as if we got the previous spot.
00674 
00675             existingRange.location = maxRange;
00676             existingRange.length = existingMaxRange - maxRange;
00677         }
00678     }
00679 
00680     var removalCount = rhsRangeIndexFLOOR - lhsRangeIndexCEIL + 1;
00681 
00682     if (removalCount > 0)
00683     {
00684         var removal = lhsRangeIndexCEIL,
00685             lastRemoval = lhsRangeIndexCEIL + removalCount - 1;
00686 
00687         for (; removal <= lastRemoval; ++removal)
00688             _count -= _ranges[removal].length;
00689 
00690         [_ranges removeObjectsInRange:_CPMakeRange(lhsRangeIndexCEIL, removalCount)];
00691     }
00692 }
00693 
00694 // Shifting Index Groups
00701 - (void)shiftIndexesStartingAtIndex:(CPInteger)anIndex by:(int)aDelta
00702 {
00703     if (!_count || aDelta == 0)
00704        return;
00705 
00706     // Later indexes have a higher probability of being shifted
00707     // than lower ones, so start at the end and work backwards.
00708     var i = _ranges.length - 1,
00709         shifted = CPMakeRange(CPNotFound, 0);
00710 
00711     for (; i >= 0; --i)
00712     {
00713         var range = _ranges[i],
00714             maximum = CPMaxRange(range);
00715 
00716         if (anIndex >= maximum)
00717             break;
00718 
00719         // If our index is within our range, but not the first index,
00720         // then this range will be split.
00721         if (anIndex > range.location)
00722         {
00723             // Split the range into shift and unshifted.
00724             shifted = CPMakeRange(anIndex + aDelta, maximum - anIndex);
00725             range.length = anIndex - range.location;
00726 
00727             // If our delta is positive, then we can simply add the range
00728             // to the array.
00729             if (aDelta > 0)
00730                 [_ranges insertObject:shifted atIndex:i + 1];
00731             // If it's negative, it needs to be added properly later.
00732             else if (shifted.location < 0)
00733             {
00734                 shifted.length = CPMaxRange(shifted);
00735                 shifted.location = 0;
00736             }
00737 
00738             // We don't need to continue.
00739             break;
00740         }
00741 
00742         // Shift the range, and normalize it if the result is negative.
00743         if ((range.location += aDelta) < 0)
00744         {
00745             _count -= range.length - CPMaxRange(range);
00746             range.length = CPMaxRange(range);
00747             range.location = 0;
00748         }
00749     }
00750 
00751     // We need to add the shifted ranges if the delta is negative.
00752     if (aDelta < 0)
00753     {
00754         var j = i + 1,
00755             count = _ranges.length,
00756             shifts = [];
00757 
00758         for (; j < count; ++j)
00759         {
00760             [shifts addObject:_ranges[j]];
00761             _count -= _ranges[j].length;
00762         }
00763 
00764         if ((j = i + 1) < count)
00765         {
00766             [_ranges removeObjectsInRange:CPMakeRange(j, count - j)];
00767 
00768             for (j = 0, count = shifts.length; j < count; ++j)
00769                 [self addIndexesInRange:shifts[j]];
00770         }
00771 
00772         if (shifted.location != CPNotFound)
00773             [self addIndexesInRange:shifted];
00774     }
00775 }
00776 
00777 @end
00778 
00779 var CPIndexSetCountKey              = @"CPIndexSetCountKey",
00780     CPIndexSetRangeStringsKey       = @"CPIndexSetRangeStringsKey";
00781 
00782 @implementation CPIndexSet (CPCoding)
00783 
00790 - (id)initWithCoder:(CPCoder)aCoder
00791 {
00792     self = [super init];
00793 
00794     if (self)
00795     {
00796         _count = [aCoder decodeIntForKey:CPIndexSetCountKey];
00797         _ranges = [];
00798 
00799         var rangeStrings = [aCoder decodeObjectForKey:CPIndexSetRangeStringsKey],
00800             index = 0,
00801             count = rangeStrings.length;
00802 
00803         for (; index < count; ++index)
00804             _ranges.push(CPRangeFromString(rangeStrings[index]));
00805     }
00806 
00807     return self;
00808 }
00809 
00815 - (void)encodeWithCoder:(CPCoder)aCoder
00816 {
00817     [aCoder encodeInt:_count forKey:CPIndexSetCountKey];
00818 
00819     var index = 0,
00820         count = _ranges.length,
00821         rangeStrings = [];
00822 
00823     for (; index < count; ++index)
00824         rangeStrings[index] = CPStringFromRange(_ranges[index]);
00825 
00826     [aCoder encodeObject:rangeStrings forKey:CPIndexSetRangeStringsKey];
00827 }
00828 
00829 @end
00830 
00831 @implementation CPIndexSet (CPCopying)
00832 
00839 - (id)copy
00840 {
00841     return [[[self class] alloc] initWithIndexSet:self];
00842 }
00843 
00850 - (id)mutableCopy
00851 {
00852     return [[[self class] alloc] initWithIndexSet:self];
00853 }
00854 
00855 @end
00856 
00865 @implementation CPMutableIndexSet : CPIndexSet
00866 {
00867     id __doxygen__;
00868 }
00869 
00870 @end
00871 
00872 var positionOfIndex = function(ranges, anIndex)
00873 {
00874     var low = 0,
00875         high = ranges.length - 1;
00876 
00877     while (low <= high)
00878     {
00879         var middle = FLOOR(low + (high - low) / 2),
00880             range = ranges[middle];
00881 
00882         if (anIndex < range.location)
00883             high = middle - 1;
00884 
00885         else if (anIndex >= CPMaxRange(range))
00886             low = middle + 1;
00887 
00888         else
00889             return middle;
00890    }
00891 
00892    return CPNotFound;
00893 }
00894 
00895 var assumedPositionOfIndex = function(ranges, anIndex)
00896 {
00897     var count = ranges.length;
00898 
00899     if (count <= 0)
00900         return CPNotFound;
00901 
00902     var low = 0,
00903         high = count * 2;
00904 
00905     while (low <= high)
00906     {
00907         var middle = FLOOR(low + (high - low) / 2),
00908             position = middle / 2,
00909             positionFLOOR = FLOOR(position);
00910 
00911         if (position === positionFLOOR)
00912         {
00913             if (positionFLOOR - 1 >= 0 && anIndex < CPMaxRange(ranges[positionFLOOR - 1]))
00914                 high = middle - 1;
00915 
00916             else if (positionFLOOR < count && anIndex >= ranges[positionFLOOR].location)
00917                 low = middle + 1;
00918 
00919             else
00920                 return positionFLOOR - 0.5;
00921         }
00922         else
00923         {
00924             var range = ranges[positionFLOOR];
00925 
00926             if (anIndex < range.location)
00927                 high = middle - 1;
00928 
00929             else if (anIndex >= CPMaxRange(range))
00930                 low = middle + 1;
00931 
00932             else
00933                 return positionFLOOR;
00934         }
00935     }
00936 
00937    return CPNotFound;
00938 }
00939 
00940 /*
00941 new old method
00942 X       + (id)indexSet;
00943 X       + (id)indexSetWithIndex:(unsigned int)value;
00944 X       + (id)indexSetWithIndexesInRange:(NSRange)range;
00945 X   X   - (id)init;
00946 X   X   - (id)initWithIndex:(unsigned int)value;
00947 X   X   - (id)initWithIndexesInRange:(NSRange)range;   // designated initializer
00948 X   X   - (id)initWithIndexSet:(NSIndexSet *)indexSet;   // designated initializer
00949 X       - (BOOL)isEqualToIndexSet:(NSIndexSet *)indexSet;
00950 X   X   - (unsigned int)count;
00951 X   X   - (unsigned int)firstIndex;
00952 X   X   - (unsigned int)lastIndex;
00953 X   X   - (unsigned int)indexGreaterThanIndex:(unsigned int)value;
00954 X   X   - (unsigned int)indexLessThanIndex:(unsigned int)value;
00955 X   X   - (unsigned int)indexGreaterThanOrEqualToIndex:(unsigned int)value;
00956 X   X   - (unsigned int)indexLessThanOrEqualToIndex:(unsigned int)value;
00957 X       - (unsigned int)getIndexes:(unsigned int *)indexBuffer maxCount:(unsigned int)bufferSize inIndexRange:(NSRangePointer)range;
00958 X   X   - (BOOL)containsIndex:(unsigned int)value;
00959 X   X   - (BOOL)containsIndexesInRange:(NSRange)range;
00960 X   X   - (BOOL)containsIndexes:(NSIndexSet *)indexSet;
00961 X   X   - (BOOL)intersectsIndexesInRange:(NSRange)range;
00962 X   X   - (void)addIndexes:(NSIndexSet *)indexSet;
00963 X       - (void)removeIndexes:(NSIndexSet *)indexSet;
00964 X   X   - (void)removeAllIndexes;
00965 X       - (void)addIndex:(unsigned int)value;
00966 X       - (void)removeIndex:(unsigned int)value;
00967 X       - (void)addIndexesInRange:(NSRange)range;
00968 X       - (void)removeIndexesInRange:(NSRange)range;
00969         - (void)shiftIndexesStartingAtIndex:(unsigned int)index by:(int)delta;
00970 */
 All Classes Files Functions Variables Defines