1/*
2 * [The "BSD license"]
3 *  Copyright (c) 2011 Terence Parr and Alan Condit
4 *  All rights reserved.
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions
8 *  are met:
9 *  1. Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 *  2. Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *  3. The name of the author may not be used to endorse or promote products
15 *     derived from this software without specific prior written permission.
16 *
17 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28#import "AMutableArray.h"
29#import "ArrayIterator.h"
30#import "RuntimeException.h"
31
32@class AMutableArray;
33
34@implementation ArrayIterator
35
36@synthesize peekObj;
37//@synthesize count;
38@synthesize index;
39@synthesize anArray;
40
41
42+ (ArrayIterator *) newIterator:(NSArray *)array
43{
44    return [[ArrayIterator alloc] initWithArray:array];
45}
46
47+ (ArrayIterator *) newIteratorForDictKey:(NSDictionary *)dict
48{
49    return [[ArrayIterator alloc] initWithDictKey:dict];
50}
51
52+ (ArrayIterator *) newIteratorForDictObj:(NSDictionary *)dict
53{
54    return [[ArrayIterator alloc] initWithDictObj:dict];
55}
56
57- (id) initWithArray:(NSArray *)array
58{
59    self=[super init];
60    if ( self != nil ) {
61        if (![array isKindOfClass:[NSArray class]]) {
62                @throw [NSException exceptionWithName:NSInvalidArgumentException
63                                               reason:[NSString stringWithFormat:@"ArrayIterator expecting NSArray class but got %@", [array className]]
64                                             userInfo:nil];
65        }
66        anArray = [array retain];
67#ifdef DONTUSENOMO
68        for (int i = 0; i < [array count]; i++) {
69            [anArray addObject:[array objectAtIndex:i]];
70            count++;
71        }
72#endif
73        peekObj = nil;
74        count = [anArray count];
75        index = 0;
76    }
77    return self;
78}
79
80- (id) initWithDictKey:(NSDictionary *)dict
81{
82    self=[super init];
83    if ( self != nil ) {
84        if (![dict isKindOfClass:[NSDictionary class]]) {
85            @throw [NSException exceptionWithName:NSInvalidArgumentException
86                                           reason:[NSString stringWithFormat:@"ArrayIterator expecting NSDictionary class but got %@", [dict className]]
87                                         userInfo:nil];
88        }
89        anArray = [[[dict keyEnumerator] allObjects] retain];
90        peekObj = nil;
91        count = [anArray count];
92        index = 0;
93    }
94    return self;
95}
96
97- (id) initWithDictObj:(NSDictionary *)dict
98{
99    self=[super init];
100    if ( self != nil ) {
101        if (![dict isKindOfClass:[NSDictionary class]]) {
102            @throw [NSException exceptionWithName:NSInvalidArgumentException
103                                           reason:[NSString stringWithFormat:@"ArrayIterator expecting NSDictionary class but got %@", [dict className]]
104                                         userInfo:nil];
105        }
106        anArray = [[[dict objectEnumerator] allObjects] retain];
107        peekObj = nil;
108        count = [anArray count];
109        index = 0;
110    }
111    return self;
112}
113
114- (void)dealloc
115{
116#ifdef DEBUG_DEALLOC
117    NSLog( @"called dealloc in ArrayIterator" );
118#endif
119    if ( anArray ) [anArray release];
120    [super dealloc];
121}
122
123- (BOOL) hasNext
124{
125    if ( peekObj == nil ) {
126        peekObj = [self nextObject];
127    }
128    return ((peekObj) ? YES : NO);
129}
130
131- (NSObject *) nextObject
132{
133    id obj = nil;
134    if ( peekObj ) {
135        obj = peekObj;
136        peekObj = nil;
137        return obj;
138    }
139    if ( index >= count ) {
140        return nil;
141    }
142    if ( anArray ) {
143        obj = [anArray objectAtIndex:index++];
144        if ( index >= count ) {
145            [anArray release];
146            anArray = nil;
147            index = 0;
148            count = 0;
149        }
150    }
151    return obj;
152}
153
154- (NSArray *) allObjects
155{
156    if ( (count <= 0 || index >= count) && peekObj == nil ) return nil;
157    AMutableArray *theArray = [AMutableArray arrayWithCapacity:count];
158    if (peekObj) {
159        [theArray addObject:peekObj];
160        peekObj = nil;
161    }
162    for (int i = index; i < count; i++) {
163        [theArray addObject:[anArray objectAtIndex:i]];
164    }
165    return [NSArray arrayWithArray:(NSArray *)theArray];
166}
167
168- (void) removeObjectAtIndex:(NSInteger)idx
169{
170    @throw [UnsupportedOperationException newException:@"Cant remove object from ArrayIterator"];
171}
172
173- (NSInteger) count
174{
175    return (index - count);
176}
177
178- (void) setCount:(NSInteger)cnt
179{
180    count = cnt;
181}
182
183@end
184