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