NSIndexSet updates finally comitted

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18853 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2004-03-18 06:56:12 +00:00
parent 066a631d64
commit 3c513f8a67
6 changed files with 524 additions and 14 deletions

View file

@ -2,7 +2,8 @@
* Source/NSDictionary.m: Don't use stack as temporary storage for
large numbers of objects ... reduce chances of stack overflow.
* Source/NSIndexSet.m: Added a few range checks.
* Source/NSIndexSet.m: Added a few range checks, implemented many
methods of mutable class.
2004-03-16 Willem Rein Oudshoorn <Wim.Oudshoorn@agilisys.com>

View file

@ -58,6 +58,7 @@
#include <Foundation/NSHashTable.h>
#include <Foundation/NSGeometry.h>
#include <Foundation/NSHost.h>
#include <Foundation/NSIndexSet.h>
#include <Foundation/NSInvocation.h>
#include <Foundation/NSKeyValueCoding.h>
#include <Foundation/NSLock.h>

View file

@ -33,7 +33,7 @@
#include <Foundation/NSRange.h>
/**
* <strong> NOT YET IMPLEMENTED/TESTED </strong>
* <strong> NOT YET FULLY IMPLEMENTED/TESTED </strong>
* Instances of this class are collections of unsigned integers in the
* range 0 to NSNotFound-1.<br />
* Each integer can appear in a collection only once.
@ -161,13 +161,51 @@
@interface NSMutableIndexSet : NSIndexSet
/**
* Adds anIndex to the set of indexes stored in the receiver.
*/
- (void) addIndex: (unsigned int)anIndex;
/**
* Adds all the indexes from aSet to the set of indexes stored in the receiver.
*/
- (void) addIndexes: (NSIndexSet*)aSet;
/**
* Adds all the indexes in aRange to the set of indexes stored in the receiver.
*/
- (void) addIndexesInRange: (NSRange)aRange;
/**
* Removes all indexes stored in the receiver.
*/
- (void) removeAllIndexes;
/**
* Removes anIndex from the set of indexes stored in the receiver.
*/
- (void) removeIndex: (unsigned int)anIndex;
/**
* Removes all the indexes in aSet from the set of indexes
* stored in the receiver.
*/
- (void) removeIndexes: (NSIndexSet*)aSet;
/**
* Removes all the indexes in aRange from the set of indexes
* stored in the receiver.
*/
- (void) removeIndexesInRange: (NSRange)aRange;
/**
* Not implemented.<br />
* Moves all the indexes from anIndex upwards by the amount specified.<br />
* If amount is negative, index values below anIndex will be overwritten
* by the shifted values.<br />
* If amount is positive, a 'hole' will be left in the index range after
* anIndex.
*/
- (void) shiftIndexesStartingAtIndex: (unsigned int)anIndex by: (int)amount;
@end

View file

@ -189,6 +189,7 @@ static unsigned posForIndex(GSIArray array, unsigned index)
while (i < count)
{
total += GSIArrayItemAtIndex(_array, i).ext.length;
i++;
}
return total;
}
@ -205,6 +206,25 @@ static unsigned posForIndex(GSIArray array, unsigned index)
[super dealloc];
}
- (NSString*) description
{
NSMutableString *m;
unsigned c = GSIArrayCount(_array);
unsigned i;
m = [NSMutableString stringWithFormat:
@"%@[number of indexes: %u (in %u ranges), indexes: ",
[super description], [self count], c];
for (i = 0; i < c; i++)
{
NSRange r = GSIArrayItemAtIndex(_array, i).ext;
[m appendFormat: @"(%u-%u) ", r.location, NSMaxRange(r) - 1];
}
[m appendString: @"]"];
return m;
}
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[self notImplemented:_cmd];
@ -260,7 +280,7 @@ static unsigned posForIndex(GSIArray array, unsigned index)
aRange->location += skip;
aRange->length -= skip;
}
else if (NSLocationInRange(aRange->location, r))
if (NSLocationInRange(aRange->location, r))
{
while (aRange->length > 0 && i < aCount
&& aRange->location < NSMaxRange(r))
@ -328,6 +348,10 @@ static unsigned posForIndex(GSIArray array, unsigned index)
{
return anIndex;
}
if (r.location > anIndex)
{
return r.location;
}
if (++pos >= GSIArrayCount(_array))
{
return NSNotFound;
@ -501,9 +525,9 @@ static unsigned posForIndex(GSIArray array, unsigned index)
- (BOOL) isEqualToIndexSet: (NSIndexSet*)aSet
{
unsigned count = GSIArrayCount(_other);
unsigned count = _other ? GSIArrayCount(_other) : 0;
if (count != GSIArrayCount(_array))
if (count != (_array ? GSIArrayCount(_array) : 0))
{
return NO;
}
@ -531,7 +555,7 @@ static unsigned posForIndex(GSIArray array, unsigned index)
{
return NSNotFound;
}
return GSIArrayItemAtIndex(_array, GSIArrayCount(_array)-1).ext.location;
return NSMaxRange(GSIArrayItemAtIndex(_array, GSIArrayCount(_array)-1).ext)-1;
}
- (id) mutableCopyWithZone: (NSZone*)aZone
@ -594,10 +618,64 @@ static unsigned posForIndex(GSIArray array, unsigned index)
}
else
{
unsigned p1 = posForIndex(_array, aRange.location);
unsigned p2 = posForIndex(_array, NSMaxRange(aRange)-1);
unsigned pos = posForIndex(_array, aRange.location);
[self notImplemented:_cmd];
if (pos >= GSIArrayCount(_array))
{
/*
* The start of the range to add lies beyond the existing
* ranges, so we can simply append it.
*/
GSIArrayAddItem(_array, (GSIArrayItem)aRange);
}
else
{
NSRange r = GSIArrayItemAtIndex(_array, pos-1).ext;
if (NSLocationInRange(aRange.location, r))
{
pos++;
}
GSIArrayInsertItem(_array, (GSIArrayItem)aRange, pos);
}
/*
* Combine with the preceding ranges if possible.
*/
while (pos > 0)
{
NSRange r = GSIArrayItemAtIndex(_array, pos-1).ext;
if (NSMaxRange(r) < aRange.location)
{
break;
}
r.length += (NSMaxRange(aRange) - NSMaxRange(r));
GSIArrayRemoveItemAtIndex(_array, pos--);
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
}
/*
* Combine with any following ranges where possible.
*/
while (pos + 1 < GSIArrayCount(_array))
{
NSRange r = GSIArrayItemAtIndex(_array, pos+1).ext;
if (NSMaxRange(aRange) < r.location)
{
break;
}
GSIArrayRemoveItemAtIndex(_array, pos + 1);
if (NSMaxRange(r) > NSMaxRange(aRange))
{
int offset = NSMaxRange(r) - NSMaxRange(aRange);
r = GSIArrayItemAtIndex(_array, pos).ext;
r.length += offset;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
}
}
}
}
@ -618,28 +696,233 @@ static unsigned posForIndex(GSIArray array, unsigned index)
- (void) removeIndex: (unsigned int)anIndex
{
[self notImplemented:_cmd];
[self removeIndexesInRange: NSMakeRange(anIndex, 1)];
}
- (void) removeIndexes: (NSIndexSet*)aSet
{
[self notImplemented:_cmd];
unsigned count = GSIArrayCount(_other);
if (count > 0)
{
unsigned i;
for (i = 0; i < count; i++)
{
NSRange r = GSIArrayItemAtIndex(_other, i).ext;
[self removeIndexesInRange: r];
}
}
}
- (void) removeIndexesInRange: (NSRange)aRange
{
unsigned pos;
if (NSNotFound - aRange.length < aRange.location)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@]: Bad range",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
[self notImplemented:_cmd];
if (aRange.length == 0 || _array == 0 || GSIArrayCount(_array) == 0)
{
return; // Already empty
}
pos = posForIndex(_array, aRange.location);
/*
* Remove any ranges contained entirely in the one to be removed.
*/
while (pos < GSIArrayCount(_array))
{
NSRange r = GSIArrayItemAtIndex(_array, pos).ext;
if (r.location < aRange.location || NSMaxRange(r) > NSMaxRange(aRange))
{
break;
}
GSIArrayRemoveItemAtIndex(_array, pos);
}
if (pos < GSIArrayCount(_array))
{
NSRange r = GSIArrayItemAtIndex(_array, pos).ext;
if (r.location <= aRange.location)
{
/*
* The existing range might overlap or mcontain the range to remove.
*/
if (NSMaxRange(r) >= NSMaxRange(aRange))
{
/*
* Range to remove is contained in the range we found ...
*/
if (r.location == aRange.location)
{
/*
* Remove from start of range.
*/
r.length -= aRange.length;
r.location += aRange.length;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
}
else if (NSMaxRange(r) == NSMaxRange(aRange))
{
/*
* Remove from end of range.
*/
r.length -= aRange.length;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
}
else
{
NSRange t;
unsigned p;
/*
* Split the range.
*/
p = NSMaxRange(aRange);
t = NSMakeRange(p, NSMaxRange(r) - p);
GSIArrayInsertItem(_array, (GSIArrayItem)t, pos+1);
r.length = aRange.location - r.location;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
}
}
else if (NSMaxRange(r) >= aRange.location)
{
/*
* The range to remove overlaps the one we found.
*/
r.length = aRange.location - r.location;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
if (++pos < GSIArrayCount(_array))
{
NSRange r = GSIArrayItemAtIndex(_array, pos).ext;
if (r.location < NSMaxRange(aRange))
{
/*
* and also overlaps the following range.
*/
r.length -= NSMaxRange(aRange) - r.location;
r.location = NSMaxRange(aRange);
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
}
}
}
}
}
}
- (void) shiftIndexesStartingAtIndex: (unsigned int)anIndex by: (int)amount
{
[self notImplemented:_cmd];
if (amount != 0 && _array != 0 && GSIArrayCount(_array) > 0)
{
unsigned c;
unsigned pos;
if (amount > 0)
{
c = GSIArrayCount(_array);
pos = posForIndex(_array, anIndex);
if (pos < c)
{
NSRange r = GSIArrayItemAtIndex(_array, pos).ext;
/*
* If anIndex is within an existing range, we split
* that range so we have one starting at anIndex.
*/
if (r.location < anIndex)
{
NSRange t;
/*
* Split the range.
*/
t = NSMakeRange(r.location, anIndex - r.location);
GSIArrayInsertItem(_array, (GSIArrayItem)t, pos);
c++;
r.length = NSMaxRange(r) - anIndex;
r.location = anIndex;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, ++pos);
}
/*
* Shift all higher ranges to the right.
*/
while (c > pos)
{
NSRange r = GSIArrayItemAtIndex(_array, --c).ext;
if (NSNotFound - amount <= r.location)
{
GSIArrayRemoveItemAtIndex(_array, c);
}
else if (NSNotFound - amount < NSMaxRange(r))
{
r.location += amount;
r.length = NSNotFound - r.location;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, c);
}
else
{
r.location += amount;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, c);
}
}
}
}
else
{
amount = -amount;
/*
* Delete range which will be overwritten.
*/
if (amount >= anIndex)
{
[self removeIndexesInRange: NSMakeRange(0, anIndex)];
}
else
{
[self removeIndexesInRange:
NSMakeRange(anIndex - amount, amount)];
}
pos = posForIndex(_array, anIndex);
/*
* Now shift everything left into the hole we made.
*/
c = GSIArrayCount(_array);
while (c > pos)
{
NSRange r = GSIArrayItemAtIndex(_array, --c).ext;
if (NSMaxRange(r) <= amount)
{
GSIArrayRemoveItemAtIndex(_array, c);
}
else if (r.location <= amount)
{
r.length += (r.location - amount);
r.location = 0;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, c);
}
else
{
r.location -= amount;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, c);
}
}
}
}
}
@end

View file

@ -51,7 +51,7 @@ CHECKABLE_TOOLS = \
nsfilemanager \
nshashtable \
nshost \
nsinvocation \
nsindexset \
nsmaptable \
nsnotification \
nsprocessinfo \
@ -104,6 +104,7 @@ nsfilehandle_OBJC_FILES = nsfilehandle.m
nsfilemanager_OBJC_FILES = nsfilemanager.m
nshashtable_OBJC_FILES = nshashtable.m
nshost_OBJC_FILES = nshost.m
nsindexset_OBJC_FILES = nsindexset.m
nsinvocation_OBJC_FILES = nsinvocation.m
nsmaptable_OBJC_FILES = nsmaptable.m
nsnotification_OBJC_FILES = nsnotification.m

186
Testing/nsindexset.m Normal file
View file

@ -0,0 +1,186 @@
#include <Foundation/Foundation.h>
int
main ()
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSIndexSet *s;
NSMutableIndexSet *m;
unsigned int buf[2];
NSRange r;
printf("Can create empty set ...");
s = [NSIndexSet indexSet];
printf(" %s\n", s != nil ? "passed" : "failed");
printf("Empty set count is 0 ...");
printf(" %s\n", [s count] == 0 ? "passed" : "failed");
printf("Empty set does not contain index 0 ...");
printf(" %s\n", [s containsIndex: 0] == NO ? "passed" : "failed");
printf("Empty set does not intersect indexes in range 0->NSNotFound-1 ...");
printf(" %s\n", [s intersectsIndexesInRange: NSMakeRange(0,NSNotFound-1)] == NO ? "passed" : "failed");
printf("Empty set first index is NSNotFound...");
printf(" %s\n", [s firstIndex] == NSNotFound ? "passed" : "failed");
printf("Empty set last index is NSNotFound...");
printf(" %s\n", [s lastIndex] == NSNotFound ? "passed" : "failed");
printf("Empty set index less than 1 is NSNotFound...");
printf(" %s\n", [s indexLessThanIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Empty set index less than or equal to 1 is NSNotFound...");
printf(" %s\n", [s indexLessThanOrEqualToIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Empty set index greater than 1 is NSNotFound...");
printf(" %s\n", [s indexGreaterThanIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Empty set index greater than or equal to 1 is NSNotFound...");
printf(" %s\n", [s indexGreaterThanOrEqualToIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Empty set getIndexes gives 0...");
r = NSMakeRange(0, NSNotFound-1);
printf(" %s\n", [s getIndexes: buf maxCount:3 inIndexRange: &r] == 0 ? "passed" : "failed");
printf("Can create single index set with 2 ...");
s = [NSIndexSet indexSetWithIndex: 2];
printf(" %s\n", s != nil ? "passed" : "failed");
printf("Set count is 1 ...");
printf(" %s\n", [s count] == 1 ? "passed" : "failed");
printf("Set does not contain index 0 ...");
printf(" %s\n", [s containsIndex: 0] == NO ? "passed" : "failed");
printf("Set contains index 2 ...");
printf(" %s\n", [s containsIndex: 2] == YES ? "passed" : "failed");
printf("Set intersects indexes in range 0->NSNotFound-1 ...");
printf(" %s\n", [s intersectsIndexesInRange: NSMakeRange(0,NSNotFound-1)] == YES ? "passed" : "failed");
printf("Set first index is 2...");
printf(" %s\n", [s firstIndex] == 2 ? "passed" : "failed");
printf("Set last index is 2...");
printf(" %s\n", [s lastIndex] == 2 ? "passed" : "failed");
printf("Set index less than 1 is NSNotFound...");
printf(" %s\n", [s indexLessThanIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Set index less than or equal to 1 is NSNotFound...");
printf(" %s\n", [s indexLessThanOrEqualToIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Set index less than 2 is NSNotFound...");
printf(" %s\n", [s indexLessThanIndex: 2] == NSNotFound ? "passed" : "failed");
printf("Set index less than or equal to 2 is 2...");
printf(" %s\n", [s indexLessThanOrEqualToIndex: 2] == 2 ? "passed" : "failed");
printf("Set index greater than 1 is 2...");
printf(" %s\n", [s indexGreaterThanIndex: 1] == 2 ? "passed" : "failed");
printf("Set index greater than or equal to 1 is 2...");
printf(" %s\n", [s indexGreaterThanOrEqualToIndex: 1] == 2 ? "passed" : "failed");
printf("Set index greater than 2 is NSNotFound...");
printf(" %s\n", [s indexGreaterThanIndex: 2] == NSNotFound ? "passed" : "failed");
printf("Set index greater than or equal to 2 is 2...");
printf(" %s\n", [s indexGreaterThanOrEqualToIndex: 2] == 2 ? "passed" : "failed");
printf("Set getIndexes gives 1...");
r = NSMakeRange(0, NSNotFound-1);
printf(" %s\n", [s getIndexes: buf maxCount:3 inIndexRange: &r] == 1 ? "passed" : "failed");
printf("Can create multipe index set with range 2...5 ...");
s = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(2,4)];
printf(" %s\n", s != nil ? "passed" : "failed");
printf("Set count is 4 ...");
printf(" %s\n", [s count] == 4 ? "passed" : "failed");
printf("Set does not contain index 0 ...");
printf(" %s\n", [s containsIndex: 0] == NO ? "passed" : "failed");
printf("Set contains index 2 ...");
printf(" %s\n", [s containsIndex: 2] == YES ? "passed" : "failed");
printf("Set contains index 5 ...");
printf(" %s\n", [s containsIndex: 5] == YES ? "passed" : "failed");
printf("Set intersects indexes in range 0->NSNotFound-1 ...");
printf(" %s\n", [s intersectsIndexesInRange: NSMakeRange(0,NSNotFound-1)] == YES ? "passed" : "failed");
printf("Set first index is 2...");
printf(" %s\n", [s firstIndex] == 2 ? "passed" : "failed");
printf("Set last index is 5...");
printf(" %s\n", [s lastIndex] == 5 ? "passed" : "failed");
printf("Set index less than 1 is NSNotFound...");
printf(" %s\n", [s indexLessThanIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Set index less than or equal to 1 is NSNotFound...");
printf(" %s\n", [s indexLessThanOrEqualToIndex: 1] == NSNotFound ? "passed" : "failed");
printf("Set index less than 2 is NSNotFound...");
printf(" %s\n", [s indexLessThanIndex: 2] == NSNotFound ? "passed" : "failed");
printf("Set index less than or equal to 2 is 2...");
printf(" %s\n", [s indexLessThanOrEqualToIndex: 2] == 2 ? "passed" : "failed");
printf("Set index greater than 1 is 2...");
printf(" %s\n", [s indexGreaterThanIndex: 1] == 2 ? "passed" : "failed");
printf("Set index greater than or equal to 1 is 2...");
printf(" %s\n", [s indexGreaterThanOrEqualToIndex: 1] == 2 ? "passed" : "failed");
printf("Set index greater than 2 is 3...");
printf(" %s\n", [s indexGreaterThanIndex: 2] == 3 ? "passed" : "failed");
printf("Set index greater than or equal to 2 is 2...");
printf(" %s\n", [s indexGreaterThanOrEqualToIndex: 2] == 2 ? "passed" : "failed");
printf("Set getIndexes gives 3...");
r = NSMakeRange(0, NSNotFound-1);
printf(" %s\n", [s getIndexes: buf maxCount:3 inIndexRange: &r] == 3 ? "passed" : "failed");
printf("Set getIndexes gives 1...");
printf(" %s\n", [s getIndexes: buf maxCount:3 inIndexRange: &r] == 1 ? "passed" : "failed");
printf("Set mutableCopy works...");
m = [[s mutableCopy] autorelease];
printf(" %s\n", m != nil ? "passed" : "failed");
printf("Copy equals originals...");
printf(" %s\n", [m isEqual: s] == YES ? "passed" : "failed");
printf("Can add index 10 to mutable set...");
[m addIndex: 10];
printf(" %s\n", [m containsIndex: 10] == YES && [m containsIndex: 9] == NO && [m containsIndex: 11] == NO ? "passed" : "failed");
printf("Can add index 7 to mutable set...");
[m addIndex: 7];
printf(" %s\n", [m containsIndex: 7] == YES && [m containsIndex: 6] == NO && [m containsIndex: 8] == NO ? "passed" : "failed");
printf("Can add index 8 to mutable set...");
[m addIndex: 8];
printf(" %s\n", [m containsIndex: 7] == YES && [m containsIndex: 8] == YES && [m containsIndex: 9] == NO ? "passed" : "failed");
printf("Can add index 9 to mutable set...");
[m addIndex: 9];
printf(" %s\n", [m containsIndex: 8] == YES && [m containsIndex: 9] == YES && [m containsIndex: 10] == YES ? "passed" : "failed");
printf("Can remove index 9 from mutable set...");
[m removeIndex: 9];
printf(" %s\n", [m containsIndex: 8] == YES && [m containsIndex: 9] == NO && [m containsIndex: 10] == YES ? "passed" : "failed");
printf("Can shift right by 5 from 7...");
[m shiftIndexesStartingAtIndex: 7 by: 5];
printf(" %s\n", [m containsIndex: 7] == NO && [m containsIndex: 12] == YES ? "passed" : "failed");
printf("Can shift left by 5 from 12...");
[m shiftIndexesStartingAtIndex: 12 by: -5];
printf(" %s\n", [m containsIndex: 7] == YES && [m containsIndex: 12] == NO ? "passed" : "failed");
printf("Can remove range 5-7 from mutable set...");
[m removeIndexesInRange: NSMakeRange(5, 3)];
printf(" %s\n", [m containsIndex: 4] == YES && [m containsIndex: 5] == NO && [m containsIndex: 8] == YES ? "passed" : "failed");
printf("Can remove range 0-10 from mutable set...");
[m removeIndexesInRange: NSMakeRange(0, 11)];
printf(" %s\n", [m isEqual: [NSIndexSet indexSet]] == YES ? "passed" : "failed");
// NSLog(@"%@", m);
[arp release];
exit (0);
}