Add more fast enumeration code

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27712 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-01-28 13:31:00 +00:00
parent afb0f171c7
commit f2a92b88ec
4 changed files with 60 additions and 6 deletions

View file

@ -2,6 +2,8 @@
* Headers/Foundation/NSEnumerator.h: * Headers/Foundation/NSEnumerator.h:
* Source/NSEnumerator.m: * Source/NSEnumerator.m:
* Source/GSArray.m:
* Source/GSprivate.h:
Add Apple's fast enumeration protocol. Add Apple's fast enumeration protocol.
2009-01-28 Richard Frith-Macdonald <rfm@gnu.org> 2009-01-28 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -367,6 +367,15 @@ static Class GSInlineArrayClass;
aBuffer[j++] = _contents_array[i]; aBuffer[j++] = _contents_array[i];
} }
} }
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (id*)stackbuf
count: (NSUInteger)len
{
/* For immutable arrays we can return the contents pointer directly. */
state->itemsPtr = _contents_array;
return _count;
}
@end @end
#if !GS_WITH_GC #if !GS_WITH_GC
@ -437,6 +446,7 @@ static Class GSInlineArrayClass;
- (void) addObject: (id)anObject - (void) addObject: (id)anObject
{ {
_version++;
if (anObject == nil) if (anObject == nil)
{ {
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
@ -459,6 +469,7 @@ static Class GSInlineArrayClass;
} }
_contents_array[_count] = RETAIN(anObject); _contents_array[_count] = RETAIN(anObject);
_count++; /* Do this AFTER we have retained the object. */ _count++; /* Do this AFTER we have retained the object. */
_version++;
} }
/** /**
@ -479,6 +490,7 @@ static Class GSInlineArrayClass;
- (void) exchangeObjectAtIndex: (unsigned int)i1 - (void) exchangeObjectAtIndex: (unsigned int)i1
withObjectAtIndex: (unsigned int)i2 withObjectAtIndex: (unsigned int)i2
{ {
_version++;
if (i1 >= _count) if (i1 >= _count)
{ {
[self _raiseRangeExceptionWithIndex: i1 from: _cmd]; [self _raiseRangeExceptionWithIndex: i1 from: _cmd];
@ -494,6 +506,7 @@ static Class GSInlineArrayClass;
_contents_array[i1] = _contents_array[i2]; _contents_array[i1] = _contents_array[i2];
_contents_array[i2] = tmp; _contents_array[i2] = tmp;
} }
_version++;
} }
- (id) init - (id) init
@ -572,8 +585,7 @@ static Class GSInlineArrayClass;
- (void) insertObject: (id)anObject atIndex: (unsigned)index - (void) insertObject: (id)anObject atIndex: (unsigned)index
{ {
unsigned i; _version++;
if (!anObject) if (!anObject)
{ {
NSException *exception; NSException *exception;
@ -607,10 +619,7 @@ static Class GSInlineArrayClass;
_capacity += _grow_factor; _capacity += _grow_factor;
_grow_factor = _capacity/2; _grow_factor = _capacity/2;
} }
for (i = _count; i > index; i--) memmove(&_contents_array[index], &_contents_array[index+1], _count - index);
{
_contents_array[i] = _contents_array[i - 1];
}
/* /*
* Make sure the array is 'sane' so that it can be deallocated * Make sure the array is 'sane' so that it can be deallocated
* safely by an autorelease pool if the '[anObject retain]' causes * safely by an autorelease pool if the '[anObject retain]' causes
@ -619,6 +628,7 @@ static Class GSInlineArrayClass;
_contents_array[index] = nil; _contents_array[index] = nil;
_count++; _count++;
_contents_array[index] = RETAIN(anObject); _contents_array[index] = RETAIN(anObject);
_version++;
} }
- (id) makeImmutableCopyOnFail: (BOOL)force - (id) makeImmutableCopyOnFail: (BOOL)force
@ -635,6 +645,7 @@ static Class GSInlineArrayClass;
- (void) removeLastObject - (void) removeLastObject
{ {
_version++;
if (_count == 0) if (_count == 0)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
@ -643,12 +654,14 @@ static Class GSInlineArrayClass;
_count--; _count--;
RELEASE(_contents_array[_count]); RELEASE(_contents_array[_count]);
_contents_array[_count] = 0; _contents_array[_count] = 0;
_version++;
} }
- (void) removeObject: (id)anObject - (void) removeObject: (id)anObject
{ {
unsigned index; unsigned index;
_version++;
if (anObject == nil) if (anObject == nil)
{ {
NSWarnMLog(@"attempt to remove nil object"); NSWarnMLog(@"attempt to remove nil object");
@ -694,12 +707,14 @@ static Class GSInlineArrayClass;
} }
#endif #endif
} }
_version++;
} }
- (void) removeObjectAtIndex: (unsigned)index - (void) removeObjectAtIndex: (unsigned)index
{ {
id obj; id obj;
_version++;
if (index >= _count) if (index >= _count)
{ {
[self _raiseRangeExceptionWithIndex: index from: _cmd]; [self _raiseRangeExceptionWithIndex: index from: _cmd];
@ -713,12 +728,14 @@ static Class GSInlineArrayClass;
} }
_contents_array[_count] = 0; _contents_array[_count] = 0;
RELEASE(obj); /* Adjust array BEFORE releasing object. */ RELEASE(obj); /* Adjust array BEFORE releasing object. */
_version++;
} }
- (void) removeObjectIdenticalTo: (id)anObject - (void) removeObjectIdenticalTo: (id)anObject
{ {
unsigned index; unsigned index;
_version++;
if (anObject == nil) if (anObject == nil)
{ {
NSWarnMLog(@"attempt to remove nil object"); NSWarnMLog(@"attempt to remove nil object");
@ -743,12 +760,14 @@ static Class GSInlineArrayClass;
RELEASE(obj); RELEASE(obj);
} }
} }
_version++;
} }
- (void) replaceObjectAtIndex: (unsigned)index withObject: (id)anObject - (void) replaceObjectAtIndex: (unsigned)index withObject: (id)anObject
{ {
id obj; id obj;
_version++;
if (index >= _count) if (index >= _count)
{ {
[self _raiseRangeExceptionWithIndex: index from: _cmd]; [self _raiseRangeExceptionWithIndex: index from: _cmd];
@ -776,6 +795,7 @@ static Class GSInlineArrayClass;
IF_NO_GC(RETAIN(anObject)); IF_NO_GC(RETAIN(anObject));
_contents_array[index] = anObject; _contents_array[index] = anObject;
RELEASE(obj); RELEASE(obj);
_version++;
} }
- (void) sortUsingFunction: (NSComparisonResult(*)(id,id,void*))compare - (void) sortUsingFunction: (NSComparisonResult(*)(id,id,void*))compare
@ -793,6 +813,7 @@ static Class GSInlineArrayClass;
BOOL badComparison = NO; BOOL badComparison = NO;
#endif #endif
_version++;
while (stride <= count) while (stride <= count)
{ {
stride = stride * STRIDE_FACTOR + 1; stride = stride * STRIDE_FACTOR + 1;
@ -852,6 +873,7 @@ static Class GSInlineArrayClass;
NSWarnMLog(@"Detected bad return value from comparison"); NSWarnMLog(@"Detected bad return value from comparison");
} }
#endif #endif
_version++;
} }
- (NSEnumerator*) objectEnumerator - (NSEnumerator*) objectEnumerator
@ -870,6 +892,34 @@ static Class GSInlineArrayClass;
return AUTORELEASE([enumerator initWithArray: (GSArray*)self]); return AUTORELEASE([enumerator initWithArray: (GSArray*)self]);
} }
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (id*)stackbuf
count: (NSUInteger)len
{
NSInteger count;
/* This is cached in the caller at the start and compared at each
* iteration. If it changes during the iteration then
* objc_enumerationMutation() will be called, throwing an exception.
*/
state->mutationsPtr = (unsigned long*)_version;
count = MIN(len, _count - state->state);
/* If a mutation has occurred then it's possible that we are being asked to
* get objects from after the end of the array. Don't pass negative values
* to memcpy.
*/
if (count <= 0)
{
memcpy(stackbuf, _contents_array, count);
state->state += count;
}
else
{
count = 0;
}
state->itemsPtr = stackbuf;
return count;
}
@end @end

View file

@ -70,6 +70,7 @@
unsigned _count; unsigned _count;
unsigned _capacity; unsigned _capacity;
int _grow_factor; int _grow_factor;
int _version;
} }
@end @end

View file

@ -91,6 +91,7 @@
} }
*(stackbuf+i) = next; *(stackbuf+i) = next;
} }
state->itemsPtr;
return len; return len;
} }
@end @end