00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPObject.j"
00024 @import "CPRange.j"
00025 @import "CPEnumerator.j"
00026 @import "CPSortDescriptor.j"
00027 @import "CPException.j"
00028
00029
00030 @implementation _CPArrayEnumerator : CPEnumerator
00031 {
00032 CPArray _array;
00033 int _index;
00034 }
00035
00036 - (id)initWithArray:(CPArray)anArray
00037 {
00038 self = [super init];
00039
00040 if (self)
00041 {
00042 _array = anArray;
00043 _index = -1;
00044 }
00045
00046 return self;
00047 }
00048
00049 - (id)nextObject
00050 {
00051 if (++_index >= [_array count])
00052 return nil;
00053
00054 return [_array objectAtIndex:_index];
00055 }
00056
00057 @end
00058
00059
00060 @implementation _CPReverseArrayEnumerator : CPEnumerator
00061 {
00062 CPArray _array;
00063 int _index;
00064 }
00065
00066 - (id)initWithArray:(CPArray)anArray
00067 {
00068 self = [super init];
00069
00070 if (self)
00071 {
00072 _array = anArray;
00073 _index = [_array count];
00074 }
00075
00076 return self;
00077 }
00078
00079 - (id)nextObject
00080 {
00081 if (--_index < 0)
00082 return nil;
00083
00084 return [_array objectAtIndex:_index];
00085 }
00086
00087 @end
00088
00098 @implementation CPArray : CPObject
00099
00103 + (id)alloc
00104 {
00105 return [];
00106 }
00107
00111 + (id)array
00112 {
00113 return [[self alloc] init];
00114 }
00115
00121 + (id)arrayWithArray:(CPArray)anArray
00122 {
00123 return [[self alloc] initWithArray:anArray];
00124 }
00125
00131 + (id)arrayWithObject:(id)anObject
00132 {
00133 return [[self alloc] initWithObjects:anObject];
00134 }
00135
00141 + (id)arrayWithObjects:(id)anObject, ...
00142 {
00143 var i = 2,
00144 array = [[self alloc] init],
00145 argument;
00146
00147 for(; i < arguments.length && (argument = arguments[i]) != nil; ++i)
00148 array.push(argument);
00149
00150 return array;
00151 }
00152
00159 + (id)arrayWithObjects:(id)objects count:(unsigned)aCount
00160 {
00161 return [[self alloc] initWithObjects:objects count:aCount];
00162 }
00163
00168 - (id)init
00169 {
00170 return self;
00171 }
00172
00173
00179 - (id)initWithArray:(CPArray)anArray
00180 {
00181 self = [super init];
00182
00183 if (self)
00184 [self setArray:anArray];
00185
00186 return self;
00187 }
00188
00197 - (id)initWithArray:(CPArray)anArray copyItems:(BOOL)copyItems
00198 {
00199 if (!copyItems)
00200 return [self initWithArray:anArray];
00201
00202 self = [super init];
00203
00204 if (self)
00205 {
00206 var index = 0,
00207 count = [anArray count];
00208
00209 for(; index < count; ++i)
00210 {
00211 if (anArray[i].isa)
00212 self[i] = [anArray copy];
00213
00214 else
00215 self[i] = anArray;
00216 }
00217 }
00218
00219 return self;
00220 }
00221
00225 - (id)initWithObjects:(Array)anArray, ...
00226 {
00227
00228 var i = 2,
00229 argument;
00230
00231 for(; i < arguments.length && (argument = arguments[i]) != nil; ++i)
00232 push(argument);
00233
00234 return self;
00235 }
00236
00243 - (id)initWithObjects:(id)objects count:(unsigned)aCount
00244 {
00245 self = [super init];
00246
00247 if (self)
00248 {
00249 var index = 0;
00250
00251 for(; index < aCount; ++index)
00252 push(objects[index]);
00253 }
00254
00255 return self;
00256 }
00257
00258
00263 - (BOOL)containsObject:(id)anObject
00264 {
00265 return [self indexOfObject:anObject] != CPNotFound;
00266 }
00267
00271 - (int)count
00272 {
00273 return length;
00274 }
00275
00283 - (int)indexOfObject:(id)anObject
00284 {
00285 if (anObject === nil)
00286 return CPNotFound;
00287
00288 var i = 0,
00289 count = length;
00290
00291
00292 if (anObject.isa)
00293 {
00294 for(; i < count; ++i)
00295 if([self[i] isEqual:anObject])
00296 return i;
00297 }
00298
00299
00300 else if (self.indexOf)
00301 return indexOf(anObject);
00302
00303 else
00304 for(; i < count; ++i)
00305 if(self[i] == anObject)
00306 return i;
00307
00308 return CPNotFound;
00309 }
00310
00319 - (int)indexOfObject:(id)anObject inRange:(CPRange)aRange
00320 {
00321 if (anObject === nil)
00322 return CPNotFound;
00323
00324 var i = aRange.location,
00325 count = MIN(CPMaxRange(aRange), length);
00326
00327
00328 if (anObject.isa)
00329 {
00330 for(; i < count; ++i)
00331 if([self[i] isEqual:anObject])
00332 return i;
00333 }
00334
00335 else
00336 for(; i < count; ++i)
00337 if(self[i] == anObject)
00338 return i;
00339
00340 return CPNotFound;
00341 }
00342
00348 - (int)indexOfObjectIdenticalTo:(id)anObject
00349 {
00350 if (anObject === nil)
00351 return CPNotFound;
00352
00353
00354
00355 if (self.indexOf)
00356 return indexOf(anObject);
00357
00358
00359 else
00360 {
00361 var index = 0,
00362 count = length;
00363
00364 for(; index < count; ++index)
00365 if(self[index] == anObject)
00366 return index;
00367 }
00368
00369 return CPNotFound;
00370 }
00371
00380 - (int)indexOfObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange
00381 {
00382 if (anObject === nil)
00383 return CPNotFound;
00384
00385
00386
00387 if (self.indexOf)
00388 {
00389 var index = indexOf(anObject, aRange.location);
00390
00391 if (CPLocationInRange(index, aRange))
00392 return index;
00393 }
00394
00395
00396 else
00397 {
00398 var index = aRange.location,
00399 count = MIN(CPMaxRange(aRange), length);
00400
00401 for(; index < count; ++index)
00402 if(self[index] == anObject)
00403 return index;
00404 }
00405
00406 return CPNotFound;
00407 }
00408
00417 - (unsigned)indexOfObject:(id)anObject sortedBySelector:(SEL)aSelector
00418 {
00419 return [self indexOfObject:anObject sortedByFunction: function(lhs, rhs) { objj_msgSend(lhs, aSelector, rhs); }];
00420 }
00421
00434 - (unsigned)indexOfObject:(id)anObject sortedByFunction:(Function)aFunction
00435 {
00436 return [self indexOfObject:anObject sortedByFunction:aFunction context:nil];
00437 }
00438
00452 - (unsigned)indexOfObject:(id)anObject sortedByFunction:(Function)aFunction context:(id)aContext
00453 {
00454 if (!aFunction || anObject === undefined)
00455 return CPNotFound;
00456
00457 var mid, c, first = 0, last = length - 1;
00458 while (first <= last)
00459 {
00460 mid = FLOOR((first + last) / 2);
00461 c = aFunction(anObject, self[mid], aContext);
00462
00463 if (c > 0)
00464 first = mid + 1;
00465 else if (c < 0)
00466 last = mid - 1;
00467 else
00468 {
00469 while (mid < length - 1 && aFunction(anObject, self[mid+1], aContext) == CPOrderedSame)
00470 mid++;
00471
00472 return mid;
00473 }
00474 }
00475
00476 return CPNotFound;
00477 }
00478
00487 - (unsigned)indexOfObject:(id)anObject sortedByDescriptors:(CPArray)descriptors
00488 {
00489 [self indexOfObject:anObject sortedByFunction:function(lhs, rhs)
00490 {
00491 var i = 0,
00492 count = [descriptors count],
00493 result = CPOrderedSame;
00494
00495 while (i < count)
00496 if((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
00497 return result;
00498
00499 return result;
00500 }];
00501 }
00502
00506 - (id)lastObject
00507 {
00508 var count = [self count];
00509
00510 if (!count) return nil;
00511
00512 return self[count - 1];
00513 }
00514
00519 - (id)objectAtIndex:(int)anIndex
00520 {
00521 return self[anIndex];
00522 }
00523
00529 - (CPArray)objectsAtIndexes:(CPIndexSet)indexes
00530 {
00531 var index = [indexes firstIndex],
00532 objects = [];
00533
00534 while(index != CPNotFound)
00535 {
00536 [objects addObject:self[index]];
00537 index = [indexes indexGreaterThanIndex:index];
00538 }
00539
00540 return objects;
00541 }
00542
00548 - (CPEnumerator)objectEnumerator
00549 {
00550 return [[_CPArrayEnumerator alloc] initWithArray:self];
00551 }
00552
00558 - (CPEnumerator)reverseObjectEnumerator
00559 {
00560 return [[_CPReverseArrayEnumerator alloc] initWithArray:self];
00561 }
00562
00563
00569 - (void)makeObjectsPerformSelector:(SEL)aSelector
00570 {
00571 if (!aSelector)
00572 [CPException raise:CPInvalidArgumentException reason:"makeObjectsPerformSelector: 'aSelector' can't be nil"];
00573
00574 var index = 0,
00575 count = length;
00576
00577 for(; index < count; ++index)
00578 objj_msgSend(self[index], aSelector);
00579 }
00580
00587 - (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
00588 {
00589 if (!aSelector)
00590 [CPException raise:CPInvalidArgumentException reason:"makeObjectsPerformSelector:withObject 'aSelector' can't be nil"];
00591
00592 var index = 0,
00593 count = length;
00594
00595 for(; index < count; ++index)
00596 objj_msgSend(self[index], aSelector, anObject);
00597 }
00598
00599
00605 - (id)firstObjectCommonWithArray:(CPArray)anArray
00606 {
00607 if (![anArray count] || ![self count])
00608 return nil;
00609
00610 var i = 0,
00611 count = [self count];
00612
00613 for(; i < count; ++i)
00614 if([anArray containsObject:self[i]])
00615 return self[i];
00616
00617 return nil;
00618 }
00619
00623 - (BOOL)isEqualToArray:(id)anArray
00624 {
00625 if (self === anArray)
00626 return YES;
00627
00628 if(length != anArray.length)
00629 return NO;
00630
00631 var index = 0,
00632 count = [self count];
00633
00634 for(; index < count; ++index)
00635 {
00636 var lhs = self[index],
00637 rhs = anArray[index];
00638
00639
00640 if (lhs !== rhs && (!lhs.isa || !rhs.isa || ![lhs isEqual:rhs]))
00641 return NO;
00642 }
00643
00644 return YES;
00645 }
00646
00647 - (BOOL)isEqual:(id)anObject
00648 {
00649 if (self === anObject)
00650 return YES;
00651
00652 if(![anObject isKindOfClass:[CPArray class]])
00653 return NO;
00654
00655 return [self isEqualToArray:anObject];
00656 }
00657
00658
00665 - (CPArray)arrayByAddingObject:(id)anObject
00666 {
00667 if (anObject === nil || anObject === undefined)
00668 [CPException raise:CPInvalidArgumentException
00669 reason:"arrayByAddingObject: object can't be nil"];
00670
00671 var array = [self copy];
00672
00673 array.push(anObject);
00674
00675 return array;
00676 }
00677
00682 - (CPArray)arrayByAddingObjectsFromArray:(CPArray)anArray
00683 {
00684 return slice(0).concat(anArray);
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00707 - (CPArray)subarrayWithRange:(CPRange)aRange
00708 {
00709 if (aRange.location < 0 || CPMaxRange(aRange) > length)
00710 [CPException raise:CPRangeException reason:"subarrayWithRange: aRange out of bounds"];
00711
00712 return slice(aRange.location, CPMaxRange(aRange));
00713 }
00714
00715
00716
00717
00718
00719 - (CPArray)sortedArrayUsingDescriptors:(CPArray)descriptors
00720 {
00721 var sorted = [self copy];
00722
00723 [sorted sortUsingDescriptors:descriptors];
00724
00725 return sorted;
00726 }
00727
00731 - (CPArray)sortedArrayUsingFunction:(Function)aFunction
00732 {
00733 return [self sortedArrayUsingFunction:aFunction context:nil];
00734 }
00735
00744 - (CPArray)sortedArrayUsingFunction:(Function)aFunction context:(id)aContext
00745 {
00746 var sorted = [self copy];
00747
00748 [sorted sortUsingFunction:aFunction context:aContext];
00749
00750 return sorted;
00751 }
00752
00757 - (CPArray)sortedArrayUsingSelector:(SEL)aSelector
00758 {
00759 var sorted = [self copy]
00760
00761 [sorted sortUsingSelector:aSelector];
00762
00763 return sorted;
00764 }
00765
00766
00767
00776 - (CPString)componentsJoinedByString:(CPString)aString
00777 {
00778
00779
00780 return join(aString);
00781 }
00782
00783
00784
00788 - (CPString)description
00789 {
00790 var index = 0,
00791 count = [self count],
00792 description = '(';
00793
00794 for(; index < count; ++index)
00795 {
00796 var object = self[index];
00797
00798 if (object && object.isa)
00799 description += [object description];
00800 else
00801 description += object;
00802
00803 if (index !== count - 1)
00804 description += ", ";
00805 }
00806
00807 return description + ')';
00808 }
00809
00810
00818 - (CPArray)pathsMatchingExtensions:(CPArray)filterTypes
00819 {
00820 var index = 0,
00821 count = [self count],
00822 array = [];
00823
00824 for(; index < count; ++index)
00825 if (self[index].isa && [self[index] isKindOfClass:[CPString class]] && [filterTypes containsObject:[self[index] pathExtension]])
00826 array.push(self[index]);
00827
00828 return array;
00829 }
00830
00831
00837 - (void)setValue:(id)aValue forKey:(CPString)aKey
00838 {
00839 var i = 0,
00840 count = [self count];
00841
00842 for(; i < count; ++i)
00843 [self[i] setValue:aValue forKey:aKey];
00844 }
00845
00851 - (CPArray)valueForKey:(CPString)aKey
00852 {
00853 var i = 0,
00854 count = [self count],
00855 array = [];
00856
00857 for(; i < count; ++i)
00858 array.push([self[i] valueForKey:aKey]);
00859
00860 return array;
00861 }
00862
00863
00864
00869 - (id)copy
00870 {
00871 return slice(0);
00872 }
00873
00874 @end
00875
00876 @implementation CPArray(CPMutableArray)
00877
00878
00884 + (CPArray)arrayWithCapacity:(unsigned)aCapacity
00885 {
00886 return [[self alloc] initWithCapacity:aCapacity];
00887 }
00888
00893 - (id)initWithCapacity:(unsigned)aCapacity
00894 {
00895 return self;
00896 }
00897
00898
00903 - (void)addObject:(id)anObject
00904 {
00905 push(anObject);
00906 }
00907
00912 - (void)addObjectsFromArray:(CPArray)anArray
00913 {
00914 splice.apply(self, [length, 0].concat(anArray));
00915 }
00916
00922 - (void)insertObject:(id)anObject atIndex:(int)anIndex
00923 {
00924 splice(anIndex, 0, anObject);
00925 }
00926
00932 - (void)insertObjects:(CPArray)objects atIndexes:(CPIndexSet)indexes
00933 {
00934 var indexesCount = [indexes count],
00935 objectsCount = [objects count];
00936
00937 if(indexesCount !== objectsCount)
00938 [CPException raise:CPRangeException reason:"the counts of the passed-in array (" + objectsCount + ") and index set (" + indexesCount + ") must be identical."];
00939
00940 var lastIndex = [indexes lastIndex];
00941
00942 if(lastIndex >= [self count] + indexesCount)
00943 [CPException raise:CPRangeException reason:"the last index (" + lastIndex + ") must be less than the sum of the original count (" + [self count] + ") and the insertion count (" + indexesCount + ")."];
00944
00945 var index = 0,
00946 currentIndex = [indexes firstIndex];
00947
00948 for (; index < objectsCount; ++index, currentIndex = [indexes indexGreaterThanIndex:currentIndex])
00949 [self insertObject:objects[index] atIndex:currentIndex];
00950 }
00951
00957 - (void)replaceObjectAtIndex:(int)anIndex withObject:(id)anObject
00958 {
00959 self[anIndex] = anObject;
00960 }
00961
00968 - (void)replaceObjectsAtIndexes:(CPIndexSet)anIndexSet withObjects:(CPArray)objects
00969 {
00970 var i = 0,
00971 index = [anIndexSet firstIndex];
00972
00973 while(index != CPNotFound)
00974 {
00975 [self replaceObjectAtIndex:index withObject:objects[i++]];
00976 index = [anIndexSet indexGreaterThanIndex:index];
00977 }
00978 }
00979
00988 - (void)replaceObjectsInRange:(CPRange)aRange withObjectsFromArray:(CPArray)anArray range:(CPRange)otherRange
00989 {
00990 if (!otherRange.location && otherRange.length == [anArray count])
00991 [self replaceObjectsInRange:aRange withObjectsFromArray:anArray];
00992 else
00993 splice.apply(self, [aRange.location, aRange.length].concat([anArray subarrayWithRange:otherRange]));
00994 }
00995
01003 - (void)replaceObjectsInRange:(CPRange)aRange withObjectsFromArray:(CPArray)anArray
01004 {
01005 splice.apply(self, [aRange.location, aRange.length].concat(anArray));
01006 }
01007
01012 - (void)setArray:(CPArray)anArray
01013 {
01014 if(self == anArray) return;
01015
01016 splice.apply(self, [0, length].concat(anArray));
01017 }
01018
01019
01023 - (void)removeAllObjects
01024 {
01025 splice(0, length);
01026 }
01027
01031 - (void)removeLastObject
01032 {
01033 pop();
01034 }
01035
01040 - (void)removeObject:(id)anObject
01041 {
01042 [self removeObject:anObject inRange:CPMakeRange(0, length)];
01043 }
01044
01050 - (void)removeObject:(id)anObject inRange:(CPRange)aRange
01051 {
01052 var index;
01053
01054 while ((index = [self indexOfObject:anObject inRange:aRange]) != CPNotFound)
01055 {
01056 [self removeObjectAtIndex:index];
01057 aRange = CPIntersectionRange(CPMakeRange(index, length - index), aRange);
01058 }
01059 }
01060
01065 - (void)removeObjectAtIndex:(int)anIndex
01066 {
01067 splice(anIndex, 1);
01068 }
01069
01074 - (void)removeObjectsAtIndexes:(CPIndexSet)anIndexSet
01075 {
01076 var index = [anIndexSet lastIndex];
01077
01078 while (index != CPNotFound)
01079 {
01080 [self removeObjectAtIndex:index];
01081 index = [anIndexSet indexLessThanIndex:index];
01082 }
01083 }
01084
01090 - (void)removeObjectIdenticalTo:(id)anObject
01091 {
01092 [self removeObjectIdenticalTo:anObject inRange:CPMakeRange(0, length)];
01093 }
01094
01102 - (void)removeObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange
01103 {
01104 var index;
01105
01106 while ((index = [self indexOfObjectIdenticalTo:anObject inRange:aRange]) != CPNotFound)
01107 {
01108 [self removeObjectAtIndex:index];
01109 aRange = CPIntersectionRange(CPMakeRange(index, length - index), aRange);
01110 }
01111 }
01112
01117 - (void)removeObjectsInArray:(CPArray)anArray
01118 {
01119 var index = 0,
01120 count = [anArray count];
01121
01122 for (; index < count; ++index)
01123 [self removeObject:anArray[index]];
01124 }
01125
01130 - (void)removeObjectsInRange:(CPRange)aRange
01131 {
01132 splice(aRange.location, aRange.length);
01133 }
01134
01135
01141 - (void)exchangeObjectAtIndex:(unsigned)anIndex withObjectAtIndex:(unsigned)otherIndex
01142 {
01143 var temporary = self[anIndex];
01144 self[anIndex] = self[otherIndex];
01145 self[otherIndex] = temporary;
01146 }
01147
01148 - (CPArray)sortUsingDescriptors:(CPArray)descriptors
01149 {
01150 sort(function(lhs, rhs)
01151 {
01152 var i = 0,
01153 count = [descriptors count],
01154 result = CPOrderedSame;
01155
01156 while(i < count)
01157 if((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
01158 return result;
01159
01160 return result;
01161 });
01162 }
01163
01169 - (void)sortUsingFunction:(Function)aFunction context:(id)aContext
01170 {
01171 sort(function(lhs, rhs) { return aFunction(lhs, rhs, aContext); });
01172 }
01173
01178 - (void)sortUsingSelector:(SEL)aSelector
01179 {
01180 sort(function(lhs, rhs) { return objj_msgSend(lhs, aSelector, rhs); });
01181 }
01182
01183 @end
01184
01185 @implementation CPArray (CPCoding)
01186
01187 - (id)initWithCoder:(CPCoder)aCoder
01188 {
01189 return [aCoder decodeObjectForKey:@"CP.objects"];
01190 }
01191
01192 - (void)encodeWithCoder:(CPCoder)aCoder
01193 {
01194 [aCoder _encodeArrayOfObjects:self forKey:@"CP.objects"];
01195 }
01196
01197 @end
01198
01204 @implementation CPMutableArray : CPArray
01205
01206 @end
01207
01208 Array.prototype.isa = CPArray;
01209 [CPArray initialize];
01210