1//
2//  ANTLRIntArray.m
3//  ANTLR
4//
5//  Created by Ian Michell on 27/04/2010.
6// Copyright (c) 2010 Ian Michell 2010 Alan Condit
7// All rights reserved.
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions
11// are met:
12// 1. Redistributions of source code must retain the above copyright
13//    notice, this list of conditions and the following disclaimer.
14// 2. Redistributions in binary form must reproduce the above copyright
15//    notice, this list of conditions and the following disclaimer in the
16//    documentation and/or other materials provided with the distribution.
17// 3. The name of the author may not be used to endorse or promote products
18//    derived from this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "ANTLRIntArray.h"
32#import "ANTLRRuntimeException.h"
33
34@implementation ANTLRIntArray
35
36@synthesize BuffSize;
37@synthesize count;
38@synthesize idx;
39@synthesize buffer;
40@synthesize intBuffer;
41@synthesize SPARSE;
42
43+ (ANTLRIntArray *)newArray
44{
45    return [[ANTLRIntArray alloc] init];
46}
47
48+ (ANTLRIntArray *)newArrayWithLen:(NSUInteger)aLen
49{
50    return [[ANTLRIntArray alloc] initWithLen:aLen];
51}
52
53- (id)init
54{
55    self = [super init];
56    if ( self != nil ) {
57        BuffSize  = (ANTLR_INT_ARRAY_INITIAL_SIZE * (sizeof(NSInteger)/sizeof(id)));
58        count = 0;
59        idx = -1;
60        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize * sizeof(id)] retain];
61        intBuffer = (NSInteger *)[buffer mutableBytes];
62        SPARSE = NO;
63    }
64    return self;
65}
66
67- (id)initWithLen:(NSUInteger)aLen
68{
69    self = [super init];
70    if ( self != nil ) {
71        BuffSize  = (ANTLR_INT_ARRAY_INITIAL_SIZE * (sizeof(NSInteger)/sizeof(id)));
72        count = 0;
73        idx = -1;
74        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize * sizeof(id)] retain];
75        intBuffer = (NSInteger *)[buffer mutableBytes];
76        SPARSE = NO;
77    }
78    return self;
79}
80
81- (void)dealloc
82{
83#ifdef DEBUG_DEALLOC
84    NSLog( @"called dealloc in ANTLRIntArray" );
85#endif
86    if ( buffer ) [buffer release];
87    [super dealloc];
88}
89
90- (id)copyWithZone:(NSZone *)aZone
91{
92    ANTLRIntArray *copy;
93    
94    copy = [[[self class] alloc] initWithLen:BuffSize];
95    copy.idx = self.idx;
96    NSInteger anIndex;
97    for ( anIndex = 0; anIndex < BuffSize; anIndex++ ) {
98        [copy addInteger:intBuffer[anIndex]];
99    }
100    return copy;
101}
102
103- (NSUInteger)count
104{
105    return count;
106}
107
108// FIXME: Java runtime returns p, I'm not so sure it's right so have added p + 1 to show true size!
109- (NSUInteger)size
110{
111    if ( count > 0 )
112        return ( count * sizeof(NSInteger));
113    return 0;
114}
115
116- (void)addInteger:(NSInteger) value
117{
118    [self ensureCapacity:idx+1];
119    intBuffer[++idx] = (NSInteger) value;
120    count++;
121}
122
123- (NSInteger)pop
124{
125    if ( idx < 0 ) {
126        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Nothing to pop, count = %d", count]];
127    }
128    NSInteger value = (NSInteger) intBuffer[idx--];
129    count--;
130    return value;
131}
132
133- (void)push:(NSInteger)aValue
134{
135    [self addInteger:aValue];
136}
137
138- (NSInteger)integerAtIndex:(NSUInteger) anIndex
139{
140    if ( SPARSE==NO  && anIndex > idx ) {
141        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Index %d must be less than count %d", anIndex, count]];
142    }
143    else if ( SPARSE == YES && anIndex >= BuffSize ) {
144        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Index %d must be less than BuffSize %d", anIndex, BuffSize]];
145    }
146    return intBuffer[anIndex];
147}
148
149- (void)insertInteger:(NSInteger)aValue AtIndex:(NSUInteger)anIndex
150{
151    [self replaceInteger:aValue AtIndex:anIndex];
152    count++;
153}
154
155- (NSInteger)removeIntegerAtIndex:(NSUInteger) anIndex
156{
157    if ( SPARSE==NO && anIndex > idx ) {
158        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Index %d must be less than count %d", anIndex, count]];
159        return (NSInteger)-1;
160    } else if ( SPARSE==YES && anIndex >= BuffSize ) {
161        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Index %d must be less than BuffSize %d", anIndex, BuffSize]];
162    }
163    count--;
164    return intBuffer[anIndex];
165}
166
167- (void)replaceInteger:(NSInteger)aValue AtIndex:(NSUInteger)anIndex
168{
169    if ( SPARSE == NO && anIndex > idx ) {
170        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Index %d must be less than count %d", anIndex, count]];
171    }
172    else if ( SPARSE == YES && anIndex >= BuffSize ) {
173        @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Index %d must be less than BuffSize %d", anIndex, BuffSize]];
174    }
175    intBuffer[anIndex] = aValue;
176}
177
178-(void) reset
179{
180    count = 0;
181    idx = -1;
182}
183
184- (void) ensureCapacity:(NSUInteger) anIndex
185{
186    if ( (anIndex * sizeof(NSUInteger)) >= [buffer length] )
187    {
188        NSUInteger newSize = ([buffer length] / sizeof(NSInteger)) * 2;
189        if (anIndex > newSize) {
190            newSize = anIndex + 1;
191        }
192        BuffSize = newSize;
193        [buffer setLength:(BuffSize * sizeof(NSUInteger))];
194        intBuffer = (NSInteger *)[buffer mutableBytes];
195    }
196}
197
198@end
199
200