• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//
2//  AMutableArray.m
3//  a_ST4
4//
5//  Created by Alan Condit on 3/12/11.
6//  Copyright 2011 Alan's MachineWorks. All rights reserved.
7//
8#import "AMutableArray.h"
9#import "ArrayIterator.h"
10
11#define BUFFSIZE 25
12
13@implementation AMutableArray
14
15@synthesize BuffSize;
16@synthesize buffer;
17@synthesize ptrBuffer;
18//@synthesize count;
19
20
21+ (id) newArray
22{
23    return [[AMutableArray alloc] init];
24}
25
26+ (id) arrayWithCapacity:(NSInteger)size
27{
28    return [[AMutableArray alloc] initWithCapacity:size];
29}
30
31- (id) init
32{
33    self=[super init];
34    if ( self != nil ) {
35        BuffSize = BUFFSIZE;
36        buffer = [[NSMutableData dataWithLength:(BuffSize * sizeof(id))] retain];
37        ptrBuffer = (id *)[buffer mutableBytes];
38        for( int idx = 0; idx < BuffSize; idx++ ) {
39            ptrBuffer[idx] = nil;
40        }
41    }
42    return self;
43}
44
45- (id) initWithCapacity:(NSInteger)len
46{
47    self=[super init];
48    if ( self != nil ) {
49        BuffSize = (len >= BUFFSIZE) ? len : BUFFSIZE;
50        buffer = [[NSMutableData dataWithLength:(BuffSize * sizeof(id))] retain];
51        ptrBuffer = (id *)[buffer mutableBytes];
52        for( int idx = 0; idx < BuffSize; idx++ ) {
53            ptrBuffer[idx] = nil;
54        }
55    }
56    return self;
57}
58
59- (void) dealloc
60{
61#ifdef DEBUG_DEALLOC
62    NSLog( @"called dealloc in AMutableArray" );
63#endif
64    if ( count ) [self removeAllObjects];
65    if ( buffer ) [buffer release];
66    [super dealloc];
67}
68
69- (id) copyWithZone:(NSZone *)aZone
70{
71    AMutableArray *copy;
72
73    copy = [[[self class] allocWithZone:aZone] init];
74    if ( buffer ) {
75        copy.buffer = [buffer copyWithZone:aZone];
76    }
77    copy.ptrBuffer = [copy.buffer mutableBytes];
78    copy.count = count;
79    copy.BuffSize = BuffSize;
80    return copy;
81}
82
83- (void) addObject:(id)anObject
84{
85    if ( anObject == nil ) anObject = [NSNull null];
86    [anObject retain];
87	[self ensureCapacity:count];
88	ptrBuffer[count++] = anObject;
89}
90
91- (void) addObjectsFromArray:(NSArray *)otherArray
92{
93    NSInteger cnt, i;
94    id tmp;
95    cnt = [otherArray count];
96    [self ensureCapacity:count+cnt];
97    for( i = 0; i < cnt; i++) {
98        tmp = [otherArray objectAtIndex:i];
99        [self addObject:tmp];
100    }
101    return;
102}
103
104- (id) objectAtIndex:(NSInteger)anIdx
105{
106    id obj;
107    if ( anIdx < 0 || anIdx >= count ) {
108        @throw [NSException exceptionWithName:NSRangeException
109                                       reason:[NSString stringWithFormat:@"Attempt to retrieve objectAtIndex %d past end", anIdx]
110                                     userInfo:nil];
111        return nil;
112    }
113    ptrBuffer = [buffer mutableBytes];
114    obj = ptrBuffer[anIdx];
115    if ( obj == [NSNull null] ) {
116        obj = nil;
117    }
118    return obj;
119}
120
121- (void) insertObject:(id)anObject atIndex:(NSInteger)anIdx
122{
123    if ( anObject == nil ) anObject = [NSNull null];
124    if ( anObject == nil ) {
125        @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Attempt to insert nil objectAtIndex" userInfo:nil];
126    }
127    if ( anIdx < 0 || anIdx > count ) {
128        @throw [NSException exceptionWithName:NSRangeException reason:@"Attempt to insertObjectAtIndex past end" userInfo:nil];
129    }
130    if ( count == BuffSize ) {
131        [self ensureCapacity:count];
132    }
133    if ( anIdx < count ) {
134        for (int i = count; i > anIdx; i--) {
135            ptrBuffer[i] = ptrBuffer[i-1];
136        }
137    }
138    ptrBuffer[anIdx] = [anObject retain];
139    count++;
140}
141
142- (void) removeObjectAtIndex:(NSInteger)idx;
143{
144    id tmp;
145    if (idx < 0 || idx >= count) {
146        @throw [NSException exceptionWithName:NSRangeException reason:@"Attempt to insert removeObjectAtIndex past end" userInfo:nil];
147    }
148    else if (count) {
149        tmp = ptrBuffer[idx];
150        if ( tmp ) [tmp release];
151        for (int i = idx; i < count; i++) {
152            ptrBuffer[i] = ptrBuffer[i+1];
153        }
154        count--;
155    }
156}
157
158- (void) removeLastObject
159{
160    id tmp;
161    if (count == 0) {
162        @throw [NSException exceptionWithName:NSRangeException reason:@"Attempt to removeLastObject from 0" userInfo:nil];
163    }
164    count--;
165    tmp = ptrBuffer[count];
166    if ( tmp ) [tmp release];
167    ptrBuffer[count] = nil;
168}
169
170- (void)removeAllObjects
171{
172    id tmp;
173    if (count == 0) {
174        @throw [NSException exceptionWithName:NSRangeException reason:@"Attempt to removeAllObjects from 0" userInfo:nil];
175    }
176    int i;
177    for ( i = 0; i < BuffSize; i++ ) {
178        if (i < count) {
179            tmp = ptrBuffer[i];
180            if ( tmp ) [tmp release];
181        }
182        ptrBuffer[i] = nil;
183    }
184    count = 0;
185}
186
187- (void) replaceObjectAtIndex:(NSInteger)idx withObject:(id)obj
188{
189    id tmp;
190    if ( obj == nil ) {
191        obj = [NSNull null];
192    }
193    if ( idx < 0 || idx >= count ) {
194        @throw [NSException exceptionWithName:NSRangeException reason:@"Attempt to replace object past end" userInfo:nil];
195   }
196    if ( count ) {
197        [obj retain];
198        tmp = ptrBuffer[idx];
199        if ( tmp ) [tmp release];
200        ptrBuffer[idx] = obj;
201    }
202}
203
204- (NSInteger) count
205{
206    return count;
207}
208
209- (void) setCount:(NSInteger)cnt
210{
211    count = cnt;
212}
213
214- (NSArray *) allObjects
215{
216    return [NSArray arrayWithObjects:ptrBuffer count:count];
217}
218
219- (ArrayIterator *) objectEnumerator
220{
221    return [ArrayIterator newIterator:[self allObjects]];
222}
223
224// This is where all the magic happens.
225// You have two choices when implementing this method:
226// 1) Use the stack based array provided by stackbuf. If you do this, then you must respect the value of 'len'.
227// 2) Return your own array of objects. If you do this, return the full length of the array returned until you run out of objects, then return 0. For example, a linked-array implementation may return each array in order until you iterate through all arrays.
228// In either case, state->itemsPtr MUST be a valid array (non-nil). This sample takes approach #1, using stackbuf to store results.
229- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
230{
231    NSUInteger cnt = 0;
232    // This is the initialization condition, so we'll do one-time setup here.
233    // Ensure that you never set state->state back to 0, or use another method to detect initialization
234    // (such as using one of the values of state->extra).
235    if (state->state == 0) {
236        // We are not tracking mutations, so we'll set state->mutationsPtr to point into one of our extra values,
237        // since these values are not otherwise used by the protocol.
238        // If your class was mutable, you may choose to use an internal variable that is updated when the class is mutated.
239        // state->mutationsPtr MUST NOT be NULL.
240        state->mutationsPtr = &state->extra[0];
241    }
242    // Now we provide items, which we track with state->state, and determine if we have finished iterating.
243    if (state->state < self.count) {
244        // Set state->itemsPtr to the provided buffer.
245        // Alternate implementations may set state->itemsPtr to an internal C array of objects.
246        // state->itemsPtr MUST NOT be NULL.
247        state->itemsPtr = stackbuf;
248        // Fill in the stack array, either until we've provided all items from the list
249        // or until we've provided as many items as the stack based buffer will hold.
250        while((state->state < self.count) && (cnt < len)) {
251            // For this sample, we generate the contents on the fly.
252            // A real implementation would likely just be copying objects from internal storage.
253            stackbuf[cnt++] = ptrBuffer[state->state++];
254        }
255        // state->state = ((cnt < len)? cnt : len);
256    }
257    else
258    {
259        // We've already provided all our items, so we signal we are done by returning 0.
260        cnt = 0;
261    }
262    return cnt;
263}
264
265- (NSString *) description
266{
267    NSMutableString *str;
268    NSInteger idx, cnt;
269    id tmp;
270    cnt = [self count];
271    str = [NSMutableString stringWithCapacity:30];
272    [str appendString:@"["];
273    for (idx = 0; idx < cnt; idx++ ) {
274        tmp = [self objectAtIndex:idx];
275        [str appendString:((tmp == nil) ? @"nil" : [tmp description])];
276    }
277    [str appendString:@"]"];
278    return str;
279}
280
281- (NSString *) toString
282{
283    return [self description];
284}
285
286- (void) ensureCapacity:(NSInteger) index
287{
288	if ((index * sizeof(id)) >= [buffer length])
289	{
290		NSInteger newSize = ([buffer length] / sizeof(id)) * 2;
291		if (index > newSize) {
292			newSize = index + 1;
293		}
294        BuffSize = newSize;
295		[buffer setLength:(BuffSize * sizeof(id))];
296        ptrBuffer = [buffer mutableBytes];
297	}
298}
299
300@end
301