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 Frith-MacDonald 1999-09-14 19:24:58 +00:00
parent faa7cd2785
commit aeae4c5e6f
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>
* Source/NSTimer.m: minor optimisations

View file

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

View file

@ -1,5 +1,5 @@
/* 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>
Date: March 1995
@ -29,8 +29,14 @@
#include <Foundation/NSException.h>
#include <Foundation/NSPortCoder.h>
static SEL eqSel = @selector(isEqual:);
@class NSGArrayEnumerator;
@class NSGArrayEnumeratorReverse;
@interface NSGArray : NSArray
{
@public
id *_contents_array;
unsigned _count;
}
@ -38,6 +44,7 @@
@interface NSGMutableArray : NSMutableArray
{
@public
id *_contents_array;
unsigned _count;
unsigned _capacity;
@ -166,15 +173,14 @@
*/
if (_count > 1)
{
static SEL sel = @selector(isEqual:);
BOOL (*imp)(id,SEL,id);
unsigned i;
imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: sel];
imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: eqSel];
for (i = 0; i < _count; i++)
{
if ((*imp)(anObject, sel, _contents_array[i]))
if ((*imp)(anObject, eqSel, _contents_array[i]))
{
return i;
}
@ -413,6 +419,33 @@
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
{
id obj;
@ -433,6 +466,27 @@
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
{
id obj;
@ -467,29 +521,102 @@
while (stride <= count)
stride = stride * STRIDE_FACTOR + 1;
while(stride > (STRIDE_FACTOR - 1)) {
// loop to sort for each value of stride
stride = stride / STRIDE_FACTOR;
for (c = stride; c < count; c++) {
found = NO;
if (stride > c)
break;
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)
while (stride > (STRIDE_FACTOR - 1))
{
// loop to sort for each value of stride
stride = stride / STRIDE_FACTOR;
for (c = stride; c < count; c++)
{
found = NO;
if (stride > c)
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
@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