1 /* Copyright (c) 2006-2007 Christopher J. W. Lloyd
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. */
9 #import <Foundation/NSMutableArray_concrete.h>
10 #import <Foundation/NSRaise.h>
11 #import <Foundation/NSCoder.h>
12 #import <Foundation/NSRaiseException.h>
14 @implementation NSMutableArray_concrete
16 static inline NSUInteger roundCapacityUp(NSUInteger capacity){
17 return (capacity<1)?1:capacity;
21 NSMutableArray_concrete *NSMutableArray_concreteInit(NSMutableArray_concrete *self, id *objects, NSUInteger count, NSZone *zone)
26 self->_capacity = roundCapacityUp(count);
27 self->_objects = NSZoneMalloc(zone, sizeof(id) * self->_capacity);
28 for (i = 0; i < count; i++) {
29 self->_objects[i] = [objects[i] retain];
36 NSMutableArray_concrete *NSMutableArray_concreteInitWithCapacity(NSMutableArray_concrete *self, NSUInteger capacity, NSZone *zone)
39 self->_capacity = roundCapacityUp(capacity);
40 self->_objects = NSZoneMalloc(zone, sizeof(id) * self->_capacity);
46 NSArray *NSMutableArray_concreteNew(NSZone *zone,id *objects,NSUInteger count) {
47 NSMutableArray_concrete *self=NSAllocateObject([NSMutableArray_concrete class],0,zone);
49 self = NSMutableArray_concreteInit(self,objects,count,zone);
54 NSArray *NSMutableArray_concreteNewWithCapacity(NSZone *zone,NSUInteger capacity) {
55 NSMutableArray_concrete *self=NSAllocateObject([NSMutableArray_concrete class],0,zone);
57 self = NSMutableArray_concreteInitWithCapacity(self,capacity,zone);
63 return NSMutableArray_concreteInitWithCapacity(self,0,
64 NSZoneFromPointer(self));
67 -initWithArray:(NSArray *)array {
68 NSUInteger i,count=[array count];
70 NSMutableArray_concreteInitWithCapacity(self,count,NSZoneFromPointer(self));
72 [array getObjects:_objects];
79 -initWithContentsOfFile:(NSString *)path {
80 NSUnimplementedMethod();
84 -initWithObjects:(id *)objects count:(NSUInteger)count {
85 return NSMutableArray_concreteInit(self,objects,count,
86 NSZoneFromPointer(self));
89 -initWithObjects:object,... {
94 va_start(arguments,object);
96 while(va_arg(arguments,id)!=nil)
100 objects=__builtin_alloca(sizeof(id)*count);
102 va_start(arguments,object);
105 objects[i]=va_arg(arguments,id);
108 return NSMutableArray_concreteInit(self,objects,count,NSZoneFromPointer(self));
111 -initWithCapacity:(NSUInteger)capacity {
112 return NSMutableArray_concreteInitWithCapacity(self,capacity,
113 NSZoneFromPointer(self));
117 NSInteger count=_count;
120 [_objects[count] release];
122 NSZoneFree(NSZoneFromPointer(_objects),_objects);
123 NSDeallocateObject(self);
132 -objectAtIndex:(NSUInteger)index {
134 NSRaiseException(NSRangeException,self,_cmd,@"index %d beyond count %d",index,[self count]);
138 return _objects[index];
141 -(void)addObject:object {
143 NSRaiseException(NSInvalidArgumentException,self,_cmd,@"nil object");
150 if(_count>_capacity){
152 _objects=NSZoneRealloc(NSZoneFromPointer(_objects),_objects,sizeof(id)*_capacity);
154 _objects[_count-1]=object;
157 -(void)replaceObjectAtIndex:(NSUInteger)index withObject:object {
159 NSRaiseException(NSInvalidArgumentException,self,_cmd,@"nil object");
164 NSRaiseException(NSRangeException,self,_cmd,@"index %d beyond count %d",index,[self count]);
169 [_objects[index] release];
170 _objects[index]=object;
177 return _objects[_count-1];
180 -(void)insertObject:object atIndex:(NSUInteger)index {
184 NSRaiseException(NSInvalidArgumentException,self,_cmd,@"nil object");
189 NSRaiseException(NSRangeException,self,_cmd,@"index %d beyond count %d",index,[self count]);
194 if(_count>_capacity){
196 _objects=NSZoneRealloc(NSZoneFromPointer(_objects),
197 _objects,sizeof(id)*_capacity);
201 for(c=_count-1;c>index && c>0;c--)
202 _objects[c]=_objects[c-1];
204 _objects[index]=[object retain];
207 static void removeObjectAtIndex(NSMutableArray_concrete *self,NSUInteger index) {
211 object=self->_objects[index];
213 for(i=index;i<self->_count;i++)
214 self->_objects[i]=self->_objects[i+1];
218 if(self->_capacity>self->_count*2){
219 self->_capacity=self->_count;
220 self->_objects=NSZoneRealloc(NSZoneFromPointer(self->_objects),self->_objects,sizeof(id)*self->_capacity);
224 -(void)removeObjectAtIndex:(NSUInteger)index {
226 NSRaiseException(NSRangeException,self,_cmd,@"index %d beyond count %d",index,[self count]);
229 removeObjectAtIndex(self,index);
232 -(void)removeLastObject {
234 NSRaiseException(NSRangeException,self,_cmd,@"index %d beyond count %d",1,[self count]);
238 removeObjectAtIndex(self,_count-1);
241 -(void)removeAllObjects {
244 for(i=0;i<_count;i++)
245 [_objects[i] release];
248 if(self->_capacity>8){
250 self->_objects=NSZoneRealloc(NSZoneFromPointer(self->_objects),self->_objects,sizeof(id)*self->_capacity);
254 -(void)getObjects:(id *)objects {
257 for(i=0;i<_count;i++)
258 objects[i]=_objects[i];
261 -(NSUInteger)indexOfObjectIdenticalTo:object {
264 for(i=0;i<self->_count;i++)
265 if(self->_objects[i]==object)
271 static inline NSUInteger indexOfObject(NSMutableArray_concrete *self,id object){
274 for(i=0;i<self->_count;i++)
275 if([self->_objects[i] isEqual:object])
281 -(NSUInteger)indexOfObject:object {
282 return indexOfObject(self,object);
285 -(BOOL)containsObject:object {
286 return (indexOfObject(self,object)!=NSNotFound)?YES:NO;
289 -(void)makeObjectsPerformSelector:(SEL)selector {
290 NSInteger i, count = [self count];
292 for (i = 0; i < count; i++)
293 [_objects[i] performSelector:selector];
298 -(void)mergeUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context A: (id *)A left:(NSInteger)iLeft right:(NSInteger)iRight end:(NSInteger)iEnd B: (id *)B
300 NSInteger i0 = iLeft;
301 NSInteger i1 = iRight;
304 /* While there are elements in the left or right lists */
305 for (j = iLeft; j < iEnd; j++)
307 /* If left list head exists and is <= existing right list head */
308 if (i0 < iRight && (i1 >= iEnd || compare(A[i0], A[i1], context) != NSOrderedDescending))
319 // iterative bottom up mergesort based on http://en.wikipedia.org/wiki/Merge_sort
320 -(void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context {
321 NSInteger n = _count;
323 /* array A[] has the items to sort; array B[] is a work array */
325 id *B = NSZoneMalloc(NULL,(n+1)* sizeof(id));
327 /* Each 1-element run in A is already "sorted". */
329 /* Make successively longer sorted runs of length 2, 4, 8, 16... until whole array is sorted. */
330 for (int width = 1; width < n; width = 2 * width)
332 /* Array A is full of runs of length width. */
333 for (int i = 0; i < n; i = i + 2 * width)
335 /* Merge two runs: A[i:i+width-1] and A[i+width:i+2*width-1] to B[] */
336 /* or copy A[i:n-1] to B[] ( if(i+width >= n) ) */
337 [self mergeUsingFunction: compare context: context A: A left: i right: MIN(i+width, n) end: MIN(i+2*width, n) B: B];
339 /* Now work array B is full of runs of length 2*width. */
340 /* Copy array B to array A for next iteration. */
341 memcpy(A, B, n * sizeof(id));
347 -(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)length;
349 if(state->state>=_count)
352 state->itemsPtr=_objects;
355 state->mutationsPtr=(unsigned long*)self;