/src/NSArray.m
https://github.com/jsyedidia/nufound · Objective C · 1190 lines · 890 code · 204 blank · 96 comment · 141 complexity · ef6a61ad0f9749b083f8dc56e6b0b050 MD5 · raw file
- /*
- NSArray.m
- Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
- All rights reserved.
- Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
- This file is part of libFoundation.
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted, provided
- that the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- We disclaim all warranties with regard to this software, including all
- implied warranties of merchantability and fitness, in no event shall
- we be liable for any special, indirect or consequential damages or any
- damages whatsoever resulting from loss of use, data or profits, whether in
- an action of contract, negligence or other tortious action, arising out of
- or in connection with the use or performance of this software.
- */
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <Foundation/common.h>
- #include <Foundation/NSObject.h>
- #include <Foundation/NSArray.h>
- #include <Foundation/NSRange.h>
- #include <Foundation/NSString.h>
- #include <Foundation/NSAutoreleasePool.h>
- #include <Foundation/NSException.h>
- #include <Foundation/NSCoder.h>
- #include <Foundation/PropertyListParser.h>
- #include <Foundation/NSUtilities.h>
- #include <Foundation/NSURL.h>
- #include <Foundation/exceptions/GeneralExceptions.h>
- #include "NSConcreteArray.h"
- #include "NSObject+PropLists.h"
- /*
- * NSArray Implementation
- *
- * primary methods are
- * init
- * initWithObjects:count:
- * dealloc
- * count
- * objectAtIndex:
- */
- @implementation NSArray
- static Class NSArrayClass = Nil;
- static Class NSMutableArrayClass = Nil;
- static Class NSConcreteArrayClass = Nil;
- /* Allocating and Initializing an Array */
- + (id)allocWithZone:(NSZone*)zone
- {
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
- if (NSConcreteArrayClass == Nil)
- NSConcreteArrayClass = [NSConcreteArray class];
-
- return NSAllocateObject( (self == NSArrayClass) ?
- NSConcreteArrayClass : (Class)self, 0, zone);
- }
- + (id)array
- {
- return AUTORELEASE([[self alloc] init]);
- }
- + (id)arrayWithObject:(id)anObject
- {
- return AUTORELEASE([[self alloc] initWithObjects:&anObject count:1]);
- }
- + (id)arrayWithObjects:(id)firstObj,...
- {
- id array, obj, *objects;
- va_list list;
- unsigned int count;
- va_start(list, firstObj);
- for (count=0, obj = firstObj; obj; obj = va_arg(list,id))
- count++;
- va_end(list);
- objects = Malloc(sizeof(id) * count);
- {
- va_start(list, firstObj);
- for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
- objects[count++] = obj;
- va_end(list);
- array = [[self alloc] initWithObjects:objects count:count];
- }
- lfFree(objects);
- return AUTORELEASE(array);
- }
- + (id)arrayWithArray:(NSArray*)anotherArray
- {
- return AUTORELEASE([[self alloc] initWithArray:anotherArray]);
- }
- + (id)arrayWithContentsOfFile:(NSString *)fileName
- {
- volatile id plist = nil;
- NSString *format = @"%@: Caught exception %@ with reason %@ ";
-
- NS_DURING {
- plist = NSParsePropertyListFromFile(fileName);
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
- if (![plist isKindOfClass:NSArrayClass])
- plist = nil;
- }
- NS_HANDLER {
- NSLog(format, self, [localException name], [localException reason]);
- plist = nil;
- }
- NS_ENDHANDLER;
-
- return plist;
- }
- + (id)arrayWithContentsOfURL:(NSURL *)_url
- {
- id plist;
-
- if ([_url isFileURL])
- return [self arrayWithContentsOfFile:[_url path]];
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- plist = [[NSString stringWithContentsOfURL:_url] propertyList];
- if (![plist isKindOfClass:NSArrayClass])
- return nil;
- return plist;
- }
- + (id)arrayWithObjects:(id*)objects count:(unsigned int)count
- {
- return AUTORELEASE([[self alloc]
- initWithObjects:objects count:count]);
- }
- - (NSArray*)arrayByAddingObject:(id)anObject
- {
- int i, count = [self count];
- id array;
- id *objects;
- objects = Malloc(sizeof(id) * (count + 1));
- {
- for (i = 0; i < count; i++)
- objects[i] = [self objectAtIndex:i];
- objects[i] = anObject;
-
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- array = AUTORELEASE([[NSArrayClass alloc]
- initWithObjects:objects count:count+1]);
- }
- lfFree(objects);
- return array;
- }
- - (NSArray*)arrayByAddingObjectsFromArray:(NSArray*)anotherArray;
- {
- unsigned int i, count = [self count], another = [anotherArray count];
- id array;
- id *objects;
- objects = Malloc(sizeof(id) * (count+another));
- {
- for (i = 0; i < count; i++)
- objects[i] = [self objectAtIndex:i];
- for (i = 0; i < another; i++)
- objects[i + count] = [anotherArray objectAtIndex:i];
-
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- array = AUTORELEASE([[NSArrayClass alloc]
- initWithObjects:objects count:count + another]);
- }
- lfFree(objects);
- return array;
- }
- - (id)initWithArray:(NSArray*)anotherArray
- {
- return [self initWithArray:anotherArray copyItems:NO];
- }
- - (id)initWithArray:(NSArray*)anotherArray copyItems:(BOOL)flag;
- {
- unsigned int i, count = [anotherArray count];
- id *objects;
- if (count == 0)
- return [self initWithObjects:NULL count:0];
- objects = Malloc(sizeof(id) * count);
- {
- for (i = 0; i < count; i++) {
- objects[i] = flag
- ? [anotherArray objectAtIndex:i]
- : AUTORELEASE([[anotherArray objectAtIndex:i] copyWithZone:NULL]);
- }
- self = [self initWithObjects:objects count:count];
- }
- lfFree(objects);
- return self;
- }
- - (id)initWithObjects:(id)firstObj,...
- {
- id obj, *objects;
- va_list list;
- unsigned int count;
- va_start(list, firstObj);
- for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
- count++;
- va_end(list);
- objects = Malloc(sizeof(id) * count);
- {
- va_start(list, firstObj);
- for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
- objects[count++] = obj;
- va_end(list);
- self = [self initWithObjects:objects count:count];
- }
- lfFree(objects);
- return self;
- }
- - (id)initWithObjects:(id*)objects count:(unsigned int)count
- {
- [self subclassResponsibility:_cmd];
- return self;
- }
- - (id)initWithContentsOfFile:(NSString*)fileName
- {
- NSArray *plist;
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- if ((plist = [NSArrayClass arrayWithContentsOfFile:fileName])) {
- return [self initWithArray:plist];
- }
- else {
- self = AUTORELEASE(self);
- return nil;
- }
- }
- - (id)initWithContentsOfURL:(NSURL *)_url
- {
- NSArray *plist;
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- if ((plist = [NSArrayClass arrayWithContentsOfURL:_url])) {
- return [self initWithArray:plist];
- }
- else {
- self = AUTORELEASE(self);
- return nil;
- }
- }
- /* Querying the Array */
- - (BOOL)containsObject:(id)anObject
- {
- return ([self indexOfObject:anObject] == NSNotFound) ? NO : YES;
- }
- - (unsigned int)count
- {
- [self subclassResponsibility:_cmd];
- return 0;
- }
- - (unsigned int)indexOfObject:(id)anObject
- {
- return [self indexOfObject:anObject
- inRange:NSMakeRange(0, [self count])];
- }
- - (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
- {
- return [self indexOfObjectIdenticalTo:anObject
- inRange:NSMakeRange(0, [self count])];
- }
- - (unsigned int)indexOfObject:(id)anObject inRange:(NSRange)aRange
- {
- unsigned int index;
- for (index = 0; index < aRange.length; index++)
- if ([anObject isEqual:[self objectAtIndex:aRange.location+index]])
- return aRange.location+index;
- return NSNotFound;
- }
- - (unsigned int)indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange
- {
- unsigned int index;
- for (index = 0; index < aRange.length; index++)
- if (anObject == [self objectAtIndex:aRange.location+index])
- return index;
- return NSNotFound;
- }
- - (id)lastObject
- {
- int count = [self count];
- return count ? [self objectAtIndex:count - 1] : nil;
- }
- - (id)objectAtIndex:(unsigned int)index
- {
- [self subclassResponsibility:_cmd];
- return self;
- }
- - (void)getObjects:(id *)buffer
- {
- unsigned i, count = [self count];
-
- for (i = 0; i < count; i++) {
- buffer[i] = [self objectAtIndex: i];
- }
- }
- - (void)getObjects:(id *)buffer range:(NSRange)range
- {
- /* naive implementation, to be fixed ... */
- return [[self subarrayWithRange:range] getObjects:buffer];
- }
- - (NSEnumerator *)objectEnumerator
- {
- return AUTORELEASE([[_NSArrayEnumerator alloc]
- initWithArray:self reverse:NO]);
- }
- - (NSEnumerator *)reverseObjectEnumerator
- {
- return AUTORELEASE([[_NSArrayEnumerator alloc]
- initWithArray:self reverse:YES]);
- }
- /* Sending Messages to Elements */
- - (void)makeObjectsPerformSelector:(SEL)aSelector
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++)
- [[self objectAtIndex:index] performSelector:aSelector];
- }
- - (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++)
- [[self objectAtIndex:index]
- performSelector:aSelector withObject:anObject];
- }
- /* Obsolete methods */
- - (void)makeObjectsPerform:(SEL)aSelector
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++)
- [[self objectAtIndex:index] performSelector:aSelector];
- }
- - (void)makeObjectsPerform:(SEL)aSelector withObject:(id)anObject
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++)
- [[self objectAtIndex:index]
- performSelector:aSelector withObject:anObject];
- }
- /* Comparing Arrays */
- - (id)firstObjectCommonWithArray:(NSArray*)otherArray
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++) {
- id object = [self objectAtIndex:index];
- if ([otherArray containsObject:object])
- return object;
- }
- return nil;
- }
- - (BOOL)isEqualToArray:(NSArray*)otherArray
- {
- unsigned int index, count;
- if( otherArray == self )
- return YES;
- if ([otherArray count] != (count = [self count]))
- return NO;
- for (index = 0; index < count; index++) {
- register id o1, o2;
- o1 = [self objectAtIndex:index];
- o2 = [otherArray objectAtIndex:index];
- if (![o1 isEqual:o2])
- return NO;
- }
- return YES;
- }
- /* Deriving New Arrays */
- - (NSArray *)sortedArrayUsingFunction:
- (int(*)(id element1, id element2, void *userData))comparator
- context:(void *)context
- {
- NSMutableArray *sortedArray;
- NSArray *result;
-
- sortedArray = [self mutableCopy];
- [sortedArray sortUsingFunction:comparator context:context];
- result = [sortedArray copy];
- RELEASE(sortedArray);
- return AUTORELEASE(result);
- }
- static int compare(id elem1, id elem2, void* comparator)
- {
- return (int)(long)[elem1 performSelector:comparator withObject:elem2];
- }
- - (NSArray*)sortedArrayUsingSelector:(SEL)comparator
- // Returns an array listing the receiver's elements in ascending order,
- // as determined by the comparison method specified by the selector
- // comparator.
- {
- return [self sortedArrayUsingFunction:compare context:(void*)comparator];
- }
- - (NSArray*)subarrayWithRange:(NSRange)range
- {
- id array;
- unsigned int index;
- id *objects;
- objects = Malloc(sizeof(id) * range.length);
- {
- for (index = 0; index < range.length; index++)
- objects[index] = [self objectAtIndex:range.location+index];
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- array = AUTORELEASE([[NSArrayClass alloc]
- initWithObjects:objects count:range.length]);
- }
- lfFree(objects);
- return array;
- }
- // Returns an array containing the receiver's elements
- // that fall within the limits specified by range.
- /* Joining String Elements */
- - (NSString*)componentsJoinedByString:(NSString*)separator
- {
- unsigned int index, count = [self count];
- if (!separator)
- separator = @"";
- if (count > 0) {
- NSMutableString* string = [NSMutableString new];
- id elem;
- SEL sel;
- IMP imp;
- CREATE_AUTORELEASE_POOL(pool);
- elem = [self objectAtIndex:0];
- sel = @selector(appendString:);
- imp = [string methodForSelector:sel];
- if (![elem isKindOfClass:[NSString class]])
- elem = [elem description];
- (*imp)(string, sel, elem);
- for (index = 1; index < count; index++) {
- elem = [self objectAtIndex:index];
- if (![elem isKindOfClass:[NSString class]])
- elem = [elem description];
- (*imp)(string, sel, separator);
- (*imp)(string, sel, elem);
- }
- RELEASE(pool);
- return AUTORELEASE(string);
- }
- return @"";
- }
- /* Creating a String Description of the Array */
- - (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
- indent:(unsigned int)_indent
- {
- return [self descriptionWithLocale:_locale indent:_indent];
- }
- - (NSString*)descriptionWithLocale:(NSDictionary*)locale
- indent:(unsigned int)indent;
- {
- NSMutableString* description = [NSMutableString stringWithCString:"(\n"];
- unsigned int indent1 = indent + 4;
- NSMutableString* indentation
- = [NSString stringWithFormat:
- [NSString stringWithFormat:@"%%%dc", indent1], ' '];
- unsigned int count = [self count];
- SEL sel = @selector(appendString:);
- IMP imp = [description methodForSelector:sel];
- if(count) {
- id object;
- id stringRepresentation;
- unsigned int index;
- CREATE_AUTORELEASE_POOL(pool);
- object = [self objectAtIndex:0];
- stringRepresentation = [object propertyListStringWithLocale:locale
- indent:indent1];
- (*imp)(description, sel, indentation);
- (*imp)(description, sel, stringRepresentation);
- for (index = 1; index < count; index++) {
- object = [self objectAtIndex:index];
- stringRepresentation = [object propertyListStringWithLocale:locale
- indent:indent1];
-
- (*imp)(description, sel, @",\n");
- (*imp)(description, sel, indentation);
- (*imp)(description, sel, stringRepresentation);
- }
- RELEASE(pool);
- }
- (*imp)(description, sel, indent
- ? [NSMutableString stringWithFormat:
- [NSString stringWithFormat:@"\n%%%dc)", indent], ' ']
- : [NSMutableString stringWithCString:"\n)"]);
- return description;
- }
- - (NSString*)descriptionWithLocale:(NSDictionary*)locale
- {
- return [self descriptionWithLocale:locale indent:0];
- }
- - (NSString*)description
- {
- return [self descriptionWithLocale:nil indent:0];
- }
- - (NSString*)stringRepresentation
- {
- return [self descriptionWithLocale:nil indent:0];
- }
- /* Write plist to file */
- - (BOOL)writeToFile:(NSString*)fileName atomically:(BOOL)flag
- {
- volatile BOOL success = NO;
-
- TRY {
- id content = [self description];
- success = [content writeToFile:fileName atomically:flag];
- } END_TRY
- OTHERWISE {
- success = NO;
- } END_CATCH
-
- return success;
- }
- /* From adopted/inherited protocols */
- - (unsigned)hash
- {
- return [self count];
- }
- - (BOOL)isEqual:(id)anObject
- {
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- if (![anObject isKindOfClass:NSArrayClass])
- return NO;
- return [self isEqualToArray:anObject];
- }
- /* Copying */
- - (id)copyWithZone:(NSZone *)zone
- {
- if (NSShouldRetainWithZone(self, zone))
- return RETAIN(self);
- else {
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
-
- return [[NSArrayClass allocWithZone:zone]
- initWithArray:self copyItems:NO];
- }
- }
- - (id)mutableCopyWithZone:(NSZone*)zone
- {
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
- return [[NSMutableArrayClass alloc] initWithArray:self];
- }
- /* Encoding */
- - (Class)classForCoder
- {
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
- return NSArrayClass;
- }
- - (void)encodeWithCoder:(NSCoder*)aCoder
- {
- IMP imp = [aCoder methodForSelector:@selector(encodeObject:)];
- int i, count = [self count];
- [aCoder encodeValueOfObjCType:@encode(int) at:&count];
- for(i = 0; i < count; i++)
- (*imp)(aCoder, @selector(encodeObject:), [self objectAtIndex:i]);
- }
- - (id)initWithCoder:(NSCoder*)aDecoder
- {
- IMP imp = [aDecoder methodForSelector:@selector(decodeObject)];
- int i, count;
- [aDecoder decodeValueOfObjCType:@encode(int) at:&count];
- if (count > 0) {
- id* objects;
- objects = Malloc(sizeof(id) * count);
- {
- for(i = 0; i < count; i++)
- objects[i] = (*imp)(aDecoder, @selector(decodeObject));
- self = [self initWithObjects:objects count:count];
- }
- lfFree(objects);
- }
- else {
- self = [self init]; // empty array
- }
- return self;
- }
- @end /* NSArray */
- /*
- * Extensions to NSArray
- */
- @implementation NSArray (NSArrayExtensions)
- /* Sending Messages to Elements */
- - (void)makeObjectsPerform:(SEL)aSelector
- withObject:(id)anObject1 withObject:(id)anObject2
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++)
- [[self objectAtIndex:index]
- performSelector:aSelector withObject:anObject1 withObject:anObject2];
- }
- /* Deriving New Arrays */
- - (NSArray *)map:(SEL)aSelector
- {
- unsigned int index, count = [self count];
- id array;
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
- array = [NSMutableArrayClass arrayWithCapacity:count];
-
- for (index = 0; index < count; index++) {
- [array insertObject:[[self objectAtIndex:index]
- performSelector:aSelector]
- atIndex:index];
- }
- return array;
- }
- - (NSArray *)map:(SEL)aSelector with:(id)anObject
- {
- unsigned int index, count = [self count];
- id array;
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
- array = [NSMutableArrayClass arrayWithCapacity:count];
- for (index = 0; index < count; index++) {
- [array insertObject:[[self objectAtIndex:index]
- performSelector:aSelector withObject:anObject]
- atIndex:index];
- }
- return array;
- }
- - (NSArray *)map:(SEL)aSelector with:(id)anObject with:(id)otherObject;
- {
- unsigned int index, count = [self count];
- id array;
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
- array = [NSMutableArrayClass arrayWithCapacity:count];
- for (index = 0; index < count; index++) {
- [array insertObject:[[self objectAtIndex:index]
- performSelector:aSelector withObject:anObject withObject:otherObject]
- atIndex:index];
- }
- return array;
- }
- - (NSArray *)arrayWithObjectsThat:(BOOL(*)(id anObject))comparator;
- // Returns an array listing the receiver's elements for that comparator
- // function returns YES
- {
- unsigned i, m, n = [self count];
- id *objects;
- id array;
- objects = Malloc(sizeof(id) * n);
- {
- for (i = m = 0; i < n; i++) {
- id obj = [self objectAtIndex:i];
- if (comparator(obj))
- objects[m++] = obj;
- }
-
- array = AUTORELEASE([[[self class] alloc] initWithObjects:objects count:m]);
- }
- lfFree(objects);
- return array;
- }
- - (NSArray *)map:(id(*)(id anObject))function
- objectsThat:(BOOL(*)(id anObject))comparator;
- // Returns an array listing the objects returned by function applied to
- // objects for that comparator returns YES
- {
- unsigned i, m, n = [self count];
- id *objects;
- id array;
- objects = Malloc(sizeof(id) * n);
- {
- for (i = m = 0; i < n; i++) {
- id obj = [self objectAtIndex:i];
- if (comparator(obj))
- objects[m++] = function(obj);
- }
-
- array = AUTORELEASE([[[self class] alloc] initWithObjects:objects count:m]);
- }
- lfFree(objects);
- return array;
- }
- @end
- /*
- * NSMutableArray class
- *
- * primary methods are
- * init
- * initWithCapacity:
- * initWithObjects:count:
- * dealloc
- * count
- * objectAtIndex:
- * addObject:
- * replaceObjectAtIndex:withObject:
- * insertObject:atIndex:
- * removeObjectAtIndex:
- */
- @implementation NSMutableArray
- + (id)arrayWithContentsOfFile:(NSString *)fileName
- {
- id array;
-
- if ((array = [super arrayWithContentsOfFile:fileName])) {
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
-
- if (![array isKindOfClass:NSMutableArrayClass]) {
- array = [[NSMutableArrayClass alloc] initWithArray:array];
- array = AUTORELEASE(array);
- }
- }
- return array;
- }
- /* Creating and Initializing an NSMutableArray */
- + (id)allocWithZone:(NSZone*)zone
- {
- static Class NSConcreteMutableArrayClass = Nil;
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
- if (NSConcreteMutableArrayClass == Nil)
- NSConcreteMutableArrayClass = [NSConcreteMutableArray class];
-
- return NSAllocateObject( (self == NSMutableArrayClass) ?
- NSConcreteMutableArrayClass : (Class)self,
- 0, zone);
- }
- + (id)arrayWithCapacity:(unsigned int)aNumItems
- {
- return AUTORELEASE([[self alloc] initWithCapacity:aNumItems]);
- }
- - (id)init
- {
- return [self initWithCapacity:0];
- }
- - (id)initWithCapacity:(unsigned int)aNumItems
- {
- [self subclassResponsibility:_cmd];
- return self;
- }
- - (id)copyWithZone:(NSZone*)zone
- {
- if (NSArrayClass == Nil)
- NSArrayClass = [NSArray class];
- return [[NSArrayClass alloc] initWithArray:self copyItems:YES];
- }
- /* Adding Objects */
- - (void)addObject:(id)anObject
- {
- [self insertObject:anObject atIndex:[self count]];
- }
- - (void)addObjectsFromArray:(NSArray*)anotherArray
- {
- unsigned int i, j, n;
- n = [anotherArray count];
- for (i = 0, j = [self count]; i < n; i++)
- [self insertObject:[anotherArray objectAtIndex:i] atIndex:j++];
- }
- - (void)insertObject:(id)anObject atIndex:(unsigned int)index
- {
- [self subclassResponsibility:_cmd];
- }
- /* Removing Objects */
- - (void)removeAllObjects
- {
- int count = [self count];
- while (--count >= 0)
- [self removeObjectAtIndex:count];
- }
- - (void)removeLastObject
- {
- [self removeObjectAtIndex:[self count]-1];
- }
- - (void)removeObject:(id)anObject
- {
- unsigned int i, n;
- n = [self count];
- for (i = 0; i < n; i++) {
- id obj = [self objectAtIndex:i];
- if ([obj isEqual:anObject]) {
- [self removeObjectAtIndex:i];
- n--; i--;
- }
- }
- }
- - (void)removeObjectAtIndex:(unsigned int)index
- {
- [self subclassResponsibility:_cmd];
- }
- - (void)removeObjectIdenticalTo:(id)anObject
- {
- unsigned int i, n;
- i = n = [self count];
- for (i = 0; i < n; i++) {
- id obj = [self objectAtIndex:i];
- if (obj == anObject) {
- [self removeObjectAtIndex:i];
- n--; i--;
- }
- }
- }
- static int __cmp_unsigned_ints(unsigned int* i1, unsigned int* i2)
- {
- return (*i1 == *i2) ? 0 : ((*i1 < *i2) ? -1 : +1);
- }
- - (void)removeObjectsFromIndices:(unsigned int*)indices
- numIndices:(unsigned int)count;
- {
- unsigned int *indexes;
- int i;
-
- if (!count)
- return;
-
- indexes = Malloc(count * sizeof(unsigned int));
- {
- memcpy(indexes, indices, count * sizeof(unsigned int));
- qsort(indexes, count, sizeof(unsigned int),
- (int(*)(const void *, const void*))__cmp_unsigned_ints);
-
- for (i = count - 1; i >= 0; i++)
- [self removeObjectAtIndex:indexes[i]];
- }
- lfFree(indexes);
- }
- - (void)removeObjectsInArray:(NSArray*)otherArray
- {
- unsigned int i, n = [otherArray count];
- for (i = 0; i < n; i++)
- [self removeObject:[otherArray objectAtIndex:i]];
- }
- - (void)removeObject:(id)anObject inRange:(NSRange)aRange
- {
- unsigned int index;
- for (index = aRange.location-1; index >= aRange.location; index--)
- if ([anObject isEqual:[self objectAtIndex:index+aRange.location]])
- [self removeObjectAtIndex:index+aRange.location];
- }
- - (void)removeObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange
- {
- unsigned int index;
- for (index = aRange.location-1; index >= aRange.location; index--)
- if (anObject == [self objectAtIndex:index+aRange.location])
- [self removeObjectAtIndex:index+aRange.location];
- }
- - (void)removeObjectsInRange:(NSRange)aRange
- {
- unsigned int index;
- for (index = aRange.location-1; index >= aRange.location; index--)
- [self removeObjectAtIndex:index+aRange.location];
- }
- /* Replacing Objects */
- - (void)replaceObjectAtIndex:(unsigned int)index withObject:(id)anObject
- {
- [self subclassResponsibility:_cmd];
- }
- - (void)replaceObjectsInRange:(NSRange)rRange
- withObjectsFromArray:(NSArray*)anArray
- {
- [self replaceObjectsInRange:rRange
- withObjectsFromArray:anArray
- range:NSMakeRange(0, [anArray count])];
- }
- - (void)replaceObjectsInRange:(NSRange)rRange
- withObjectsFromArray:(NSArray*)anArray range:(NSRange)aRange
- {
- unsigned int index;
- [self removeObjectsInRange:rRange];
- for (index = 0; index < aRange.length; index++)
- [self insertObject:[anArray objectAtIndex:aRange.location+index]
- atIndex:rRange.location+index];
- }
- - (void)setArray:(NSArray*)otherArray
- {
- [self removeAllObjects];
- [self addObjectsFromArray:otherArray];
- }
- - (void)sortUsingFunction:
- (int(*)(id element1, id element2, void *userData))comparator
- context:(void*)context
- {
- /* Shell sort algorithm taken from SortingInAction - a NeXT example */
- #define STRIDE_FACTOR 3 // good value for stride factor is not well-understood
- // 3 is a fairly good choice (Sedgewick)
- register int c,d, stride;
- BOOL found;
- int count;
- id (*objAtIdx)(id, SEL, unsigned int);
-
- if ((count = [self count]) < 2)
- return;
-
- objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
-
- stride = 1;
- 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;
- d = c - stride;
- while ((d >= 0) && !found) {
- // move to left until correct place
- register id a =
- objAtIdx(self, @selector(objectAtIndex:), d + stride);
- register id b =
- objAtIdx(self, @selector(objectAtIndex:), d);
-
- if ((*comparator)(a, b, context) == NSOrderedAscending) {
- #if !LIB_FOUNDATION_BOEHM_GC
- [a retain];
- [b retain];
- #endif
-
- [self replaceObjectAtIndex:(d + stride) withObject:b];
- [self replaceObjectAtIndex:d withObject:a];
- d -= stride; // jump by stride factor
-
- #if !LIB_FOUNDATION_BOEHM_GC
- [a release];
- [b release];
- #endif
- }
- else
- found = YES;
- }
- }
- }
- }
- static int selector_compare(id elem1, id elem2, void* comparator)
- {
- return (int)(long)[elem1 performSelector:(SEL)comparator withObject:elem2];
- }
- - (void)sortUsingSelector:(SEL)comparator
- {
- [self sortUsingFunction:selector_compare context:(void*)comparator];
- }
- /* Encoding */
- - (Class)classForCoder
- {
- if (NSMutableArrayClass == Nil)
- NSMutableArrayClass = [NSMutableArray class];
- return NSMutableArrayClass;
- }
- @end /* NSMutableArray */
- /*
- * Extensions to NSArray
- */
- @implementation NSMutableArray (NSMutableArrayExtensions)
- - (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count
- {
- if (count) {
- while (count--)
- [self removeObjectAtIndex:index+count];
- }
- }
- - (void)removeObjectsThat:(BOOL(*)(id anObject))comparator
- {
- unsigned int index, count = [self count];
- for (index = 0; index < count; index++)
- if (comparator([self objectAtIndex:index])) {
- [self removeObjectAtIndex:index];
- index--; count--;
- }
- }
- @end /* NSMutableArray(NSMutableArrayExtensions) */
- /*
- * NSArrayEnumerator class
- */
- @implementation _NSArrayEnumerator
- - (id)initWithArray:(NSArray*)anArray reverse:(BOOL)isReverse
- {
- unsigned count = [anArray count];
-
- self->reverse = isReverse;
- self->array = RETAIN(anArray);
- self->index = (reverse)
- ? (count ? count - 1 : NSNotFound)
- : (count ? 0 : NSNotFound);
- return self;
- }
- - (void)dealloc
- {
- RELEASE(self->array);
- [super dealloc];
- }
- - (id)nextObject
- {
- id object;
- NSAssert(array, @"Invalid Array enumerator");
- if (self->index == NSNotFound)
- return nil;
- object = [self->array objectAtIndex:index];
- if (self->reverse) {
- if (self->index == 0)
- self->index = NSNotFound;
- else
- self->index--;
- } else {
- self->index++;
- if (self->index >= [array count])
- self->index = NSNotFound;
- }
-
- return object;
- }
- @end /* _NSArrayEnumerator */
- /*
- Local Variables:
- c-basic-offset: 4
- tab-width: 8
- End:
- */