mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
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:
parent
faa7cd2785
commit
aeae4c5e6f
3 changed files with 501 additions and 226 deletions
|
@ -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
|
||||
|
|
545
Source/NSArray.m
545
Source/NSArray.m
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue