1 /* Copyright (c) 2006-2007 Christopher J. W. Lloyd <cjwl@objc.net>
3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8 #import <Foundation/NSArray.h>
9 #import <Foundation/NSString.h>
10 #import <Foundation/NSDictionary.h>
11 #import <Foundation/NSData.h>
12 #import <Foundation/NSRaise.h>
13 #import <Foundation/NSCoder.h>
14 #import <Foundation/NSArray_placeholder.h>
15 #import <Foundation/NSArray_concrete.h>
16 #import <Foundation/NSEnumerator_array.h>
17 #import <Foundation/NSEnumerator_arrayReverse.h>
18 #import <Foundation/NSAutoreleasePool-private.h>
19 #import <Foundation/NSPropertyListReader.h>
20 #import <Foundation/NSPropertyListWriter_vintage.h>
21 #import <Foundation/NSKeyedUnarchiver.h>
22 #import <Foundation/NSKeyedArchiver.h>
23 #import <Foundation/NSPredicate.h>
24 #import <Foundation/NSIndexSet.h>
25 #import <Foundation/NSURL.h>
26 #import <Foundation/NSRaiseException.h>
28 @interface NSKeyedArchiver (PrivateToContainers)
29 - (void)encodeArray:(NSArray *)array forKey:(NSString *)key;
33 @implementation NSArray
35 +allocWithZone:(NSZone *)zone {
36 if(self==objc_lookUpClass("NSArray"))
37 return NSAllocateObject([NSArray_placeholder class],0,NULL);
39 return NSAllocateObject(self,0,zone);
42 -initWithArray:(NSArray *)array {
43 NSUInteger count=[array count];
44 id *objects=__builtin_alloca(sizeof(id)*count);
46 [array getObjects:objects];
48 return [self initWithObjects:objects count:count];
51 -initWithArray:(NSArray *)array copyItems:(BOOL)copyItems {
52 if (copyItems == NO) {
53 return [self initWithArray:array];
56 const NSUInteger count=[array count];
57 id *oldObjects = __builtin_alloca(sizeof(id)*count);
58 id *newObjects = __builtin_alloca(sizeof(id)*count);
60 [array getObjects:oldObjects];
63 for (i = 0; i < count; i++) {
64 newObjects[i] = [oldObjects[i] copyWithZone:NULL];
67 self = [self initWithObjects:newObjects count:count];
69 for (i = 0; i < count; i++) {
70 [newObjects[i] release];
75 -initWithContentsOfFile:(NSString *)path {
76 id contents = [NSPropertyListReader arrayWithContentsOfFile: path];
83 return [self initWithArray: contents];
86 -initWithContentsOfURL:(NSURL *)url {
91 return [self initWithContentsOfFile:[url path]];
94 -initWithObjects:(id *)objects count:(NSUInteger)count {
95 NSInvalidAbstractInvocation();
100 -initWithObjects:object,... {
105 va_start(arguments,object);
107 while(va_arg(arguments,id)!=nil)
111 objects=__builtin_alloca(sizeof(id)*count);
113 va_start(arguments,object);
116 objects[i]=va_arg(arguments,id);
119 return [self initWithObjects:objects count:count];
122 -copyWithZone:(NSZone *)zone {
123 return [self retain];
127 -mutableCopyWithZone:(NSZone *)zone {
128 return [[NSMutableArray allocWithZone:zone] initWithArray:self];
132 -(Class)classForCoder {
133 return objc_lookUpClass("NSArray");
136 -initWithCoder:(NSCoder *)coder {
137 if([coder allowsKeyedCoding]){
138 NSKeyedUnarchiver *keyed=(NSKeyedUnarchiver *)coder;
139 NSArray *array=[keyed decodeObjectForKey:@"NS.objects"];
141 return [self initWithArray:array];
147 [coder decodeValueOfObjCType:@encode(int) at:&count];
149 objects=__builtin_alloca(count*sizeof(id));
152 objects[i]=[coder decodeObject];
154 return [self initWithObjects:objects count:count];
159 -(void)encodeWithCoder:(NSCoder *)coder {
160 if([coder isKindOfClass:[NSKeyedArchiver class]]){
161 NSKeyedArchiver *keyed=(NSKeyedArchiver *)coder;
163 [keyed encodeArray:self forKey:@"NS.objects"];
166 int i,count=[self count];
168 [coder encodeValueOfObjCType:@encode(int) at:&count];
170 [coder encodeObject:[self objectAtIndex:i]];
175 return [[[self allocWithZone:NULL] init] autorelease];
179 +arrayWithContentsOfFile:(NSString *)path {
180 return [[[self allocWithZone:NULL] initWithContentsOfFile:path] autorelease];
183 +arrayWithContentsOfURL:(NSURL *)url {
184 return [[[self allocWithZone:NULL] initWithContentsOfURL:url] autorelease];
187 +arrayWithObject:object {
188 return [[[self allocWithZone:NULL]
189 initWithObjects:&object count:1] autorelease];
193 +arrayWithObjects:object,... {
194 NSUInteger i,count=0;
200 va_start(arguments,object);
201 count=1; // include object
202 while(va_arg(arguments,id)!=nil)
206 objects=__builtin_alloca(sizeof(id)*count);
208 va_start(arguments,object);
211 objects[i]=va_arg(arguments,id);
215 return [[[self allocWithZone:NULL] initWithObjects:objects count:count] autorelease];
219 +arrayWithArray:(NSArray *)array {
220 return [[[self allocWithZone:NULL] initWithArray:array] autorelease];
224 +arrayWithObjects:(id *)objects count:(NSUInteger)count {
225 return [[[self allocWithZone:NULL] initWithObjects:objects count:count] autorelease];
230 NSInvalidAbstractInvocation();
235 -objectAtIndex:(NSUInteger)index {
236 NSInvalidAbstractInvocation();
240 -(void)getObjects:(id *)objects {
241 NSUInteger i,count=[self count];
244 objects[i]=[self objectAtIndex:i];
248 -(void)getObjects:(id *)objects range:(NSRange)range {
249 NSUInteger i,count=[self count],loc=range.location;
251 if(NSMaxRange(range)>count)
252 NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",
253 NSStringFromRange(range),[self count]);
255 for(i=0;i<range.length;i++)
256 objects[i]=[self objectAtIndex:loc+i];
259 -(NSArray *)subarrayWithRange:(NSRange)range {
260 if(NSMaxRange(range)>[self count])
261 NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",
262 NSStringFromRange(range),[self count]);
264 return NSAutorelease(NSArray_concreteWithArrayRange(self,range));
271 -(BOOL)isEqual:array {
275 if(![array isKindOfClass:objc_lookUpClass("NSArray")])
278 return [self isEqualToArray:array];
282 -(BOOL)isEqualToArray:(NSArray *)array {
289 if(count!=[array count])
293 if(![[self objectAtIndex:i] isEqual:[array objectAtIndex:i]])
299 -(NSUInteger)indexOfObject:object {
300 NSInteger i,count=[self count];
303 if([[self objectAtIndex:i] isEqual:object])
310 -(NSUInteger)indexOfObject:object inRange:(NSRange)range {
311 NSInteger i,count=[self count],loc=range.location;
313 if(NSMaxRange(range)>count)
314 NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",NSStringFromRange(range),[self count]);
316 for(i=0;i<range.length;i++)
317 if([[self objectAtIndex:loc+i] isEqual:object])
324 -(NSUInteger)indexOfObjectIdenticalTo:object {
325 NSInteger i,count=[self count];
328 if([self objectAtIndex:i]==object)
335 -(NSUInteger)indexOfObjectIdenticalTo:object inRange:(NSRange)range {
336 NSInteger i,count=[self count],loc=range.location;
338 if(NSMaxRange(range)>count)
339 NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",NSStringFromRange(range),[self count]);
341 for(i=0;i<range.length;i++)
342 if([self objectAtIndex:loc+i]==object)
348 -(NSEnumerator *)objectEnumerator {
349 return NSAutorelease(NSEnumerator_arrayNew(self));
353 -(NSEnumerator *)reverseObjectEnumerator {
354 return NSAutorelease(NSEnumerator_arrayReverseNew(self));
358 -(NSArray *)arrayByAddingObject:object {
359 return NSAutorelease(NSArray_concreteWithArrayAndObject(self,object));
363 -(NSArray *)arrayByAddingObjectsFromArray:(NSArray *)array {
364 return NSAutorelease(NSArray_concreteWithArrayAndArray(self,array));
367 -(NSString *)componentsJoinedByString:(NSString *)separator {
368 NSMutableString *string=[NSMutableString stringWithCapacity:256];
369 NSInteger i,count=[self count];
371 for(i=0;i<count;i++){
372 [string appendString:[[self objectAtIndex:i] description]];
374 [string appendString:separator];
380 -(BOOL)containsObject:object {
381 return ([self indexOfObject:object]!=NSNotFound)?YES:NO;
385 -firstObjectCommonWithArray:(NSArray *)array {
387 NSInteger i,count=[self count];
389 for(i=0;i<count;i++){
390 id object=[self objectAtIndex:i];
392 if([array indexOfObject:object]!=NSNotFound)
400 NSInteger count=[self count];
405 return [self objectAtIndex:count-1];
409 NSInteger count=[self count];
414 return [self objectAtIndex:0];
417 -(NSArray *)sortedArrayUsingSelector:(SEL)selector {
418 NSMutableArray *array=[NSMutableArray arrayWithArray:self];
420 [array sortUsingSelector:selector];
425 -(NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))function
426 context:(void *)context {
427 NSMutableArray *array=[NSMutableArray arrayWithArray:self];
429 [array sortUsingFunction:function context:context];
434 -(BOOL)writeToFile:(NSString *)path atomically:(BOOL)atomically {
435 return [NSPropertyListWriter_vintage writePropertyList:self toFile:path atomically:atomically];
438 -(BOOL)writeToURL:(NSURL *)aURL atomically:(BOOL)atomically {
439 if ([aURL isFileURL]) {
440 return [self writeToFile:[aURL path] atomically:atomically];
448 -(void)makeObjectsPerformSelector:(SEL)selector {
449 NSInteger i, count = [self count];
451 for (i = 0; i < count; i++)
452 [[self objectAtIndex:i] performSelector:selector];
456 -(void)makeObjectsPerformSelector:(SEL)selector withObject:object {
457 NSInteger i, count = [self count];
459 for (i = 0; i < count; i++)
460 [[self objectAtIndex:i] performSelector:selector withObject:object];
463 -(NSString *)description {
464 return [NSPropertyListWriter_vintage stringWithPropertyList:self];
467 -(NSString *)descriptionWithLocale:(NSDictionary *)locale {
468 NSUnimplementedMethod();
472 -(NSString *)descriptionWithLocale:(NSDictionary *)locale indent:(NSUInteger)indent {
473 NSUnimplementedMethod();
477 -(NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate {
478 NSInteger i,count=[self count];
479 NSMutableArray *result=[NSMutableArray arrayWithCapacity:count];
481 for(i=0;i<count;i++){
482 id check=[self objectAtIndex:i];
484 if([predicate evaluateWithObject:check])
485 [result addObject:check];
491 -(NSArray *)sortedArrayUsingDescriptors:(NSArray *)descriptors {
492 NSMutableArray *result=[NSMutableArray arrayWithArray:self];
494 [result sortUsingDescriptors:descriptors];
501 -(NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
502 NSUInteger i,count=[indexes count];
503 NSUInteger buffer[count];
506 count=[indexes getIndexes:buffer maxCount:count inIndexRange:NULL];
507 // getObjects:range: would make more sense
509 objects[i]=[self objectAtIndex:buffer[i]];
511 return [NSArray arrayWithObjects:objects count:count];
515 -(NSArray *)objectsAtIndexes:(NSIndexSet*)indexes
517 NSUInteger idx=[indexes firstIndex];
518 id ret=[NSMutableArray array];
519 while(idx!=NSNotFound)
521 [ret addObject:[self objectAtIndex:idx]];
522 idx=[indexes indexGreaterThanIndex:idx];
527 -(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)length;
529 NSInteger numObjects=MIN([self count] - state->extra[0], length);
530 NSInteger i=state->extra[0];
532 state->itemsPtr=stackbuf;
534 for(j=0; j<numObjects; j++, i++)
536 state->itemsPtr[j]=[self objectAtIndex:i];
539 state->extra[0]+=numObjects;
541 state->mutationsPtr=(unsigned long *)self;
548 void objc_enumerationMutation(id collection)
550 [NSException raise:NSInternalInconsistencyException format:@"Collection %p of class %@ was mutated during enumeration. Break on objc_enumerationMutation to debug.", collection, [collection className]];
553 #import <Foundation/NSCFTypeID.h>
555 @implementation NSArray (CFTypeID)
557 - (unsigned) _cfTypeID
559 return kNSCFTypeArray;