23 #include "Foundation.h" 45 return [[
self alloc] init];
51 + (id)indexSetWithIndex:(
int)anIndex
60 + (id)indexSetWithIndexesInRange:(CPRange)aRange
76 - (id)initWithIndex:(CPInteger)anIndex
78 if (!_IS_NUMERIC(anIndex))
90 - (id)initWithIndexesInRange:(CPRange)aRange
92 if (aRange.location < 0)
93 [
CPException raise:CPInvalidArgumentException
reason:"Range " + CPStringFromRange(aRange) + " is out of bounds."];
99 _count = MAX(0, aRange.length);
121 _count = [anIndexSet
count];
124 var otherRanges = anIndexSet._ranges,
125 otherRangesCount = otherRanges.length;
127 while (otherRangesCount--)
128 _ranges[otherRangesCount] =
CPMakeRangeCopy(otherRanges[otherRangesCount]);
136 if (
self === anObject)
139 if (!anObject || ![anObject isKindOfClass:[
CPIndexSet class]])
157 if (
self === anIndexSet)
160 var rangesCount = _ranges.length,
161 otherRanges = anIndexSet._ranges;
165 if (rangesCount !== otherRanges.length || _count !== anIndexSet._count)
168 while (rangesCount--)
169 if (!
CPEqualRanges(_ranges[rangesCount], otherRanges[rangesCount]))
177 return self === anObject ||
178 [anObject isKindOfClass:[
self class]] &&
179 [
self isEqualToIndexSet:anObject];
187 - (BOOL)containsIndex:(CPInteger)anIndex
196 - (BOOL)containsIndexesInRange:(CPRange)aRange
198 if (aRange.length <= 0)
202 if (_count < aRange.length)
212 var range = _ranges[rangeIndex];
224 var otherCount = anIndexSet._count;
230 if (_count < otherCount)
233 var otherRanges = anIndexSet._ranges,
234 otherRangesCount = otherRanges.length;
236 while (otherRangesCount--)
237 if (![
self containsIndexesInRange:otherRanges[otherRangesCount]])
248 - (BOOL)intersectsIndexesInRange:(CPRange)aRange
255 if (FLOOR(lhsRangeIndex) === lhsRangeIndex)
260 if (FLOOR(rhsRangeIndex) === rhsRangeIndex)
263 return lhsRangeIndex !== rhsRangeIndex;
278 - (CPInteger)firstIndex
281 return _ranges[0].location;
289 - (CPInteger)lastIndex
292 return CPMaxRange(_ranges[_ranges.length - 1]) - 1;
301 - (CPInteger)indexGreaterThanIndex:(CPInteger)anIndex
313 rangeIndex = CEIL(rangeIndex);
315 if (rangeIndex >= _ranges.length)
318 var range = _ranges[rangeIndex];
325 return range.location;
332 - (CPInteger)indexLessThanIndex:(CPInteger)anIndex
344 rangeIndex = FLOOR(rangeIndex);
349 var range = _ranges[rangeIndex];
363 - (CPInteger)indexGreaterThanOrEqualToIndex:(CPInteger)anIndex
372 - (CPInteger)indexLessThanOrEqualToIndex:(CPInteger)anIndex
386 - (CPInteger)getIndexes:(CPArray)anArray maxCount:(CPInteger)aMaxCount inIndexRange:(CPRange)aRange
388 if (!_count || aMaxCount === 0 || aRange && !aRange.length)
400 var firstIndex = aRange.location,
410 lastRangeIndex = _ranges.length - 1;
413 while (rangeIndex <= lastRangeIndex)
415 var range = _ranges[rangeIndex],
416 index = MAX(firstIndex, range.location),
417 maxRange = MIN(lastIndex + 1,
CPMaxRange(range));
419 for (; index < maxRange; ++index)
421 anArray[total++] = index;
423 if (total === aMaxCount)
428 aRange.location = index + 1;
429 aRange.length = lastIndex + 1 - index - 1;
456 count = _ranges.length;
458 description +=
"[number of indexes: " + _count +
" (in " + count;
465 for (; index < count; ++index)
467 var range = _ranges[index];
471 if (range.length > 1)
474 if (index + 1 < count)
487 - (void)enumerateIndexesUsingBlock:(Function )aFunction
492 - (void)enumerateIndexesWithOptions:(CPEnumerationOptions)options usingBlock:(Function )aFunction
499 - (void)enumerateIndexesInRange:(CPRange)enumerationRange options:(CPEnumerationOptions)options usingBlock:(Function )aFunction
509 if (options & CPEnumerationReverse)
511 index = _ranges.length - 1;
518 stop = _ranges.length;
524 var range = _ranges[index],
529 if (options & CPEnumerationReverse)
532 rangeStop = range.location - 1;
537 rangeIndex = range.location;
542 for (; rangeIndex !== rangeStop; rangeIndex += rangeIncrement)
546 aFunction(rangeIndex, @ref(shouldStop));
554 - (unsigned)indexPassingTest:(Function )aPredicate
564 - (unsigned)indexWithOptions:(CPEnumerationOptions)anOptions passingTest:(Function )aPredicate
572 - (
CPIndexSet)indexesWithOptions:(CPEnumerationOptions)anOptions passingTest:(Function )aPredicate
580 - (unsigned)indexInRange:(CPRange)aRange options:(CPEnumerationOptions)anOptions passingTest:(Function )aPredicate
590 if (anOptions & CPEnumerationReverse)
592 index = _ranges.length - 1;
599 stop = _ranges.length;
605 var range = _ranges[index],
610 if (anOptions & CPEnumerationReverse)
613 rangeStop = range.location - 1;
618 rangeIndex = range.location;
623 for (; rangeIndex !== rangeStop; rangeIndex += rangeIncrement)
627 if (aPredicate(rangeIndex, @ref(shouldStop)))
639 - (
CPIndexSet)indexesInRange:(CPRange)aRange options:(CPEnumerationOptions)anOptions passingTest:(Function )aPredicate
649 if (anOptions & CPEnumerationReverse)
651 index = _ranges.length - 1;
658 stop = _ranges.length;
666 var range = _ranges[index],
671 if (anOptions & CPEnumerationReverse)
674 rangeStop = range.location - 1;
679 rangeIndex = range.location;
684 for (; rangeIndex !== rangeStop; rangeIndex += rangeIncrement)
688 if (aPredicate(rangeIndex, @ref(shouldStop)))
689 [indexesPassingTest addIndex:rangeIndex];
692 return indexesPassingTest;
697 return indexesPassingTest;
709 - (void)addIndex:(CPInteger)anIndex
720 var otherRanges = anIndexSet._ranges,
721 otherRangesCount = otherRanges.length;
724 while (otherRangesCount--)
732 - (void)addIndexesInRange:(CPRange)aRange
734 if (aRange.location < 0)
735 [
CPException raise:CPInvalidArgumentException
reason:"Range " + CPStringFromRange(aRange) + " is out of bounds."];
738 if (aRange.length <= 0)
744 _count = aRange.length;
750 var rangeCount = _ranges.length,
752 lhsRangeIndexCEIL = CEIL(lhsRangeIndex);
754 if (lhsRangeIndexCEIL === lhsRangeIndex && lhsRangeIndexCEIL < rangeCount)
755 aRange =
CPUnionRange(aRange, _ranges[lhsRangeIndexCEIL]);
758 rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex);
760 if (rhsRangeIndexFLOOR === rhsRangeIndex && rhsRangeIndexFLOOR >= 0)
761 aRange =
CPUnionRange(aRange, _ranges[rhsRangeIndexFLOOR]);
763 var removalCount = rhsRangeIndexFLOOR - lhsRangeIndexCEIL + 1;
765 if (removalCount === _ranges.length)
768 _count = aRange.length;
771 else if (removalCount === 1)
773 if (lhsRangeIndexCEIL < _ranges.length)
774 _count -= _ranges[lhsRangeIndexCEIL].length;
776 _count += aRange.length;
777 _ranges[lhsRangeIndexCEIL] = aRange;
782 if (removalCount > 0)
784 var removal = lhsRangeIndexCEIL,
785 lastRemoval = lhsRangeIndexCEIL + removalCount - 1;
787 for (; removal <= lastRemoval; ++removal)
788 _count -= _ranges[removal].length;
790 [_ranges removeObjectsInRange:CPMakeRange(lhsRangeIndexCEIL, removalCount)];
793 [_ranges insertObject:aRange atIndex:lhsRangeIndexCEIL];
795 _count += aRange.length;
804 - (void)removeIndex:(CPInteger)anIndex
816 var otherRanges = anIndexSet._ranges,
817 otherRangesCount = otherRanges.length;
820 while (otherRangesCount--)
827 - (void)removeAllIndexes
838 - (void)removeIndexesInRange:(CPRange)aRange
841 if (aRange.length <= 0)
848 var rangeCount = _ranges.length,
850 lhsRangeIndexCEIL = CEIL(lhsRangeIndex);
853 if (lhsRangeIndex === lhsRangeIndexCEIL && lhsRangeIndexCEIL < rangeCount)
855 var existingRange = _ranges[lhsRangeIndexCEIL];
858 if (aRange.location !== existingRange.location)
863 existingRange.length = aRange.location - existingRange.location;
866 if (maxRange < existingMaxRange)
868 _count -= aRange.length;
869 [_ranges insertObject:CPMakeRange(maxRange, existingMaxRange - maxRange) atIndex:lhsRangeIndexCEIL + 1];
875 _count -= existingMaxRange - aRange.location;
876 lhsRangeIndexCEIL += 1;
882 rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex);
884 if (rhsRangeIndex === rhsRangeIndexFLOOR && rhsRangeIndexFLOOR >= 0)
887 existingRange = _ranges[rhsRangeIndexFLOOR],
890 if (maxRange !== existingMaxRange)
892 _count -= maxRange - existingRange.location;
893 rhsRangeIndexFLOOR -= 1;
895 existingRange.location = maxRange;
896 existingRange.length = existingMaxRange - maxRange;
900 var removalCount = rhsRangeIndexFLOOR - lhsRangeIndexCEIL + 1;
902 if (removalCount > 0)
904 var removal = lhsRangeIndexCEIL,
905 lastRemoval = lhsRangeIndexCEIL + removalCount - 1;
907 for (; removal <= lastRemoval; ++removal)
908 _count -= _ranges[removal].length;
910 [_ranges removeObjectsInRange:CPMakeRange(lhsRangeIndexCEIL, removalCount)];
921 - (void)shiftIndexesStartingAtIndex:(CPInteger)anIndex by:(
int)aDelta
923 if (!_count || aDelta == 0)
928 var i = _ranges.length - 1,
933 var range = _ranges[i],
936 if (anIndex >= maximum)
941 if (anIndex > range.location)
944 shifted =
CPMakeRange(anIndex + aDelta, maximum - anIndex);
945 range.length = anIndex - range.location;
950 [_ranges insertObject:shifted atIndex:i + 1];
952 else if (shifted.location < 0)
955 shifted.location = 0;
963 if ((range.location += aDelta) < 0)
975 count = _ranges.length,
978 for (; j < count; ++j)
980 [shifts addObject:_ranges[j]];
981 _count -= _ranges[j].length;
984 if ((j = i + 1) < count)
986 [_ranges removeObjectsInRange:CPMakeRange(j, count - j)];
988 for (j = 0, count = shifts.length; j < count; ++j)
1012 self = [
super init];
1016 _count = [aCoder decodeIntForKey:CPIndexSetCountKey];
1018 var rangeStrings = [aCoder decodeObjectForKey:CPIndexSetRangeStringsKey];
1020 _ranges = [rangeStrings arrayByApplyingBlock:function(range)
1022 return CPRangeFromString(range);
1036 [aCoder encodeInt:_count forKey:CPIndexSetCountKey];
1039 count = _ranges.length,
1042 for (; index < count; ++index)
1045 [aCoder encodeObject:rangeStrings forKey:CPIndexSetRangeStringsKey];
1060 return [[[
self class] alloc] initWithIndexSet:self];
1071 return [[[
self class] alloc] initWithIndexSet:self];
1093 high = ranges.length - 1;
1097 var middle = FLOOR(low + (high - low) / 2),
1098 range = ranges[middle];
1100 if (anIndex < range.location)
1115 var count = ranges.length;
1125 var middle = FLOOR(low + (high - low) / 2),
1131 if (positionFLOOR - 1 >= 0 && anIndex <
CPMaxRange(ranges[positionFLOOR - 1]))
1134 else if (positionFLOOR < count && anIndex >= ranges[positionFLOOR].location)
1138 return positionFLOOR - 0.5;
1142 var range = ranges[positionFLOOR];
1144 if (anIndex < range.location)
1151 return positionFLOOR;
unsigned indexInRange:options:passingTest:(CPRange aRange, [options] CPEnumerationOptions anOptions, [passingTest] Function/*(int anIndex) */aPredicate)
Used to implement exception handling (creating & raising).
function CPUnionRange(lhsRange, rhsRange)
void removeIndexesInRange:(CPRange aRange)
unsigned indexWithOptions:passingTest:(CPEnumerationOptions anOptions, [passingTest] Function/*(int anIndex) */aPredicate)
void raise:reason:(CPString aName, [reason] CPString aReason)
A collection of unique integers.
var CPIndexSetRangeStringsKey
function CPStringFromRange(aRange)
function CPEqualRanges(lhsRange, rhsRange)
FrameUpdater prototype stop
function CPEmptyRange(aRange)
function CPMaxRange(aRange)
An immutable string (collection of characters).
CPInteger indexGreaterThanIndex:(CPInteger anIndex)
id initWithIndexesInRange:(CPRange aRange)
var assumedPositionOfIndex
function CPIntersectionRange(lhsRange, rhsRange)
CPIndexSet indexesWithOptions:passingTest:(CPEnumerationOptions anOptions, [passingTest] Function/*(int anIndex) */aPredicate)
id initWithIndex:(CPInteger anIndex)
function CPMakeRangeCopy(aRange)
Defines methods for use when archiving & restoring (enc/decoding).
CPInteger indexLessThanIndex:(CPInteger anIndex)
function CPLocationInRange(aLocation, aRange)
CPIndexSet indexesInRange:options:passingTest:(CPRange aRange, [options] CPEnumerationOptions anOptions, [passingTest] Function/*(int anIndex) */aPredicate)
void addIndexesInRange:(CPRange aRange)
BOOL isEqualToIndexSet:(CPIndexSet anIndexSet)
void enumerateIndexesWithOptions:usingBlock:(CPEnumerationOptions options, [usingBlock] Function/*(int idx, @ref BOOL stop) */aFunction)
void enumerateIndexesInRange:options:usingBlock:(CPRange enumerationRange, [options] CPEnumerationOptions options, [usingBlock] Function/*(int idx, @ref BOOL stop) */aFunction)
CompletionHandlerAgent prototype increment
CPRange function CPMakeRange(location, length)
FrameUpdater prototype description