Fix bug removing from index set.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@19615 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2004-06-25 06:53:15 +00:00
parent 0dee75786f
commit 97b8ebd06a
3 changed files with 112 additions and 71 deletions

View file

@ -1,3 +1,10 @@
2004-06-25 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSIndexSet.m: Rewrite range removal to fix bug reported
by Fred Kiefer.
* Testing/nsindexset.m: Add test for deletion of range which has
partial overlap with two others.
2004-06-24 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSIndexSet.m: Remove some redundant code for clarity.

View file

@ -710,6 +710,7 @@ static unsigned posForIndex(GSIArray array, unsigned index)
- (void) removeIndexesInRange: (NSRange)aRange
{
unsigned pos;
NSRange r;
if (NSNotFound - aRange.length < aRange.location)
{
@ -717,95 +718,103 @@ static unsigned posForIndex(GSIArray array, unsigned index)
format: @"[%@-%@]: Bad range",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (aRange.length == 0 || _array == 0 || GSIArrayCount(_array) == 0)
if (aRange.length == 0 || _array == 0
|| (pos = posForIndex(_array, aRange.location)) >= GSIArrayCount(_array))
{
return; // Already empty
}
pos = posForIndex(_array, aRange.location);
r = GSIArrayItemAtIndex(_array, pos).ext;
if (r.location <= aRange.location)
{
if (r.location == aRange.location)
{
if (NSMaxRange(r) <= NSMaxRange(aRange))
{
/*
* Found range is entirely within range to remove,
* leaving next range to check at current position.
*/
GSIArrayRemoveItemAtIndex(_array, pos);
}
else
{
/*
* Range to remove is entirely within found range and
* overlaps the start of the found range ... shrink it
* and trhen we are finished.
*/
r.location += aRange.length;
r.length -= aRange.length;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
return;
}
}
else
{
if (NSMaxRange(r) <= NSMaxRange(aRange))
{
/*
* Range to remove overlaps the end of the found range.
* May also overlap next range ... so shorten found
* range and move on.
*/
r.length = aRange.location - r.location;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
pos++;
}
else
{
NSRange next = r;
/*
* Range to remove is entirely within found range and
* overlaps the middle of the found range ... split it.
* Then we are finished.
*/
next.location = NSMaxRange(aRange);
next.length = NSMaxRange(r) - next.location;
r.length = aRange.location - r.location;
GSIArraySetItemAtIndex(_array, (GSIArrayItem)r, pos);
pos++;
GSIArrayInsertItem(_array, (GSIArrayItem)next, pos);
return;
}
}
}
/*
* Remove any ranges contained entirely in the one to be removed.
* At this point we are guaranteed that, if there is a range at pos,
* it does not start before aRange.location
*/
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)
if (NSMaxRange(r) <= NSMaxRange(aRange))
{
/*
* The existing range might overlap or mcontain the range to remove.
* Found range is entirely within range to remove ...
* delete it.
*/
if (NSMaxRange(r) >= NSMaxRange(aRange))
GSIArrayRemoveItemAtIndex(_array, pos);
}
else
{
if (r.location < NSMaxRange(aRange))
{
/*
* Range to remove is contained in the range we found ...
* Range to remove overlaps start of found range ...
* shorten it.
*/
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;
r.length = NSMaxRange(r) - NSMaxRange(aRange);
r.location = NSMaxRange(aRange);
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);
}
}
}
/*
* Found range extends beyond range to remove ... finished.
*/
return;
}
}
}

View file

@ -6,6 +6,7 @@ main ()
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSIndexSet *s;
NSMutableIndexSet *m;
NSMutableIndexSet *o;
unsigned int buf[2];
NSRange r;
@ -179,6 +180,30 @@ main ()
[m removeIndexesInRange: NSMakeRange(0, 11)];
printf(" %s\n", [m isEqual: [NSIndexSet indexSet]] == YES ? "passed" : "failed");
o = [NSMutableIndexSet indexSet];
[m addIndex: 3];
[m addIndex: 4];
[m addIndex: 6];
[m addIndex: 7];
[o addIndex: 3];
[o addIndex: 7];
printf("Can remove range 4-6 from mutable set containing 3,4,6,7 ...");
[m removeIndexesInRange: NSMakeRange(4, 3)];
printf(" %s\n", [m isEqual: o] == YES ? "passed" : "failed");
[m addIndex: 3];
[m addIndex: 4];
[m addIndex: 6];
[m addIndex: 7];
[m addIndex: 8];
[m addIndex: 9];
[o addIndex: 3];
[o removeIndex: 7];
[o addIndex: 9];
printf("Can remove range 4-8 from mutable set containing 3,4,6,7,8,9 ...");
[m removeIndexesInRange: NSMakeRange(4, 5)];
printf(" %s\n", [m isEqual: o] == YES ? "passed" : "failed");
// NSLog(@"%@", m);
[arp release];
exit (0);