Optimisation

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4894 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-09-14 19:24:58 +00:00
parent 24886c5b3a
commit 6a01c2a85d
3 changed files with 501 additions and 226 deletions

View file

@ -1,3 +1,10 @@
Tue Sep 14 20:44:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSArray.m: Huge amounts of optimisation.
Memory leak fixed in ([-initWithFile:]).
* Source/NSGArray.m: Optimisations of less-used methods, including
implementation of fast enumerators.
Tue Sep 14 15:11:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk> Tue Sep 14 15:11:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSTimer.m: minor optimisations * Source/NSTimer.m: minor optimisations

View file

@ -50,9 +50,19 @@
@interface NSMutableArrayNonCore : NSMutableArray @interface NSMutableArrayNonCore : NSMutableArray
@end @end
static Class NSArray_abstract_class;
static Class NSArray_concrete_class; static Class NSArray_concrete_class;
static Class NSMutableArray_abstract_class;
static Class NSMutableArray_concrete_class; static Class NSMutableArray_concrete_class;
static SEL addSel = @selector(addObject:);
static SEL appSel = @selector(appendString:);
static SEL countSel = @selector(count);
static SEL eqSel = @selector(isEqual:);
static SEL oaiSel = @selector(objectAtIndex:);
static SEL remSel = @selector(removeObjectAtIndex:);
static SEL rlSel = @selector(removeLastObject);
@implementation NSArray @implementation NSArray
@ -60,6 +70,8 @@ static Class NSMutableArray_concrete_class;
{ {
if (self == [NSArray class]) if (self == [NSArray class])
{ {
NSArray_abstract_class = [NSArray class];
NSMutableArray_abstract_class = [NSMutableArray class];
NSArray_concrete_class = [NSGArray class]; NSArray_concrete_class = [NSGArray class];
NSMutableArray_concrete_class = [NSGMutableArray class]; NSMutableArray_concrete_class = [NSGMutableArray class];
behavior_class_add_class (self, [NSArrayNonCore class]); behavior_class_add_class (self, [NSArrayNonCore class]);
@ -86,31 +98,31 @@ static Class NSMutableArray_concrete_class;
return NSMutableArray_concrete_class; return NSMutableArray_concrete_class;
} }
+ allocWithZone: (NSZone*)z + (id) allocWithZone: (NSZone*)z
{ {
if ([self class] == [NSArray class]) if ([self class] == NSArray_abstract_class)
return NSAllocateObject ([self _concreteClass], 0, z); return NSAllocateObject(NSArray_concrete_class, 0, z);
return [super allocWithZone: z]; return [super allocWithZone: z];
} }
+ array + (id) array
{ {
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] init]); return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] init]);
} }
+ arrayWithArray: (NSArray*)array + (id) arrayWithArray: (NSArray*)array
{ {
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithArray: array]); initWithArray: array]);
} }
+ arrayWithContentsOfFile: (NSString*)file + (id) arrayWithContentsOfFile: (NSString*)file
{ {
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithContentsOfFile: file]); initWithContentsOfFile: file]);
} }
+ arrayWithObject: anObject + (id) arrayWithObject: anObject
{ {
if (anObject == nil) if (anObject == nil)
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
@ -120,7 +132,7 @@ static Class NSMutableArray_concrete_class;
} }
/* This is the designated initializer for NSArray. */ /* This is the designated initializer for NSArray. */
- initWithObjects: (id*)objects count: (unsigned)count - (id) initWithObjects: (id*)objects count: (unsigned)count
{ {
[self subclassResponsibility: _cmd]; [self subclassResponsibility: _cmd];
return nil; return nil;
@ -132,7 +144,7 @@ static Class NSMutableArray_concrete_class;
return 0; return 0;
} }
- objectAtIndex: (unsigned)index - (id) objectAtIndex: (unsigned)index
{ {
[self subclassResponsibility: _cmd]; [self subclassResponsibility: _cmd];
return nil; return nil;
@ -142,55 +154,54 @@ static Class NSMutableArray_concrete_class;
- (void) encodeWithCoder: (NSCoder*)aCoder - (void) encodeWithCoder: (NSCoder*)aCoder
{ {
unsigned count = [self count]; unsigned count = [self count];
[aCoder encodeValueOfObjCType: @encode(unsigned) [aCoder encodeValueOfObjCType: @encode(unsigned)
at: &count]; at: &count];
if (count > 0) { if (count > 0)
unsigned i; {
id a[count];
for (i = 0; i < count; i++) { [self getObjects: a];
[aCoder encodeObject: [self objectAtIndex: i]]; [aCoder encodeArrayOfObjCType: @encode(id)
} count: count
at: a];
} }
} }
- (id) initWithCoder: (NSCoder*)aCoder - (id) initWithCoder: (NSCoder*)aCoder
{ {
unsigned count; unsigned count;
if ([aCoder systemVersion] == 0) { [aCoder decodeValueOfObjCType: @encode(unsigned)
unsigned dummy; at: &count];
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &dummy]; if (count > 0)
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &dummy]; {
} id contents[count];
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &count];
if (count > 0) {
id contents[count];
int i;
for (i = 0; i < count; i++) { [aCoder decodeArrayOfObjCType: @encode(id)
contents[i] = [aCoder decodeObject]; count: count
} at: contents];
return [self initWithObjects: contents count: count]; return [self initWithObjects: contents count: count];
} }
else
return [self initWithObjects: 0 count: 0]; return [self initWithObjects: 0 count: 0];
} }
/* The NSCopying Protocol */ /* The NSCopying Protocol */
- copyWithZone: (NSZone*)zone - (id) copyWithZone: (NSZone*)zone
{ {
return RETAIN(self); return RETAIN(self);
} }
/* The NSMutableCopying Protocol */ /* The NSMutableCopying Protocol */
- mutableCopyWithZone: (NSZone*)zone - (id) mutableCopyWithZone: (NSZone*)zone
{ {
return [[[[self class] _mutableConcreteClass] allocWithZone: zone] return [[NSMutableArray_concrete_class allocWithZone: zone]
initWithArray: self]; initWithArray: self];
} }
@end @end
@ -198,20 +209,26 @@ static Class NSMutableArray_concrete_class;
@implementation NSArrayNonCore @implementation NSArrayNonCore
- (NSArray*) arrayByAddingObject: anObject - (NSArray*) arrayByAddingObject: (id)anObject
{ {
id na; id na;
unsigned c; unsigned c = [self count];
c = [self count]; if (anObject == nil)
{ [NSException raise: NSInvalidArgumentException
id objects[c+1]; format: @"Attempt to add nil to an array"];
if (c == 0)
na = [[NSArray_concrete_class allocWithZone: NSDefaultMallocZone()]
initWithObjects: &anObject count: 1];
else
{
id objects[c+1];
[self getObjects: objects]; [self getObjects: objects];
objects[c] = anObject; objects[c] = anObject;
na = [[NSArray allocWithZone: NSDefaultMallocZone()] na = [[NSArray_concrete_class allocWithZone: NSDefaultMallocZone()]
initWithObjects: objects count: c+1]; initWithObjects: objects count: c+1];
} }
return AUTORELEASE(na); return AUTORELEASE(na);
} }
@ -227,12 +244,12 @@ static Class NSMutableArray_concrete_class;
[self getObjects: objects]; [self getObjects: objects];
[anotherArray getObjects: &objects[c]]; [anotherArray getObjects: &objects[c]];
na = [NSArray arrayWithObjects: objects count: c+l]; na = [NSArray_abstract_class arrayWithObjects: objects count: c+l];
} }
return na; return na;
} }
- initWithObjects: firstObject rest: (va_list) ap - (id) initWithObjects: firstObject rest: (va_list) ap
{ {
register unsigned i; register unsigned i;
register unsigned curSize; register unsigned curSize;
@ -278,7 +295,7 @@ static Class NSMutableArray_concrete_class;
return( self ); return( self );
} }
- initWithObjects: firstObject, ... - (id) initWithObjects: firstObject, ...
{ {
va_list ap; va_list ap;
va_start(ap, firstObject); va_start(ap, firstObject);
@ -287,7 +304,7 @@ static Class NSMutableArray_concrete_class;
return self; return self;
} }
- initWithContentsOfFile: (NSString*)file - (id) initWithContentsOfFile: (NSString*)file
{ {
NSString *myString; NSString *myString;
@ -295,7 +312,7 @@ static Class NSMutableArray_concrete_class;
initWithContentsOfFile: file]; initWithContentsOfFile: file];
if (myString) if (myString)
{ {
id result = [myString propertyList]; id result;
NS_DURING NS_DURING
{ {
@ -307,7 +324,7 @@ static Class NSMutableArray_concrete_class;
} }
NS_ENDHANDLER NS_ENDHANDLER
RELEASE(myString); RELEASE(myString);
if ([result isKindOfClass: [NSArray class]]) if ([result isKindOfClass: NSArray_abstract_class])
{ {
[self initWithArray: result]; [self initWithArray: result];
return self; return self;
@ -318,7 +335,7 @@ static Class NSMutableArray_concrete_class;
return nil; return nil;
} }
+ arrayWithObjects: firstObject, ... + (id) arrayWithObjects: firstObject, ...
{ {
va_list ap; va_list ap;
va_start(ap, firstObject); va_start(ap, firstObject);
@ -328,13 +345,13 @@ static Class NSMutableArray_concrete_class;
return AUTORELEASE(self); return AUTORELEASE(self);
} }
+ arrayWithObjects: (id*)objects count: (unsigned)count + (id) arrayWithObjects: (id*)objects count: (unsigned)count
{ {
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithObjects: objects count: count]); initWithObjects: objects count: count]);
} }
- initWithArray: (NSArray*)array - (id) initWithArray: (NSArray*)array
{ {
unsigned c; unsigned c;
@ -351,19 +368,21 @@ static Class NSMutableArray_concrete_class;
- (void) getObjects: (id*)aBuffer - (void) getObjects: (id*)aBuffer
{ {
unsigned i, c = [self count]; unsigned i, c = [self count];
IMP get = [self methodForSelector: oaiSel];
for (i = 0; i < c; i++) for (i = 0; i < c; i++)
aBuffer[i] = [self objectAtIndex: i]; aBuffer[i] = (*get)(self, oaiSel, i);
} }
- (void) getObjects: (id*)aBuffer range: (NSRange)aRange - (void) getObjects: (id*)aBuffer range: (NSRange)aRange
{ {
unsigned i, j = 0, c = [self count], e = aRange.location + aRange.length; unsigned i, j = 0, c = [self count], e = aRange.location + aRange.length;
IMP get = [self methodForSelector: oaiSel];
GS_RANGE_CHECK(aRange, c); GS_RANGE_CHECK(aRange, c);
for (i = aRange.location; i < e; i++) for (i = aRange.location; i < e; i++)
aBuffer[j++] = [self objectAtIndex: i]; aBuffer[j++] = (*get)(self, oaiSel, i);
} }
- (unsigned) hash - (unsigned) hash
@ -373,46 +392,65 @@ static Class NSMutableArray_concrete_class;
- (unsigned) indexOfObjectIdenticalTo: anObject - (unsigned) indexOfObjectIdenticalTo: anObject
{ {
unsigned i, c = [self count]; unsigned c = [self count];
for (i = 0; i < c; i++)
if (anObject == [self objectAtIndex: i]) if (c > 0)
return i; {
IMP get = [self methodForSelector: oaiSel];
unsigned i;
for (i = 0; i < c; i++)
if (anObject == (*get)(self, oaiSel, i))
return i;
}
return NSNotFound; return NSNotFound;
} }
- (unsigned) indexOfObjectIdenticalTo: anObject inRange: (NSRange)aRange - (unsigned) indexOfObjectIdenticalTo: anObject inRange: (NSRange)aRange
{ {
unsigned i, e = aRange.location + aRange.length, c = [self count]; unsigned i, e = aRange.location + aRange.length, c = [self count];
IMP get = [self methodForSelector: oaiSel];
GS_RANGE_CHECK(aRange, c); GS_RANGE_CHECK(aRange, c);
for (i = aRange.location; i < e; i++) for (i = aRange.location; i < e; i++)
if (anObject == [self objectAtIndex: i]) if (anObject == (*get)(self, oaiSel, i))
return i; return i;
return NSNotFound; return NSNotFound;
} }
/* Inefficient, should be overridden. */ /* Inefficient, should be overridden. */
- (unsigned) indexOfObject: anObject - (unsigned) indexOfObject: (id)anObject
{ {
unsigned i, c = [self count]; unsigned c = [self count];
for (i = 0; i < c; i++)
if ([[self objectAtIndex: i] isEqual: anObject]) if (c > 0 && anObject != nil)
return i; {
unsigned i;
IMP get = [self methodForSelector: oaiSel];
BOOL (*eq)(id, SEL, id)
= (BOOL (*)(id, SEL, id))[anObject methodForSelector: eqSel];
for (i = 0; i < c; i++)
if ((*eq)(anObject, eqSel, (*get)(self, oaiSel, i)) == YES)
return i;
}
return NSNotFound; return NSNotFound;
} }
/* Inefficient, should be overridden. */ /* Inefficient, should be overridden. */
- (unsigned) indexOfObject: anObject inRange: (NSRange)aRange - (unsigned) indexOfObject: (id)anObject inRange: (NSRange)aRange
{ {
unsigned i, e = aRange.location + aRange.length, c = [self count]; unsigned i, e = aRange.location + aRange.length, c = [self count];
IMP get = [self methodForSelector: oaiSel];
BOOL (*eq)(id, SEL, id)
= (BOOL (*)(id, SEL, id))[anObject methodForSelector: eqSel];
GS_RANGE_CHECK(aRange, c); GS_RANGE_CHECK(aRange, c);
for (i = aRange.location; i < e; i++) for (i = aRange.location; i < e; i++)
{ {
id o = [self objectAtIndex: i]; if ((*eq)(anObject, eqSel, (*get)(self, oaiSel, i)) == YES)
if (anObject == o || [o isEqual: anObject])
return i; return i;
} }
return NSNotFound; return NSNotFound;
@ -423,26 +461,37 @@ static Class NSMutableArray_concrete_class;
return ([self indexOfObject: anObject] != NSNotFound); return ([self indexOfObject: anObject] != NSNotFound);
} }
- (BOOL) isEqual: anObject - (BOOL) isEqual: (id)anObject
{ {
if ([anObject isKindOf: [NSArray class]]) if (self == anObject)
return YES;
if ([anObject isKindOfClass: NSArray_abstract_class])
return [self isEqualToArray: anObject]; return [self isEqualToArray: anObject];
return NO; return NO;
} }
- (BOOL) isEqualToArray: (NSArray*)otherArray - (BOOL) isEqualToArray: (NSArray*)otherArray
{ {
unsigned i, c = [self count]; unsigned i, c;
if (self == (id)otherArray)
return YES;
c = [self count];
if (c != [otherArray count]) if (c != [otherArray count])
return NO; return NO;
for (i = 0; i < c; i++) if (c > 0)
if (![[self objectAtIndex: i] isEqual: [otherArray objectAtIndex: i]]) {
return NO; IMP get0 = [self methodForSelector: oaiSel];
IMP get1 = [otherArray methodForSelector: oaiSel];
for (i = 0; i < c; i++)
if (![(*get0)(self, oaiSel, i) isEqual: (*get1)(otherArray, oaiSel, i)])
return NO;
}
return YES; return YES;
} }
- lastObject - (id) lastObject
{ {
unsigned count = [self count]; unsigned count = [self count];
if (count == 0) if (count == 0)
@ -453,8 +502,14 @@ static Class NSMutableArray_concrete_class;
- (void) makeObjectsPerformSelector: (SEL)aSelector - (void) makeObjectsPerformSelector: (SEL)aSelector
{ {
unsigned i = [self count]; unsigned i = [self count];
while (i-- > 0)
[[self objectAtIndex: i] performSelector: aSelector]; if (i > 0)
{
IMP get = [self methodForSelector: oaiSel];
while (i-- > 0)
[(*get)(self, oaiSel, i) performSelector: aSelector];
}
} }
- (void) makeObjectsPerform: (SEL)aSelector - (void) makeObjectsPerform: (SEL)aSelector
@ -462,14 +517,20 @@ static Class NSMutableArray_concrete_class;
[self makeObjectsPerformSelector: aSelector]; [self makeObjectsPerformSelector: aSelector];
} }
- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: argument - (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id) arg
{ {
unsigned i = [self count]; unsigned i = [self count];
while (i-- > 0)
[[self objectAtIndex: i] performSelector: aSelector withObject: argument]; if (i > 0)
{
IMP get = [self methodForSelector: oaiSel];
while (i-- > 0)
[(*get)(self, oaiSel, i) performSelector: aSelector withObject: arg];
}
} }
- (void) makeObjectsPerform: (SEL)aSelector withObject: argument - (void) makeObjectsPerform: (SEL)aSelector withObject: (id)argument
{ {
[self makeObjectsPerformSelector: aSelector withObject: argument]; [self makeObjectsPerformSelector: aSelector withObject: argument];
} }
@ -481,7 +542,7 @@ static Class NSMutableArray_concrete_class;
return (int)[elem1 performSelector: comparator withObject: elem2]; return (int)[elem1 performSelector: comparator withObject: elem2];
} }
return [self sortedArrayUsingFunction: compare context: NULL]; return [self sortedArrayUsingFunction: compare context: NULL];
} }
- (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator - (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator
@ -492,7 +553,7 @@ static Class NSMutableArray_concrete_class;
- (NSData*) sortedArrayHint - (NSData*) sortedArrayHint
{ {
return nil; return nil;
} }
- (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator - (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator
@ -502,10 +563,10 @@ static Class NSMutableArray_concrete_class;
NSMutableArray *sortedArray; NSMutableArray *sortedArray;
NSArray *result; NSArray *result;
sortedArray = [[NSMutableArray allocWithZone: NSDefaultMallocZone()] sortedArray = [[NSMutableArray_abstract_class allocWithZone:
initWithArray: self]; NSDefaultMallocZone()] initWithArray: self];
[sortedArray sortUsingFunction: comparator context: context]; [sortedArray sortUsingFunction: comparator context: context];
result = [NSArray arrayWithArray: sortedArray]; result = [NSArray_abstract_class arrayWithArray: sortedArray];
RELEASE(sortedArray); RELEASE(sortedArray);
return result; return result;
} }
@ -530,17 +591,22 @@ static Class NSMutableArray_concrete_class;
{ {
unsigned i, c = [self count]; unsigned i, c = [self count];
NSMutableArray *a = [NSMutableArray arrayWithCapacity: 1]; NSMutableArray *a = [NSMutableArray arrayWithCapacity: 1];
Class cls = [NSString class];
IMP get = [self methodForSelector: oaiSel];
IMP add = [a methodForSelector: addSel];
for (i = 0; i < c; i++) for (i = 0; i < c; i++)
{ {
id o = [self objectAtIndex: i]; id o = (*get)(self, oaiSel, i);
if ([o isKindOfClass: [NSString class]])
if ([o isKindOfClass: cls])
if ([extensions containsObject: [o pathExtension]]) if ([extensions containsObject: [o pathExtension]])
[a addObject: o]; (*add)(a, addSel, o);
} }
return a; return a;
} }
- firstObjectCommonWithArray: (NSArray*)otherArray - (id) firstObjectCommonWithArray: (NSArray*)otherArray
{ {
unsigned i, c = [self count]; unsigned i, c = [self count];
id o; id o;
@ -627,10 +693,8 @@ static NSString *indentStrings[] = {
unsigned count = [self count]; unsigned count = [self count];
NSString *plists[count]; NSString *plists[count];
unsigned i; unsigned i;
SEL appSel;
IMP appImp; IMP appImp;
appSel = @selector(appendString:);
appImp = [(NSObject*)result methodForSelector: appSel]; appImp = [(NSObject*)result methodForSelector: appSel];
if (level < sizeof(indentStrings)/sizeof(NSString*)) if (level < sizeof(indentStrings)/sizeof(NSString*))
@ -693,16 +757,16 @@ static NSString *indentStrings[] = {
} }
} }
+ allocWithZone: (NSZone*)z + (id) allocWithZone: (NSZone*)z
{ {
if ([self class] == [NSMutableArray class]) if (self == NSMutableArray_abstract_class)
return NSAllocateObject ([self _mutableConcreteClass], 0, z); return NSAllocateObject(NSMutableArray_concrete_class, 0, z);
return [super allocWithZone: z]; return [super allocWithZone: z];
} }
/* The NSCopying Protocol */ /* The NSCopying Protocol */
- copyWithZone: (NSZone*)zone - (id) copyWithZone: (NSZone*)zone
{ {
/* a deep copy */ /* a deep copy */
unsigned count = [self count]; unsigned count = [self count];
@ -713,15 +777,15 @@ static NSString *indentStrings[] = {
[self getObjects: objects]; [self getObjects: objects];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
objects[i] = [objects[i] copyWithZone: zone]; objects[i] = [objects[i] copyWithZone: zone];
newArray = [[[[self class] _concreteClass] allocWithZone: zone] newArray = [[NSArray_concrete_class allocWithZone: zone]
initWithObjects: objects count: count]; initWithObjects: objects count: count];
while (i > 0) while (i > 0)
RELEASE(objects[--i]); RELEASE(objects[--i]);
return newArray; return newArray;
} }
/* This is the desgnated initializer for NSMutableArray */ /* This is the desgnated initializer for NSMutableArray */
- initWithCapacity: (unsigned)numItems - (id) initWithCapacity: (unsigned)numItems
{ {
[self subclassResponsibility: _cmd]; [self subclassResponsibility: _cmd];
return nil; return nil;
@ -774,127 +838,174 @@ static NSString *indentStrings[] = {
@implementation NSMutableArrayNonCore @implementation NSMutableArrayNonCore
+ arrayWithCapacity: (unsigned)numItems + (id) arrayWithCapacity: (unsigned)numItems
{ {
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithCapacity: numItems]); initWithCapacity: numItems]);
} }
- (BOOL)writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile - (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile
{ {
return [[self description] writeToFile: path atomically: useAuxiliaryFile]; return [[self description] writeToFile: path atomically: useAuxiliaryFile];
} }
/* Override our superclass's designated initializer to go our's */ /* Override our superclass's designated initializer to go our's */
- initWithObjects: (id*)objects count: (unsigned)count - (id) initWithObjects: (id*)objects count: (unsigned)count
{ {
unsigned i;
self = [self initWithCapacity: count]; self = [self initWithCapacity: count];
for (i = 0; i < count; i++) if (count > 0)
[self addObject: objects[i]]; {
unsigned i;
IMP add = [self methodForSelector: addSel];
for (i = 0; i < count; i++)
(*add)(self, addSel, objects[i]);
}
return self; return self;
} }
- (void) removeLastObject - (void) removeLastObject
{ {
unsigned count = [self count]; unsigned count = [self count];
if (count == 0) if (count == 0)
[NSException raise: NSRangeException [NSException raise: NSRangeException
format: @"Trying to remove from an empty array."]; format: @"Trying to remove from an empty array."];
[self removeObjectAtIndex: count-1]; [self removeObjectAtIndex: count-1];
} }
- (void) removeObjectIdenticalTo: anObject - (void) removeObjectIdenticalTo: (id)anObject
{ {
unsigned pos = NSNotFound; unsigned i = [self count];
unsigned i = [self count];
while (i-- > 0) if (i > 0)
{ {
id o = [self objectAtIndex: i]; IMP rem = 0;
if (o == anObject) IMP get = [self methodForSelector: oaiSel];
while (i-- > 0)
{ {
if (pos != NSNotFound) id o = (*get)(self, oaiSel, i);
[self removeObjectAtIndex: pos];
pos = i; if (o == anObject)
{
if (rem == 0)
rem = [self methodForSelector: remSel];
(*rem)(self, remSel, i);
}
} }
} }
if (pos != NSNotFound)
[self removeObjectAtIndex: pos];
} }
- (void) removeObject: anObject inRange: (NSRange)aRange - (void) removeObject: (id)anObject inRange: (NSRange)aRange
{ {
unsigned c = [self count], s = aRange.location; unsigned c = [self count];
unsigned i = aRange.location + aRange.length; unsigned s = aRange.location;
unsigned pos = NSNotFound; unsigned i = aRange.location + aRange.length;
if (i > c) if (i > c)
i = c; i = c;
while (i-- > s)
if (i > s)
{ {
id o = [self objectAtIndex: i]; IMP rem = 0;
if (o == anObject || [o isEqual: anObject]) IMP get = [self methodForSelector: oaiSel];
BOOL (*eq)(id, SEL, id)
= (BOOL (*)(id, SEL, id))[anObject methodForSelector: eqSel];
while (i-- > s)
{ {
if (pos != NSNotFound) id o = (*get)(self, oaiSel, i);
[self removeObjectAtIndex: pos];
pos = i; if (o == anObject || (*eq)(anObject, eqSel, o) == YES)
{
if (rem == 0)
rem = [self methodForSelector: remSel];
(*rem)(self, remSel, i);
}
} }
} }
if (pos != NSNotFound)
[self removeObjectAtIndex: pos];
} }
- (void) removeObjectIdenticalTo: anObject inRange: (NSRange)aRange - (void) removeObjectIdenticalTo: (id)anObject inRange: (NSRange)aRange
{ {
unsigned c = [self count], s = aRange.location; unsigned c = [self count];
unsigned i = aRange.location + aRange.length; unsigned s = aRange.location;
unsigned pos = NSNotFound; unsigned i = aRange.location + aRange.length;
if (i > c) if (i > c)
i = c; i = c;
while (i-- > s)
if (i > s)
{ {
id o = [self objectAtIndex: i]; IMP rem = 0;
if (o == anObject) IMP get = [self methodForSelector: oaiSel];
while (i-- > s)
{ {
if (pos != NSNotFound) id o = (*get)(self, oaiSel, i);
[self removeObjectAtIndex: pos];
pos = i; if (o == anObject)
{
if (rem == 0)
rem = [self methodForSelector: remSel];
(*rem)(self, remSel, i);
}
} }
} }
if (pos != NSNotFound)
[self removeObjectAtIndex: pos];
} }
- (void) removeObject: anObject - (void) removeObject: (id)anObject
{ {
unsigned pos = NSNotFound; unsigned i = [self count];
unsigned i = [self count];
while (i-- > 0) if (i > 0)
{ {
id o = [self objectAtIndex: i]; IMP rem = 0;
if (o == anObject || [o isEqual: anObject]) IMP get = [self methodForSelector: oaiSel];
BOOL (*eq)(id, SEL, id)
= (BOOL (*)(id, SEL, id))[anObject methodForSelector: eqSel];
while (i-- > 0)
{ {
if (pos != NSNotFound) id o = (*get)(self, oaiSel, i);
[self removeObjectAtIndex: pos];
pos = i; if (o == anObject || (*eq)(anObject, eqSel, o) == YES)
{
if (rem == 0)
rem = [self methodForSelector: remSel];
(*rem)(self, remSel, i);
}
} }
} }
if (pos != NSNotFound)
[self removeObjectAtIndex: pos];
} }
- (void) removeAllObjects - (void) removeAllObjects
{ {
while ([self count]) unsigned c = [self count];
[self removeLastObject];
if (c > 0)
{
IMP remLast = [self methodForSelector: rlSel];
while (c--)
(*remLast)(self, rlSel);
}
} }
- (void) addObjectsFromArray: (NSArray*)otherArray - (void) addObjectsFromArray: (NSArray*)otherArray
{ {
unsigned i, c = [otherArray count]; unsigned c = [otherArray count];
for (i = 0; i < c; i++)
[self addObject: [otherArray objectAtIndex: i]]; if (c > 0)
{
unsigned i;
IMP get = [otherArray methodForSelector: oaiSel];
IMP add = [self methodForSelector: addSel];
for (i = 0; i < c; i++)
(*add)(self, addSel, (*get)(otherArray, oaiSel, i));
}
} }
- (void) setArray: (NSArray *)otherArray - (void) setArray: (NSArray *)otherArray
@ -943,28 +1054,51 @@ static NSString *indentStrings[] = {
} }
} }
while (to--) if (to > 0)
{ {
[self removeObjectAtIndex: sorted[to]]; IMP rem = [self methodForSelector: remSel];
while (to--)
{
(*rem)(self, remSel, sorted[to]);
}
} }
} }
} }
- (void) removeObjectsInArray: (NSArray*)otherArray - (void) removeObjectsInArray: (NSArray*)otherArray
{ {
unsigned i, c = [otherArray count]; unsigned c = [otherArray count];
for (i = 0; i < c; i++)
[self removeObject: [otherArray objectAtIndex: i]]; if (c > 0)
{
unsigned i;
IMP get = [otherArray methodForSelector: oaiSel];
IMP rem = [self methodForSelector: @selector(removeObject:)];
for (i = 0; i < c; i++)
(*rem)(self, @selector(removeObject:), (*get)(otherArray, oaiSel, i));
}
} }
- (void) removeObjectsInRange: (NSRange)aRange - (void) removeObjectsInRange: (NSRange)aRange
{ {
unsigned i, s = aRange.location, c = [self count]; unsigned i;
unsigned s = aRange.location;
unsigned c = [self count];
i = aRange.location + aRange.length; i = aRange.location + aRange.length;
if (c < i) if (c < i)
i = c; i = c;
while (i-- > s)
[self removeObjectAtIndex: i]; if (i > s)
{
IMP rem = [self methodForSelector: remSel];
while (i-- > s)
(*rem)(self, remSel, i);
}
} }
- (void) sortUsingSelector: (SEL)comparator - (void) sortUsingSelector: (SEL)comparator
@ -974,7 +1108,7 @@ static NSString *indentStrings[] = {
return (int)[elem1 performSelector: comparator withObject: elem2]; return (int)[elem1 performSelector: comparator withObject: elem2];
} }
[self sortUsingFunction: compare context: NULL]; [self sortUsingFunction: compare context: NULL];
} }
- (void) sortUsingFunction: (int(*)(id,id,void*))compare - (void) sortUsingFunction: (int(*)(id,id,void*))compare
@ -991,58 +1125,67 @@ static NSString *indentStrings[] = {
while (stride <= count) while (stride <= count)
stride = stride * STRIDE_FACTOR + 1; stride = stride * STRIDE_FACTOR + 1;
while(stride > (STRIDE_FACTOR - 1)) { while(stride > (STRIDE_FACTOR - 1))
// loop to sort for each value of stride {
stride = stride / STRIDE_FACTOR; // loop to sort for each value of stride
for (c = stride; c < count; c++) { stride = stride / STRIDE_FACTOR;
found = NO; for (c = stride; c < count; c++)
if (stride > c) {
break; found = NO;
d = c - stride; if (stride > c)
while (!found) {
// move to left until correct place
id a = [self objectAtIndex: d + stride];
id b = [self objectAtIndex: d];
if ((*compare)(a, b, context) == NSOrderedAscending) {
RETAIN(a);
[self replaceObjectAtIndex: d + stride withObject: b];
[self replaceObjectAtIndex: d withObject: a];
RELEASE(a);
if (stride > d)
break; break;
d -= stride; // jump by stride factor d = c - stride;
while (!found)
{
// move to left until correct place
id a = [self objectAtIndex: d + stride];
id b = [self objectAtIndex: d];
if ((*compare)(a, b, context) == NSOrderedAscending)
{
RETAIN(a);
[self replaceObjectAtIndex: d + stride withObject: b];
[self replaceObjectAtIndex: d withObject: a];
RELEASE(a);
if (stride > d)
break;
d -= stride; // jump by stride factor
}
else found = YES;
}
} }
else found = YES;
}
} }
}
} }
@end @end
@interface NSArrayEnumerator : NSEnumerator @interface NSArrayEnumerator : NSEnumerator
{ {
id array; NSArray *array;
int next_index; unsigned pos;
IMP get;
unsigned (*cnt)(NSArray*, SEL);
} }
- (id) initWithArray: (NSArray*)anArray;
@end @end
@implementation NSArrayEnumerator @implementation NSArrayEnumerator
- initWithArray: (NSArray*)anArray - (id) initWithArray: (NSArray*)anArray
{ {
[super init]; [super init];
array = anArray; array = anArray;
RETAIN(array); RETAIN(array);
next_index = 0; pos = 0;
get = [array methodForSelector: oaiSel];
cnt = (unsigned (*)(NSArray*, SEL))[array methodForSelector: countSel];
return self; return self;
} }
- (id) nextObject - (id) nextObject
{ {
if (next_index >= [array count]) if (pos >= (*cnt)(array, countSel))
return nil; return nil;
return [array objectAtIndex: next_index++]; return (*get)(array, oaiSel, pos++);
} }
- (void) dealloc - (void) dealloc
@ -1058,19 +1201,17 @@ static NSString *indentStrings[] = {
@implementation NSArrayEnumeratorReverse @implementation NSArrayEnumeratorReverse
- initWithArray: (NSArray*)anArray - (id) initWithArray: (NSArray*)anArray
{ {
[super init]; [super initWithArray: anArray];
array = anArray; pos = (*cnt)(array, countSel);
RETAIN(array);
next_index = [array count]-1;
return self; return self;
} }
- (id) nextObject - (id) nextObject
{ {
if (next_index < 0) if (pos == 0)
return nil; return nil;
return [array objectAtIndex: next_index--]; return (*get)(array, oaiSel, --pos);
} }
@end @end

View file

@ -1,5 +1,5 @@
/* Concrete implementation of NSArray /* Concrete implementation of NSArray
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu> Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
Date: March 1995 Date: March 1995
@ -29,8 +29,14 @@
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSPortCoder.h> #include <Foundation/NSPortCoder.h>
static SEL eqSel = @selector(isEqual:);
@class NSGArrayEnumerator;
@class NSGArrayEnumeratorReverse;
@interface NSGArray : NSArray @interface NSGArray : NSArray
{ {
@public
id *_contents_array; id *_contents_array;
unsigned _count; unsigned _count;
} }
@ -38,6 +44,7 @@
@interface NSGMutableArray : NSMutableArray @interface NSGMutableArray : NSMutableArray
{ {
@public
id *_contents_array; id *_contents_array;
unsigned _count; unsigned _count;
unsigned _capacity; unsigned _capacity;
@ -166,15 +173,14 @@
*/ */
if (_count > 1) if (_count > 1)
{ {
static SEL sel = @selector(isEqual:);
BOOL (*imp)(id,SEL,id); BOOL (*imp)(id,SEL,id);
unsigned i; unsigned i;
imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: sel]; imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: eqSel];
for (i = 0; i < _count; i++) for (i = 0; i < _count; i++)
{ {
if ((*imp)(anObject, sel, _contents_array[i])) if ((*imp)(anObject, eqSel, _contents_array[i]))
{ {
return i; return i;
} }
@ -413,6 +419,33 @@
RELEASE(_contents_array[_count]); RELEASE(_contents_array[_count]);
} }
- (void) removeObject: (id)anObject
{
unsigned index = _count;
if (index > 0)
{
BOOL (*imp)(id,SEL,id);
imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: eqSel];
while (index-- > 0)
{
if ((*imp)(anObject, eqSel, _contents_array[index]) == YES)
{
id obj = _contents_array[index];
unsigned pos = index;
while (++pos < _count)
{
_contents_array[pos-1] = _contents_array[pos];
}
_count--;
RELEASE(obj);
}
}
}
}
- (void) removeObjectAtIndex: (unsigned)index - (void) removeObjectAtIndex: (unsigned)index
{ {
id obj; id obj;
@ -433,6 +466,27 @@
RELEASE(obj); /* Adjust array BEFORE releasing object. */ RELEASE(obj); /* Adjust array BEFORE releasing object. */
} }
- (void) removeObjectIdenticalTo: (id)anObject
{
unsigned index = _count;
while (index-- > 0)
{
if (_contents_array[index] == anObject)
{
id obj = _contents_array[index];
unsigned pos = index;
while (++pos < _count)
{
_contents_array[pos-1] = _contents_array[pos];
}
_count--;
RELEASE(obj);
}
}
}
- (void) replaceObjectAtIndex: (unsigned)index withObject: (id)anObject - (void) replaceObjectAtIndex: (unsigned)index withObject: (id)anObject
{ {
id obj; id obj;
@ -467,29 +521,102 @@
while (stride <= count) while (stride <= count)
stride = stride * STRIDE_FACTOR + 1; stride = stride * STRIDE_FACTOR + 1;
while(stride > (STRIDE_FACTOR - 1)) { while (stride > (STRIDE_FACTOR - 1))
// loop to sort for each value of stride {
stride = stride / STRIDE_FACTOR; // loop to sort for each value of stride
for (c = stride; c < count; c++) { stride = stride / STRIDE_FACTOR;
found = NO; for (c = stride; c < count; c++)
if (stride > c) {
break; found = NO;
d = c - stride; if (stride > c)
while (!found) {
// move to left until correct place
id a = _contents_array[d + stride];
id b = _contents_array[d];
if ((*compare)(a, b, context) == NSOrderedAscending) {
_contents_array[d+stride] = b;
_contents_array[d] = a;
if (stride > d)
break; break;
d -= stride; // jump by stride factor d = c - stride;
while (!found)
{
// move to left until correct place
id a = _contents_array[d + stride];
id b = _contents_array[d];
if ((*compare)(a, b, context) == NSOrderedAscending)
{
_contents_array[d+stride] = b;
_contents_array[d] = a;
if (stride > d)
break;
d -= stride; // jump by stride factor
}
else
found = YES;
}
} }
else found = YES;
}
} }
} }
- (NSEnumerator*) objectEnumerator
{
return AUTORELEASE([[NSGArrayEnumerator allocWithZone: NSDefaultMallocZone()]
initWithArray: self]);
}
- (NSEnumerator*) reverseObjectEnumerator
{
return AUTORELEASE([[NSGArrayEnumeratorReverse allocWithZone:
NSDefaultMallocZone()] initWithArray: self]);
} }
@end @end
@interface NSGArrayEnumerator : NSEnumerator
{
NSGArray *array;
unsigned pos;
}
- (id) initWithArray: (NSGArray*)anArray;
@end
@implementation NSGArrayEnumerator
- (id) initWithArray: (NSGArray*)anArray
{
[super init];
array = anArray;
RETAIN(array);
pos = 0;
return self;
}
- (id) nextObject
{
if (pos >= array->_count)
return nil;
return array->_contents_array[pos++];
}
- (void) dealloc
{
RELEASE(array);
[super dealloc];
}
@end
@interface NSGArrayEnumeratorReverse : NSGArrayEnumerator
@end
@implementation NSGArrayEnumeratorReverse
- (id) initWithArray: (NSGArray*)anArray
{
[super initWithArray: anArray];
pos = array->_count;
return self;
}
- (id) nextObject
{
if (pos == 0)
return nil;
return array->_contents_array[--pos];
}
@end