Merge pull request #9 from gunyarakun/fix-typo
[cocotron.git] / Foundation / NSArray / NSArray.m
blob1cf7813ce516d4621bf6bf90276d6e541fcb178d
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;
30 @end
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];
54    }
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];
62    NSUInteger i;
63    for (i = 0; i < count; i++) {
64       newObjects[i] = [oldObjects[i] copyWithZone:NULL];
65    }
66    
67    self = [self initWithObjects:newObjects count:count];
68    
69    for (i = 0; i < count; i++) {
70       [newObjects[i] release];
71    }
72    return self;
75 -initWithContentsOfFile:(NSString *)path {
76     id contents = [NSPropertyListReader arrayWithContentsOfFile: path]; 
78     if(contents==nil) { 
79         [self dealloc]; 
80         return nil; 
81     } 
83     return [self initWithArray: contents]; 
86 -initWithContentsOfURL:(NSURL *)url {
87    if(![url isFileURL]){
88     [self dealloc];
89     return nil;
90    }
91    return [self initWithContentsOfFile:[url path]];
94 -initWithObjects:(id *)objects count:(NSUInteger)count {
95    NSInvalidAbstractInvocation();
96    return nil;
100 -initWithObjects:object,... {
101    va_list  arguments;
102    NSUInteger i,count;
103    id      *objects;
105    va_start(arguments,object);
106    count=1;
107    while(va_arg(arguments,id)!=nil)
108     count++;
109    va_end(arguments);
111    objects=__builtin_alloca(sizeof(id)*count);
113    va_start(arguments,object);
114    objects[0]=object;
115    for(i=1;i<count;i++)
116     objects[i]=va_arg(arguments,id);
117    va_end(arguments);
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"];
140     
141     return [self initWithArray:array];
142    }
143    else {
144     unsigned i,count;
145     id      *objects;
147     [coder decodeValueOfObjCType:@encode(int) at:&count];
149     objects=__builtin_alloca(count*sizeof(id));
151     for(i=0;i<count;i++)
152      objects[i]=[coder decodeObject];
154     return [self initWithObjects:objects count:count];
155    }
159 -(void)encodeWithCoder:(NSCoder *)coder {
160   if([coder isKindOfClass:[NSKeyedArchiver class]]){
161     NSKeyedArchiver *keyed=(NSKeyedArchiver *)coder;
162     
163     [keyed encodeArray:self forKey:@"NS.objects"];
164   }
165   else {
166     int i,count=[self count];
168     [coder encodeValueOfObjCType:@encode(int) at:&count];
169     for(i=0;i<count;i++)
170      [coder encodeObject:[self objectAtIndex:i]];
171   }
174 +array {
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; 
195    id        *objects=NULL;
196    
197    if(object!=nil){
198     va_list  arguments;
200     va_start(arguments,object);
201     count=1; // include object
202     while(va_arg(arguments,id)!=nil)
203      count++;
204     va_end(arguments);
206     objects=__builtin_alloca(sizeof(id)*count);
208     va_start(arguments,object);
209     objects[0]=object;
210     for(i=1;i<count;i++)
211      objects[i]=va_arg(arguments,id);
212     va_end(arguments);
213    }
214    
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];
229 -(NSUInteger)count {
230    NSInvalidAbstractInvocation();
231    return 0;
235 -objectAtIndex:(NSUInteger)index {
236    NSInvalidAbstractInvocation();
237    return nil;
240 -(void)getObjects:(id *)objects {
241    NSUInteger i,count=[self count];
243    for(i=0;i<count;i++)
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));
267 -(NSUInteger)hash {
268    return [self count];
271 -(BOOL)isEqual:array {
272    if(self==array)
273     return YES;
275    if(![array isKindOfClass:objc_lookUpClass("NSArray")])
276     return NO;
278    return [self isEqualToArray:array];
282 -(BOOL)isEqualToArray:(NSArray *)array {
283    NSInteger i,count;
285    if(self==array)
286     return YES;
288    count=[self count];
289    if(count!=[array count])
290     return NO;
292    for(i=0;i<count;i++)
293     if(![[self objectAtIndex:i] isEqual:[array objectAtIndex:i]])
294      return NO;
296    return YES;
299 -(NSUInteger)indexOfObject:object {
300    NSInteger i,count=[self count];
302    for(i=0;i<count;i++)
303     if([[self objectAtIndex:i] isEqual:object])
304      return i;
306    return NSNotFound;
310 -(NSUInteger)indexOfObject:object inRange:(NSRange)range {
311         NSInteger i,count=[self count],loc=range.location;
312     
313     if(NSMaxRange(range)>count)
314         NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",NSStringFromRange(range),[self count]);
315     
316     for(i=0;i<range.length;i++)
317         if([[self objectAtIndex:loc+i] isEqual:object])
318             return loc+i;
319     
320     return NSNotFound;
324 -(NSUInteger)indexOfObjectIdenticalTo:object {
325    NSInteger i,count=[self count];
327    for(i=0;i<count;i++)
328     if([self objectAtIndex:i]==object)
329      return i;
331    return NSNotFound;
335 -(NSUInteger)indexOfObjectIdenticalTo:object inRange:(NSRange)range {
336     NSInteger i,count=[self count],loc=range.location;
337     
338     if(NSMaxRange(range)>count)
339         NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",NSStringFromRange(range),[self count]);
340     
341     for(i=0;i<range.length;i++)
342         if([self objectAtIndex:loc+i]==object)
343             return loc+i;
344     
345     return NSNotFound;
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]];
373     if(i+1<count)
374      [string appendString:separator];
375    }
376    return string;
380 -(BOOL)containsObject:object {
381    return ([self indexOfObject:object]!=NSNotFound)?YES:NO;
385 -firstObjectCommonWithArray:(NSArray *)array {
386    if ([array count]) { 
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)
393       return object;
394     }
395    }
396    return nil;
399 -lastObject {
400    NSInteger count=[self count];
402    if(count==0)
403     return nil;
405    return [self objectAtIndex:count-1];
408 -firstObject {
409     NSInteger count=[self count];
410     
411     if(count==0)
412         return nil;
413     
414     return [self objectAtIndex:0];
417 -(NSArray *)sortedArrayUsingSelector:(SEL)selector {
418    NSMutableArray *array=[NSMutableArray arrayWithArray:self];
420    [array sortUsingSelector:selector];
422    return array;
425 -(NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))function
426    context:(void *)context {
427    NSMutableArray *array=[NSMutableArray arrayWithArray:self];
429    [array sortUsingFunction:function context:context];
431    return array;
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];
441         }
442         else {
443                 return NO;
444         }
448 -(void)makeObjectsPerformSelector:(SEL)selector {
449         NSInteger i, count = [self count];
450         
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];
458         
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();
469    return nil;
472 -(NSString *)descriptionWithLocale:(NSDictionary *)locale indent:(NSUInteger)indent {
473    NSUnimplementedMethod();
474    return nil;
477 -(NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate {
478    NSInteger             i,count=[self count];
479    NSMutableArray *result=[NSMutableArray arrayWithCapacity:count];
480    
481    for(i=0;i<count;i++){
482     id check=[self objectAtIndex:i];
483     
484     if([predicate evaluateWithObject:check])
485      [result addObject:check];
486    }
487     
488    return result;
491 -(NSArray *)sortedArrayUsingDescriptors:(NSArray *)descriptors {
492    NSMutableArray *result=[NSMutableArray arrayWithArray:self];
493    
494    [result sortUsingDescriptors:descriptors];
495    
496    return result;
499 #if 0
500 // untested
501 -(NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
502    NSUInteger i,count=[indexes count];
503    NSUInteger buffer[count];
504    id       objects[count];
506    count=[indexes getIndexes:buffer maxCount:count inIndexRange:NULL];
507 //  getObjects:range: would make more sense
508    for(i=0;i<count;i++)
509     objects[i]=[self objectAtIndex:buffer[i]];
510    
511    return [NSArray arrayWithObjects:objects count:count];
513 #endif
515 -(NSArray *)objectsAtIndexes:(NSIndexSet*)indexes
517         NSUInteger idx=[indexes firstIndex];
518         id ret=[NSMutableArray array];
519         while(idx!=NSNotFound)
520         {
521                 [ret addObject:[self objectAtIndex:idx]];
522                 idx=[indexes indexGreaterThanIndex:idx];
523         }
524         return ret;
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];
531         NSInteger j=0;
532         state->itemsPtr=stackbuf;
534         for(j=0; j<numObjects; j++, i++)
535         {
536                 state->itemsPtr[j]=[self objectAtIndex:i];
537         }
539         state->extra[0]+=numObjects;
540         
541         state->mutationsPtr=(unsigned long *)self;
543         return numObjects;
546 @end
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;
562 @end