xref: /aosp_15_r20/external/antlr/runtime/ObjC/Framework/HashMap.m (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot//
2*16467b97STreehugger Robot//  HashMap.m
3*16467b97STreehugger Robot//  ANTLR
4*16467b97STreehugger Robot//
5*16467b97STreehugger Robot// Copyright (c) 2010 Alan Condit
6*16467b97STreehugger Robot// All rights reserved.
7*16467b97STreehugger Robot//
8*16467b97STreehugger Robot// Redistribution and use in source and binary forms, with or without
9*16467b97STreehugger Robot// modification, are permitted provided that the following conditions
10*16467b97STreehugger Robot// are met:
11*16467b97STreehugger Robot// 1. Redistributions of source code must retain the above copyright
12*16467b97STreehugger Robot//    notice, this list of conditions and the following disclaimer.
13*16467b97STreehugger Robot// 2. Redistributions in binary form must reproduce the above copyright
14*16467b97STreehugger Robot//    notice, this list of conditions and the following disclaimer in the
15*16467b97STreehugger Robot//    documentation and/or other materials provided with the distribution.
16*16467b97STreehugger Robot// 3. The name of the author may not be used to endorse or promote products
17*16467b97STreehugger Robot//    derived from this software without specific prior written permission.
18*16467b97STreehugger Robot//
19*16467b97STreehugger Robot// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20*16467b97STreehugger Robot// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21*16467b97STreehugger Robot// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22*16467b97STreehugger Robot// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23*16467b97STreehugger Robot// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24*16467b97STreehugger Robot// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25*16467b97STreehugger Robot// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26*16467b97STreehugger Robot// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27*16467b97STreehugger Robot// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28*16467b97STreehugger Robot// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*16467b97STreehugger Robot
30*16467b97STreehugger Robot#define SUCCESS (0)
31*16467b97STreehugger Robot#define FAILURE (-1)
32*16467b97STreehugger Robot
33*16467b97STreehugger Robot#import "HashMap.h"
34*16467b97STreehugger Robot#import "AMutableArray.h"
35*16467b97STreehugger Robot#import "RuntimeException.h"
36*16467b97STreehugger Robot
37*16467b97STreehugger Robotextern NSInteger max(NSInteger a, NSInteger b);
38*16467b97STreehugger Robot
39*16467b97STreehugger Robotstatic NSInteger itIndex;
40*16467b97STreehugger Robot
41*16467b97STreehugger Robot@implementation HMEntry
42*16467b97STreehugger Robot
43*16467b97STreehugger Robot@synthesize next;
44*16467b97STreehugger Robot@synthesize hash;
45*16467b97STreehugger Robot@synthesize key;
46*16467b97STreehugger Robot@synthesize value;
47*16467b97STreehugger Robot
48*16467b97STreehugger Robot/**
49*16467b97STreehugger Robot * Creates new entry.
50*16467b97STreehugger Robot */
51*16467b97STreehugger Robot+ (HMEntry *)newEntry:(NSInteger)h key:(NSString *)k value:(id)v next:(HMEntry *) n
52*16467b97STreehugger Robot{
53*16467b97STreehugger Robot    return [[HMEntry alloc] init:h key:k value:v next:n];
54*16467b97STreehugger Robot}
55*16467b97STreehugger Robot
56*16467b97STreehugger Robot- (id) init:(NSInteger)h key:(NSString *)k value:(id)v next:(HMEntry *)n
57*16467b97STreehugger Robot{
58*16467b97STreehugger Robot    self = [super init];
59*16467b97STreehugger Robot    if ( self ) {
60*16467b97STreehugger Robot        value = v;
61*16467b97STreehugger Robot        next = n;
62*16467b97STreehugger Robot        key = k;
63*16467b97STreehugger Robot        hash = h;
64*16467b97STreehugger Robot    }
65*16467b97STreehugger Robot    return self;
66*16467b97STreehugger Robot}
67*16467b97STreehugger Robot
68*16467b97STreehugger Robot- (void) setValue:(id)newValue
69*16467b97STreehugger Robot{
70*16467b97STreehugger Robot    value = newValue;
71*16467b97STreehugger Robot    //    return oldValue;
72*16467b97STreehugger Robot}
73*16467b97STreehugger Robot
74*16467b97STreehugger Robot- (BOOL) isEqualTo:(id)o
75*16467b97STreehugger Robot{
76*16467b97STreehugger Robot    /*
77*16467b97STreehugger Robot     if (!([o conformsToProtocol:@protocol(HMEntry)]))
78*16467b97STreehugger Robot     return NO;
79*16467b97STreehugger Robot     */
80*16467b97STreehugger Robot    HMEntry *e = (HMEntry *)o;
81*16467b97STreehugger Robot    NSString *k1 = [self key];
82*16467b97STreehugger Robot    NSString *k2 = [e key];
83*16467b97STreehugger Robot    if (k1 == k2 || (k1 != nil && [k1 isEqualTo:k2])) {
84*16467b97STreehugger Robot        id v1 = [self value];
85*16467b97STreehugger Robot        id v2 = [e value];
86*16467b97STreehugger Robot        if (v1 == v2 || (v1 != nil && [v1 isEqualTo:v2]))
87*16467b97STreehugger Robot            return YES;
88*16467b97STreehugger Robot    }
89*16467b97STreehugger Robot    return NO;
90*16467b97STreehugger Robot}
91*16467b97STreehugger Robot
92*16467b97STreehugger Robot- (NSInteger) hashCode
93*16467b97STreehugger Robot{
94*16467b97STreehugger Robot    return (key == nil ? 0 : [key hash]) ^ (value == nil ? 0 : [value hash]);
95*16467b97STreehugger Robot}
96*16467b97STreehugger Robot
97*16467b97STreehugger Robot- (NSString *) description
98*16467b97STreehugger Robot{
99*16467b97STreehugger Robot    return [NSString stringWithFormat:@"%@ = %@",[key description], [value description]];
100*16467b97STreehugger Robot}
101*16467b97STreehugger Robot
102*16467b97STreehugger Robot
103*16467b97STreehugger Robot/**
104*16467b97STreehugger Robot * This method is invoked whenever the value in an entry is
105*16467b97STreehugger Robot * overwritten by an invocation of put(k,v) for a key k that's already
106*16467b97STreehugger Robot * in the HashMap.
107*16467b97STreehugger Robot */
108*16467b97STreehugger Robot- (void) recordAccess:(HashMap *)m
109*16467b97STreehugger Robot{
110*16467b97STreehugger Robot}
111*16467b97STreehugger Robot
112*16467b97STreehugger Robot
113*16467b97STreehugger Robot/**
114*16467b97STreehugger Robot * This method is invoked whenever the entry is
115*16467b97STreehugger Robot * removed from the table.
116*16467b97STreehugger Robot */
117*16467b97STreehugger Robot- (void) recordRemoval:(HashMap *)m
118*16467b97STreehugger Robot{
119*16467b97STreehugger Robot}
120*16467b97STreehugger Robot
121*16467b97STreehugger Robot- (void) dealloc
122*16467b97STreehugger Robot{
123*16467b97STreehugger Robot    [key release];
124*16467b97STreehugger Robot    [value release];
125*16467b97STreehugger Robot    [next release];
126*16467b97STreehugger Robot    [super dealloc];
127*16467b97STreehugger Robot}
128*16467b97STreehugger Robot
129*16467b97STreehugger Robot@end
130*16467b97STreehugger Robot
131*16467b97STreehugger Robot@implementation HashIterator
132*16467b97STreehugger Robot
133*16467b97STreehugger Robot+ (HashIterator *)newIterator:(HashMap *)aHM
134*16467b97STreehugger Robot{
135*16467b97STreehugger Robot    return [[HashIterator alloc] init:aHM];
136*16467b97STreehugger Robot}
137*16467b97STreehugger Robot
138*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
139*16467b97STreehugger Robot{
140*16467b97STreehugger Robot    self = [super init];
141*16467b97STreehugger Robot    if ( self ) {
142*16467b97STreehugger Robot        hm = aHM;
143*16467b97STreehugger Robot        expectedModCount = hm.modCount;
144*16467b97STreehugger Robot        if (count > 0) {
145*16467b97STreehugger Robot            while ( idx < [hm.buffer length] ) {
146*16467b97STreehugger Robot                next = (HMEntry *)hm.ptrBuffer[idx++];
147*16467b97STreehugger Robot                if ( next == nil )
148*16467b97STreehugger Robot                    break;
149*16467b97STreehugger Robot            }
150*16467b97STreehugger Robot        }
151*16467b97STreehugger Robot    }
152*16467b97STreehugger Robot    return self;
153*16467b97STreehugger Robot}
154*16467b97STreehugger Robot
155*16467b97STreehugger Robot- (BOOL) hasNext
156*16467b97STreehugger Robot{
157*16467b97STreehugger Robot    return next != nil;
158*16467b97STreehugger Robot}
159*16467b97STreehugger Robot
160*16467b97STreehugger Robot- (HMEntry *) next
161*16467b97STreehugger Robot{
162*16467b97STreehugger Robot//    if (hm.modCount != expectedModCount)
163*16467b97STreehugger Robot//        @throw [[ConcurrentModificationException alloc] init];
164*16467b97STreehugger Robot    HMEntry *e = next;
165*16467b97STreehugger Robot    if (e == nil)
166*16467b97STreehugger Robot        @throw [[NoSuchElementException alloc] init];
167*16467b97STreehugger Robot    if ((next = e.next) == nil) {
168*16467b97STreehugger Robot        while ( idx < [hm.buffer length] ) {
169*16467b97STreehugger Robot            next = [anArray objectAtIndex:idx++];
170*16467b97STreehugger Robot            if ( next == nil )
171*16467b97STreehugger Robot                break;
172*16467b97STreehugger Robot        }
173*16467b97STreehugger Robot    }
174*16467b97STreehugger Robot    current = e;
175*16467b97STreehugger Robot    return e;
176*16467b97STreehugger Robot}
177*16467b97STreehugger Robot
178*16467b97STreehugger Robot- (void) remove
179*16467b97STreehugger Robot{
180*16467b97STreehugger Robot    if (current == nil)
181*16467b97STreehugger Robot        @throw [[IllegalStateException alloc] init];
182*16467b97STreehugger Robot//    if (modCount != expectedModCount)
183*16467b97STreehugger Robot//        @throw [[ConcurrentModificationException alloc] init];
184*16467b97STreehugger Robot    NSString *k = current.key;
185*16467b97STreehugger Robot    current = nil;
186*16467b97STreehugger Robot    [hm removeEntryForKey:k];
187*16467b97STreehugger Robot    expectedModCount = hm.modCount;
188*16467b97STreehugger Robot}
189*16467b97STreehugger Robot
190*16467b97STreehugger Robot- (void) dealloc
191*16467b97STreehugger Robot{
192*16467b97STreehugger Robot    [next release];
193*16467b97STreehugger Robot    [current release];
194*16467b97STreehugger Robot    [super dealloc];
195*16467b97STreehugger Robot}
196*16467b97STreehugger Robot
197*16467b97STreehugger Robot@end
198*16467b97STreehugger Robot
199*16467b97STreehugger Robot@implementation HMValueIterator
200*16467b97STreehugger Robot
201*16467b97STreehugger Robot+ (HMValueIterator *)newIterator:(HashMap *)aHM
202*16467b97STreehugger Robot{
203*16467b97STreehugger Robot    return [[HMValueIterator alloc] init:aHM];
204*16467b97STreehugger Robot}
205*16467b97STreehugger Robot
206*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
207*16467b97STreehugger Robot{
208*16467b97STreehugger Robot    self = [super init:aHM];
209*16467b97STreehugger Robot    if ( self ) {
210*16467b97STreehugger Robot    }
211*16467b97STreehugger Robot    return self;
212*16467b97STreehugger Robot}
213*16467b97STreehugger Robot
214*16467b97STreehugger Robot- (id) next
215*16467b97STreehugger Robot{
216*16467b97STreehugger Robot    return [super next].value;
217*16467b97STreehugger Robot}
218*16467b97STreehugger Robot
219*16467b97STreehugger Robot@end
220*16467b97STreehugger Robot
221*16467b97STreehugger Robot@implementation HMKeyIterator
222*16467b97STreehugger Robot
223*16467b97STreehugger Robot+ (HMKeyIterator *)newIterator:(HashMap *)aHM
224*16467b97STreehugger Robot{
225*16467b97STreehugger Robot    return [[HMKeyIterator alloc] init:aHM];
226*16467b97STreehugger Robot}
227*16467b97STreehugger Robot
228*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
229*16467b97STreehugger Robot{
230*16467b97STreehugger Robot    self = [super init:aHM];
231*16467b97STreehugger Robot    if ( self ) {
232*16467b97STreehugger Robot    }
233*16467b97STreehugger Robot    return self;
234*16467b97STreehugger Robot}
235*16467b97STreehugger Robot
236*16467b97STreehugger Robot- (NSString *) next
237*16467b97STreehugger Robot{
238*16467b97STreehugger Robot    return [super next].key;
239*16467b97STreehugger Robot}
240*16467b97STreehugger Robot
241*16467b97STreehugger Robot@end
242*16467b97STreehugger Robot
243*16467b97STreehugger Robot@implementation HMEntryIterator
244*16467b97STreehugger Robot
245*16467b97STreehugger Robot+ (HMEntryIterator *)newIterator:(HashMap *)aHM
246*16467b97STreehugger Robot{
247*16467b97STreehugger Robot    return [[HMEntryIterator alloc] init:aHM];
248*16467b97STreehugger Robot}
249*16467b97STreehugger Robot
250*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
251*16467b97STreehugger Robot{
252*16467b97STreehugger Robot    self = [super init:aHM];
253*16467b97STreehugger Robot    if ( self ) {
254*16467b97STreehugger Robot    }
255*16467b97STreehugger Robot    return self;
256*16467b97STreehugger Robot}
257*16467b97STreehugger Robot
258*16467b97STreehugger Robot- (HMEntry *) next
259*16467b97STreehugger Robot{
260*16467b97STreehugger Robot    return [super next];
261*16467b97STreehugger Robot}
262*16467b97STreehugger Robot
263*16467b97STreehugger Robot@end
264*16467b97STreehugger Robot
265*16467b97STreehugger Robot@implementation HMKeySet
266*16467b97STreehugger Robot
267*16467b97STreehugger Robot@synthesize hm;
268*16467b97STreehugger Robot@synthesize anArray;
269*16467b97STreehugger Robot
270*16467b97STreehugger Robot+ (HMKeySet *)newKeySet:(HashMap *)aHM
271*16467b97STreehugger Robot{
272*16467b97STreehugger Robot    return [[HMKeySet alloc] init:(HashMap *)aHM];
273*16467b97STreehugger Robot}
274*16467b97STreehugger Robot
275*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
276*16467b97STreehugger Robot{
277*16467b97STreehugger Robot    self = [super init];
278*16467b97STreehugger Robot    if ( self ) {
279*16467b97STreehugger Robot        hm = aHM;
280*16467b97STreehugger Robot        anArray = [[AMutableArray arrayWithCapacity:16] retain];
281*16467b97STreehugger Robot        HMKeyIterator *it = [hm newKeyIterator];
282*16467b97STreehugger Robot        while ( [it hasNext] ) {
283*16467b97STreehugger Robot            NSString *aKey = [it next];
284*16467b97STreehugger Robot            [anArray addObject:aKey];
285*16467b97STreehugger Robot        }
286*16467b97STreehugger Robot    }
287*16467b97STreehugger Robot    return self;
288*16467b97STreehugger Robot}
289*16467b97STreehugger Robot
290*16467b97STreehugger Robot- (HashIterator *) iterator
291*16467b97STreehugger Robot{
292*16467b97STreehugger Robot    return [HMKeyIterator newIterator:hm];
293*16467b97STreehugger Robot}
294*16467b97STreehugger Robot
295*16467b97STreehugger Robot- (NSUInteger) count
296*16467b97STreehugger Robot{
297*16467b97STreehugger Robot    return hm.count;
298*16467b97STreehugger Robot}
299*16467b97STreehugger Robot
300*16467b97STreehugger Robot- (BOOL) contains:(id)o
301*16467b97STreehugger Robot{
302*16467b97STreehugger Robot    return [hm containsKey:o];
303*16467b97STreehugger Robot}
304*16467b97STreehugger Robot
305*16467b97STreehugger Robot- (BOOL) remove:(id)o
306*16467b97STreehugger Robot{
307*16467b97STreehugger Robot    return [hm removeEntryForKey:o] != nil;
308*16467b97STreehugger Robot}
309*16467b97STreehugger Robot
310*16467b97STreehugger Robot- (void) clear {
311*16467b97STreehugger Robot    [hm clear];
312*16467b97STreehugger Robot}
313*16467b97STreehugger Robot
314*16467b97STreehugger Robot- (AMutableArray *)toArray
315*16467b97STreehugger Robot{
316*16467b97STreehugger Robot    return anArray;
317*16467b97STreehugger Robot}
318*16467b97STreehugger Robot
319*16467b97STreehugger Robot@end
320*16467b97STreehugger Robot
321*16467b97STreehugger Robot@implementation Values
322*16467b97STreehugger Robot
323*16467b97STreehugger Robot@synthesize hm;
324*16467b97STreehugger Robot@synthesize anArray;
325*16467b97STreehugger Robot
326*16467b97STreehugger Robot+ (Values *)newValueSet:(HashMap *)aHM
327*16467b97STreehugger Robot{
328*16467b97STreehugger Robot    return [[Values alloc] init:aHM];
329*16467b97STreehugger Robot}
330*16467b97STreehugger Robot
331*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
332*16467b97STreehugger Robot{
333*16467b97STreehugger Robot    self = [super init];
334*16467b97STreehugger Robot    if ( self ) {
335*16467b97STreehugger Robot        hm = aHM;
336*16467b97STreehugger Robot        anArray = [[AMutableArray arrayWithCapacity:16] retain];
337*16467b97STreehugger Robot        HMValueIterator *it = [hm newValueIterator];
338*16467b97STreehugger Robot        while ( [it hasNext] ) {
339*16467b97STreehugger Robot            id aValue = [it next];
340*16467b97STreehugger Robot            [anArray addObject:aValue];
341*16467b97STreehugger Robot        }
342*16467b97STreehugger Robot    }
343*16467b97STreehugger Robot    return self;
344*16467b97STreehugger Robot}
345*16467b97STreehugger Robot
346*16467b97STreehugger Robot- (ArrayIterator *) iterator
347*16467b97STreehugger Robot{
348*16467b97STreehugger Robot    return [HMValueIterator newIterator:hm];
349*16467b97STreehugger Robot}
350*16467b97STreehugger Robot
351*16467b97STreehugger Robot- (NSUInteger) count
352*16467b97STreehugger Robot{
353*16467b97STreehugger Robot    return hm.count;
354*16467b97STreehugger Robot}
355*16467b97STreehugger Robot
356*16467b97STreehugger Robot- (BOOL) contains:(id)o
357*16467b97STreehugger Robot{
358*16467b97STreehugger Robot    return [hm containsValue:o];
359*16467b97STreehugger Robot}
360*16467b97STreehugger Robot
361*16467b97STreehugger Robot- (void) clear {
362*16467b97STreehugger Robot    [hm clear];
363*16467b97STreehugger Robot}
364*16467b97STreehugger Robot
365*16467b97STreehugger Robot- (AMutableArray *)toArray
366*16467b97STreehugger Robot{
367*16467b97STreehugger Robot    return anArray;
368*16467b97STreehugger Robot}
369*16467b97STreehugger Robot
370*16467b97STreehugger Robot@end
371*16467b97STreehugger Robot
372*16467b97STreehugger Robot@implementation HMEntrySet
373*16467b97STreehugger Robot
374*16467b97STreehugger Robot@synthesize hm;
375*16467b97STreehugger Robot@synthesize anArray;
376*16467b97STreehugger Robot
377*16467b97STreehugger Robot+ (HMEntrySet *)newEntrySet:(HashMap *)aHM
378*16467b97STreehugger Robot{
379*16467b97STreehugger Robot    return [[HMEntrySet alloc] init:aHM];
380*16467b97STreehugger Robot}
381*16467b97STreehugger Robot
382*16467b97STreehugger Robot- (id) init:(HashMap *)aHM
383*16467b97STreehugger Robot{
384*16467b97STreehugger Robot    self = [super init];
385*16467b97STreehugger Robot    if ( self ) {
386*16467b97STreehugger Robot        hm = aHM;
387*16467b97STreehugger Robot        anArray = [[AMutableArray arrayWithCapacity:16] retain];
388*16467b97STreehugger Robot        HMEntryIterator *it = [hm newEntryIterator];
389*16467b97STreehugger Robot        while ( [it hasNext] ) {
390*16467b97STreehugger Robot            HMEntry *entry = [it next];
391*16467b97STreehugger Robot            [anArray addObject:entry];
392*16467b97STreehugger Robot        }
393*16467b97STreehugger Robot    }
394*16467b97STreehugger Robot    return self;
395*16467b97STreehugger Robot}
396*16467b97STreehugger Robot
397*16467b97STreehugger Robot- (HashIterator *) iterator
398*16467b97STreehugger Robot{
399*16467b97STreehugger Robot    return [HMEntryIterator newIterator:hm];
400*16467b97STreehugger Robot}
401*16467b97STreehugger Robot
402*16467b97STreehugger Robot- (BOOL) contains:(id)o
403*16467b97STreehugger Robot{
404*16467b97STreehugger Robot/*
405*16467b97STreehugger Robot    if (!([o conformsToProtocol:@protocol(HMEntry)]))
406*16467b97STreehugger Robot        return NO;
407*16467b97STreehugger Robot */
408*16467b97STreehugger Robot    HMEntry *e = (HMEntry *)o;
409*16467b97STreehugger Robot    HMEntry *candidate = [hm getEntry:e.key];
410*16467b97STreehugger Robot    return candidate != nil && [candidate isEqualTo:e];
411*16467b97STreehugger Robot}
412*16467b97STreehugger Robot
413*16467b97STreehugger Robot- (BOOL) remove:(id)o
414*16467b97STreehugger Robot{
415*16467b97STreehugger Robot    return [hm removeMapping:o] != nil;
416*16467b97STreehugger Robot}
417*16467b97STreehugger Robot
418*16467b97STreehugger Robot- (NSUInteger) count
419*16467b97STreehugger Robot{
420*16467b97STreehugger Robot    return hm.count;
421*16467b97STreehugger Robot}
422*16467b97STreehugger Robot
423*16467b97STreehugger Robot- (void) clear
424*16467b97STreehugger Robot{
425*16467b97STreehugger Robot    [hm clear];
426*16467b97STreehugger Robot}
427*16467b97STreehugger Robot
428*16467b97STreehugger Robot- (NSArray *)toArray
429*16467b97STreehugger Robot{
430*16467b97STreehugger Robot    return anArray;
431*16467b97STreehugger Robot}
432*16467b97STreehugger Robot
433*16467b97STreehugger Robot@end
434*16467b97STreehugger Robot
435*16467b97STreehugger Robot/**
436*16467b97STreehugger Robot * The default initial capacity - MUST be a power of two.
437*16467b97STreehugger Robot */
438*16467b97STreehugger RobotNSInteger const DEFAULT_INITIAL_CAPACITY = 16;
439*16467b97STreehugger Robot
440*16467b97STreehugger Robot/**
441*16467b97STreehugger Robot * The maximum capacity, used if a higher value is implicitly specified
442*16467b97STreehugger Robot * by either of the constructors with arguments.
443*16467b97STreehugger Robot * MUST be a power of two <= 1<<30.
444*16467b97STreehugger Robot */
445*16467b97STreehugger RobotNSInteger const MAXIMUM_CAPACITY = 1 << 30;
446*16467b97STreehugger Robot
447*16467b97STreehugger Robot/**
448*16467b97STreehugger Robot * The load factor used when none specified in constructor.
449*16467b97STreehugger Robot */
450*16467b97STreehugger Robotfloat const DEFAULT_LOAD_FACTOR = 0.75f;
451*16467b97STreehugger Robot//long const serialVersionUID = 362498820763181265L;
452*16467b97STreehugger Robot
453*16467b97STreehugger Robot/*
454*16467b97STreehugger Robot * Start of HashMap
455*16467b97STreehugger Robot */
456*16467b97STreehugger Robot@implementation HashMap
457*16467b97STreehugger Robot
458*16467b97STreehugger Robot@synthesize Scope;
459*16467b97STreehugger Robot@synthesize LastHash;
460*16467b97STreehugger Robot@synthesize BuffSize;
461*16467b97STreehugger Robot@synthesize Capacity;
462*16467b97STreehugger Robot@synthesize count;
463*16467b97STreehugger Robot@synthesize ptr;
464*16467b97STreehugger Robot@synthesize ptrBuffer;
465*16467b97STreehugger Robot@synthesize buffer;
466*16467b97STreehugger Robot@synthesize threshold;
467*16467b97STreehugger Robot@synthesize loadFactor;
468*16467b97STreehugger Robot@synthesize modCount;
469*16467b97STreehugger Robot@synthesize entrySet;
470*16467b97STreehugger Robot@synthesize empty;
471*16467b97STreehugger Robot@synthesize keySet;
472*16467b97STreehugger Robot@synthesize values;
473*16467b97STreehugger Robot
474*16467b97STreehugger Robot+(id)newHashMap
475*16467b97STreehugger Robot{
476*16467b97STreehugger Robot    return [[HashMap alloc] init];
477*16467b97STreehugger Robot}
478*16467b97STreehugger Robot
479*16467b97STreehugger Robot+(id)newHashMapWithLen:(NSInteger)aBuffSize
480*16467b97STreehugger Robot{
481*16467b97STreehugger Robot    return [[HashMap alloc] initWithLen:aBuffSize];
482*16467b97STreehugger Robot}
483*16467b97STreehugger Robot
484*16467b97STreehugger Robot+ (id) newHashMap:(NSInteger)initialCapacity
485*16467b97STreehugger Robot{
486*16467b97STreehugger Robot    return [[HashMap alloc] init:initialCapacity loadFactor:DEFAULT_LOAD_FACTOR];
487*16467b97STreehugger Robot}
488*16467b97STreehugger Robot
489*16467b97STreehugger Robot+ (id) newHashMap:(NSInteger)initialCapacity loadFactor:(float)aLoadFactor
490*16467b97STreehugger Robot{
491*16467b97STreehugger Robot    return [[HashMap alloc] init:initialCapacity loadFactor:aLoadFactor];
492*16467b97STreehugger Robot}
493*16467b97STreehugger Robot
494*16467b97STreehugger Robot/**
495*16467b97STreehugger Robot * Constructs an empty <tt>HashMap</tt> with the default initial capacity
496*16467b97STreehugger Robot * (16) and the default load factor (0.75).
497*16467b97STreehugger Robot */
498*16467b97STreehugger Robot- (id) init
499*16467b97STreehugger Robot{
500*16467b97STreehugger Robot    NSInteger idx;
501*16467b97STreehugger Robot
502*16467b97STreehugger Robot    self = [super init];
503*16467b97STreehugger Robot    if ( self ) {
504*16467b97STreehugger Robot        entrySet = nil;
505*16467b97STreehugger Robot        loadFactor = DEFAULT_LOAD_FACTOR;
506*16467b97STreehugger Robot        threshold = (NSInteger)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
507*16467b97STreehugger Robot        count = 0;
508*16467b97STreehugger Robot        BuffSize = HASHSIZE;
509*16467b97STreehugger Robot        NSInteger capacity = 1;
510*16467b97STreehugger Robot
511*16467b97STreehugger Robot        while (capacity < BuffSize)
512*16467b97STreehugger Robot            capacity <<= 1;
513*16467b97STreehugger Robot
514*16467b97STreehugger Robot        BuffSize = capacity;
515*16467b97STreehugger Robot        fNext = nil;
516*16467b97STreehugger Robot        Scope = 0;
517*16467b97STreehugger Robot        ptr = 0;
518*16467b97STreehugger Robot        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize * sizeof(id)] retain];
519*16467b97STreehugger Robot        ptrBuffer = (MapElement **) [buffer mutableBytes];
520*16467b97STreehugger Robot        if ( fNext != nil ) {
521*16467b97STreehugger Robot            Scope = ((HashMap *)fNext)->Scope+1;
522*16467b97STreehugger Robot            for( idx = 0; idx < BuffSize; idx++ ) {
523*16467b97STreehugger Robot                ptrBuffer[idx] = ((HashMap *)fNext)->ptrBuffer[idx];
524*16467b97STreehugger Robot            }
525*16467b97STreehugger Robot        }
526*16467b97STreehugger Robot        mode = 0;
527*16467b97STreehugger Robot        keySet = nil;
528*16467b97STreehugger Robot        values = nil;
529*16467b97STreehugger Robot   }
530*16467b97STreehugger Robot    return self;
531*16467b97STreehugger Robot}
532*16467b97STreehugger Robot
533*16467b97STreehugger Robot-(id)initWithLen:(NSInteger)aBuffSize
534*16467b97STreehugger Robot{
535*16467b97STreehugger Robot    NSInteger idx;
536*16467b97STreehugger Robot
537*16467b97STreehugger Robot    self = [super init];
538*16467b97STreehugger Robot    if ( self ) {
539*16467b97STreehugger Robot        fNext = nil;
540*16467b97STreehugger Robot        entrySet = nil;
541*16467b97STreehugger Robot        loadFactor = DEFAULT_LOAD_FACTOR;
542*16467b97STreehugger Robot        threshold = (NSInteger)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
543*16467b97STreehugger Robot        count = 0;
544*16467b97STreehugger Robot        BuffSize = aBuffSize;
545*16467b97STreehugger Robot        NSInteger capacity = 1;
546*16467b97STreehugger Robot
547*16467b97STreehugger Robot        while (capacity < BuffSize)
548*16467b97STreehugger Robot            capacity <<= 1;
549*16467b97STreehugger Robot
550*16467b97STreehugger Robot        BuffSize = capacity * sizeof(id);
551*16467b97STreehugger Robot        Capacity = capacity;
552*16467b97STreehugger Robot        Scope = 0;
553*16467b97STreehugger Robot        ptr = 0;
554*16467b97STreehugger Robot        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize] retain];
555*16467b97STreehugger Robot        ptrBuffer = (MapElement **) [buffer mutableBytes];
556*16467b97STreehugger Robot        if ( fNext != nil ) {
557*16467b97STreehugger Robot            Scope = ((HashMap *)fNext)->Scope+1;
558*16467b97STreehugger Robot            for( idx = 0; idx < Capacity; idx++ ) {
559*16467b97STreehugger Robot                ptrBuffer[idx] = ((HashMap *)fNext)->ptrBuffer[idx];
560*16467b97STreehugger Robot            }
561*16467b97STreehugger Robot        }
562*16467b97STreehugger Robot        mode = 0;
563*16467b97STreehugger Robot        keySet = nil;
564*16467b97STreehugger Robot        values = nil;
565*16467b97STreehugger Robot    }
566*16467b97STreehugger Robot    return( self );
567*16467b97STreehugger Robot}
568*16467b97STreehugger Robot
569*16467b97STreehugger Robot/**
570*16467b97STreehugger Robot * Constructs an empty <tt>HashMap</tt> with the specified initial
571*16467b97STreehugger Robot * capacity and load factor.
572*16467b97STreehugger Robot *
573*16467b97STreehugger Robot * @param  initialCapacity the initial capacity
574*16467b97STreehugger Robot * @param  loadFactor      the load factor
575*16467b97STreehugger Robot * @throws IllegalArgumentException if the initial capacity is negative
576*16467b97STreehugger Robot * or the load factor is nonpositive
577*16467b97STreehugger Robot */
578*16467b97STreehugger Robot- (id) init:(NSInteger)initialCapacity loadFactor:(float)aLoadFactor
579*16467b97STreehugger Robot{
580*16467b97STreehugger Robot    self = [super init];
581*16467b97STreehugger Robot    if ( self ) {
582*16467b97STreehugger Robot        entrySet = nil;
583*16467b97STreehugger Robot        if (initialCapacity < 0)
584*16467b97STreehugger Robot            @throw [[IllegalArgumentException alloc] init:[NSString stringWithFormat:@"Illegal initial capacity: %d", initialCapacity]];
585*16467b97STreehugger Robot        if (initialCapacity > MAXIMUM_CAPACITY)
586*16467b97STreehugger Robot            initialCapacity = MAXIMUM_CAPACITY;
587*16467b97STreehugger Robot        if (aLoadFactor <= 0 /* || [Float isNaN:loadFactor] */)
588*16467b97STreehugger Robot            @throw [[IllegalArgumentException alloc] init:[NSString stringWithFormat:@"Illegal load factor:%d ", aLoadFactor]];
589*16467b97STreehugger Robot        NSInteger capacity = 1;
590*16467b97STreehugger Robot
591*16467b97STreehugger Robot        while (capacity < initialCapacity)
592*16467b97STreehugger Robot            capacity <<= 1;
593*16467b97STreehugger Robot
594*16467b97STreehugger Robot        count = 0;
595*16467b97STreehugger Robot        BuffSize = capacity * sizeof(id);
596*16467b97STreehugger Robot        Capacity = capacity;
597*16467b97STreehugger Robot        loadFactor = aLoadFactor;
598*16467b97STreehugger Robot        threshold = (NSInteger)(capacity * loadFactor);
599*16467b97STreehugger Robot//        ptrBuffer = [AMutableArray arrayWithCapacity:initialCapacity];
600*16467b97STreehugger Robot//        [self init];
601*16467b97STreehugger Robot        keySet = nil;
602*16467b97STreehugger Robot        values = nil;
603*16467b97STreehugger Robot        Scope = 0;
604*16467b97STreehugger Robot        ptr = 0;
605*16467b97STreehugger Robot        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize] retain];
606*16467b97STreehugger Robot        ptrBuffer = (MapElement **) [buffer mutableBytes];
607*16467b97STreehugger Robot    }
608*16467b97STreehugger Robot    return self;
609*16467b97STreehugger Robot}
610*16467b97STreehugger Robot
611*16467b97STreehugger Robot
612*16467b97STreehugger Robot/**
613*16467b97STreehugger Robot * Constructs an empty <tt>HashMap</tt> with the specified initial
614*16467b97STreehugger Robot * capacity and the default load factor (0.75).
615*16467b97STreehugger Robot *
616*16467b97STreehugger Robot * @param  initialCapacity the initial capacity.
617*16467b97STreehugger Robot * @throws IllegalArgumentException if the initial capacity is negative.
618*16467b97STreehugger Robot */
619*16467b97STreehugger Robot- (id) init:(NSInteger)anInitialCapacity
620*16467b97STreehugger Robot{
621*16467b97STreehugger Robot    self = [super init];
622*16467b97STreehugger Robot    if ( self ) {
623*16467b97STreehugger Robot        entrySet = nil;
624*16467b97STreehugger Robot        NSInteger initialCapacity = anInitialCapacity;
625*16467b97STreehugger Robot        if (initialCapacity > MAXIMUM_CAPACITY)
626*16467b97STreehugger Robot            initialCapacity = MAXIMUM_CAPACITY;
627*16467b97STreehugger Robot        NSInteger capacity = 1;
628*16467b97STreehugger Robot        while (capacity < initialCapacity)
629*16467b97STreehugger Robot            capacity <<= 1;
630*16467b97STreehugger Robot        count = 0;
631*16467b97STreehugger Robot        BuffSize = capacity;
632*16467b97STreehugger Robot        loadFactor = DEFAULT_LOAD_FACTOR;
633*16467b97STreehugger Robot        threshold = (NSInteger)(capacity * loadFactor);
634*16467b97STreehugger Robot        keySet = nil;
635*16467b97STreehugger Robot        values = nil;
636*16467b97STreehugger Robot        Scope = 0;
637*16467b97STreehugger Robot        ptr = 0;
638*16467b97STreehugger Robot        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize] retain];
639*16467b97STreehugger Robot        ptrBuffer = (MapElement **) [buffer mutableBytes];
640*16467b97STreehugger Robot    }
641*16467b97STreehugger Robot    return self;
642*16467b97STreehugger Robot}
643*16467b97STreehugger Robot
644*16467b97STreehugger Robot/**
645*16467b97STreehugger Robot * Constructs a new <tt>HashMap</tt> with the same mappings as the
646*16467b97STreehugger Robot * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
647*16467b97STreehugger Robot * default load factor (0.75) and an initial capacity sufficient to
648*16467b97STreehugger Robot * hold the mappings in the specified <tt>Map</tt>.
649*16467b97STreehugger Robot *
650*16467b97STreehugger Robot * @param   m the map whose mappings are to be placed in this map
651*16467b97STreehugger Robot * @throws  NullPointerException if the specified map is null
652*16467b97STreehugger Robot */
653*16467b97STreehugger Robot- (id) initWithM:(HashMap *)m
654*16467b97STreehugger Robot{
655*16467b97STreehugger Robot    self = [super init];
656*16467b97STreehugger Robot    self = [self init:(NSInteger)max((([m count] / DEFAULT_LOAD_FACTOR) + 1), DEFAULT_INITIAL_CAPACITY) loadFactor:DEFAULT_LOAD_FACTOR];
657*16467b97STreehugger Robot    if ( self ) {
658*16467b97STreehugger Robot        entrySet = nil;
659*16467b97STreehugger Robot        NSInteger initialCapacity = max((([m count] / DEFAULT_LOAD_FACTOR) + 1), DEFAULT_INITIAL_CAPACITY);
660*16467b97STreehugger Robot        if (initialCapacity > MAXIMUM_CAPACITY)
661*16467b97STreehugger Robot            initialCapacity = MAXIMUM_CAPACITY;
662*16467b97STreehugger Robot        NSInteger capacity = 1;
663*16467b97STreehugger Robot        while (capacity < initialCapacity)
664*16467b97STreehugger Robot            capacity <<= 1;
665*16467b97STreehugger Robot        count = 0;
666*16467b97STreehugger Robot        BuffSize = capacity * sizeof(id);
667*16467b97STreehugger Robot        Capacity = capacity;
668*16467b97STreehugger Robot        loadFactor = DEFAULT_LOAD_FACTOR;
669*16467b97STreehugger Robot        threshold = (NSInteger)(capacity * loadFactor);
670*16467b97STreehugger Robot        keySet = nil;
671*16467b97STreehugger Robot        values = nil;
672*16467b97STreehugger Robot        Scope = 0;
673*16467b97STreehugger Robot        ptr = 0;
674*16467b97STreehugger Robot        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize] retain];
675*16467b97STreehugger Robot        ptrBuffer = (MapElement **) [buffer mutableBytes];
676*16467b97STreehugger Robot        [self putAllForCreate:m];
677*16467b97STreehugger Robot    }
678*16467b97STreehugger Robot    return self;
679*16467b97STreehugger Robot}
680*16467b97STreehugger Robot
681*16467b97STreehugger Robot-(void)dealloc
682*16467b97STreehugger Robot{
683*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC
684*16467b97STreehugger Robot    NSLog( @"called dealloc in HashMap" );
685*16467b97STreehugger Robot#endif
686*16467b97STreehugger Robot    MapElement *tmp, *rtmp;
687*16467b97STreehugger Robot    NSInteger idx;
688*16467b97STreehugger Robot
689*16467b97STreehugger Robot    if ( self.fNext != nil ) {
690*16467b97STreehugger Robot        for( idx = 0; idx < Capacity; idx++ ) {
691*16467b97STreehugger Robot            tmp = ptrBuffer[idx];
692*16467b97STreehugger Robot            while ( tmp && tmp != [((HashMap *)fNext) getptrBufferEntry:idx] ) {
693*16467b97STreehugger Robot                rtmp = tmp;
694*16467b97STreehugger Robot                // tmp = [tmp getfNext];
695*16467b97STreehugger Robot                tmp = (MapElement *)tmp.fNext;
696*16467b97STreehugger Robot                [rtmp release];
697*16467b97STreehugger Robot            }
698*16467b97STreehugger Robot        }
699*16467b97STreehugger Robot    }
700*16467b97STreehugger Robot    if ( buffer ) [buffer release];
701*16467b97STreehugger Robot#ifdef DONTUSEYET
702*16467b97STreehugger Robot    [ptrBuffer release];
703*16467b97STreehugger Robot    [entrySet release];
704*16467b97STreehugger Robot#endif
705*16467b97STreehugger Robot    if ( keySet ) [keySet release];
706*16467b97STreehugger Robot    if ( values ) [values release];
707*16467b97STreehugger Robot    [super dealloc];
708*16467b97STreehugger Robot}
709*16467b97STreehugger Robot
710*16467b97STreehugger Robot- (NSUInteger)count
711*16467b97STreehugger Robot{
712*16467b97STreehugger Robot/*
713*16467b97STreehugger Robot    NSUInteger aCnt = 0;
714*16467b97STreehugger Robot
715*16467b97STreehugger Robot    for (NSUInteger i = 0; i < Capacity; i++) {
716*16467b97STreehugger Robot        if ( ptrBuffer[i] != nil ) {
717*16467b97STreehugger Robot            aCnt++;
718*16467b97STreehugger Robot        }
719*16467b97STreehugger Robot    }
720*16467b97STreehugger Robot    return aCnt;
721*16467b97STreehugger Robot */
722*16467b97STreehugger Robot    return count;
723*16467b97STreehugger Robot}
724*16467b97STreehugger Robot
725*16467b97STreehugger Robot- (NSInteger) size
726*16467b97STreehugger Robot{
727*16467b97STreehugger Robot    NSInteger aSize = 0;
728*16467b97STreehugger Robot
729*16467b97STreehugger Robot    for (NSInteger i = 0; i < Capacity; i++) {
730*16467b97STreehugger Robot        if ( ptrBuffer[i] != nil ) {
731*16467b97STreehugger Robot            aSize += sizeof(id);
732*16467b97STreehugger Robot        }
733*16467b97STreehugger Robot    }
734*16467b97STreehugger Robot    return aSize;
735*16467b97STreehugger Robot}
736*16467b97STreehugger Robot
737*16467b97STreehugger Robot
738*16467b97STreehugger Robot-(void)deleteHashMap:(MapElement *)np
739*16467b97STreehugger Robot{
740*16467b97STreehugger Robot    MapElement *tmp, *rtmp;
741*16467b97STreehugger Robot    NSInteger idx;
742*16467b97STreehugger Robot
743*16467b97STreehugger Robot    if ( self.fNext != nil ) {
744*16467b97STreehugger Robot        for( idx = 0; idx < Capacity; idx++ ) {
745*16467b97STreehugger Robot            tmp = ptrBuffer[idx];
746*16467b97STreehugger Robot            while ( tmp && tmp != (LinkBase *)[((HashMap *)fNext) getptrBufferEntry:idx] ) {
747*16467b97STreehugger Robot                rtmp = tmp;
748*16467b97STreehugger Robot                tmp = [tmp getfNext];
749*16467b97STreehugger Robot                [rtmp release];
750*16467b97STreehugger Robot            }
751*16467b97STreehugger Robot        }
752*16467b97STreehugger Robot    }
753*16467b97STreehugger Robot}
754*16467b97STreehugger Robot
755*16467b97STreehugger Robot-(HashMap *)PushScope:(HashMap **)map
756*16467b97STreehugger Robot{
757*16467b97STreehugger Robot    NSInteger idx;
758*16467b97STreehugger Robot    HashMap *htmp;
759*16467b97STreehugger Robot
760*16467b97STreehugger Robot    htmp = [HashMap newHashMap];
761*16467b97STreehugger Robot    if ( *map != nil ) {
762*16467b97STreehugger Robot        ((HashMap *)htmp)->fNext = *map;
763*16467b97STreehugger Robot        [htmp setScope:[((HashMap *)htmp->fNext) getScope]+1];
764*16467b97STreehugger Robot        for( idx = 0; idx < Capacity; idx++ ) {
765*16467b97STreehugger Robot            htmp->ptrBuffer[idx] = ((HashMap *)htmp->fNext)->ptrBuffer[idx];
766*16467b97STreehugger Robot        }
767*16467b97STreehugger Robot    }
768*16467b97STreehugger Robot    //    gScopeLevel++;
769*16467b97STreehugger Robot    *map = htmp;
770*16467b97STreehugger Robot    return( htmp );
771*16467b97STreehugger Robot}
772*16467b97STreehugger Robot
773*16467b97STreehugger Robot-(HashMap *)PopScope:(HashMap **)map
774*16467b97STreehugger Robot{
775*16467b97STreehugger Robot    NSInteger idx;
776*16467b97STreehugger Robot    MapElement *tmp;
777*16467b97STreehugger Robot    HashMap *htmp;
778*16467b97STreehugger Robot
779*16467b97STreehugger Robot    htmp = *map;
780*16467b97STreehugger Robot    if ( (*map)->fNext != nil ) {
781*16467b97STreehugger Robot        *map = (HashMap *)htmp->fNext;
782*16467b97STreehugger Robot        for( idx = 0; idx < Capacity; idx++ ) {
783*16467b97STreehugger Robot            if ( htmp->ptrBuffer[idx] == nil ||
784*16467b97STreehugger Robot                htmp->ptrBuffer[idx] == (*map)->ptrBuffer[idx] ) {
785*16467b97STreehugger Robot                break;
786*16467b97STreehugger Robot            }
787*16467b97STreehugger Robot            tmp = htmp->ptrBuffer[idx];
788*16467b97STreehugger Robot            /*
789*16467b97STreehugger Robot             * must deal with parms, locals and labels at some point
790*16467b97STreehugger Robot             * can not forget the debuggers
791*16467b97STreehugger Robot             */
792*16467b97STreehugger Robot            htmp->ptrBuffer[idx] = [tmp getfNext];
793*16467b97STreehugger Robot            [tmp release];
794*16467b97STreehugger Robot        }
795*16467b97STreehugger Robot        *map = (HashMap *)htmp->fNext;
796*16467b97STreehugger Robot        //        gScopeLevel--;
797*16467b97STreehugger Robot    }
798*16467b97STreehugger Robot    return( htmp );
799*16467b97STreehugger Robot}
800*16467b97STreehugger Robot
801*16467b97STreehugger Robot#ifdef USERDOC
802*16467b97STreehugger Robot/*
803*16467b97STreehugger Robot *  HASH        hash entry to get idx to table
804*16467b97STreehugger Robot *  NSInteger hash( HashMap *self, char *s );
805*16467b97STreehugger Robot *
806*16467b97STreehugger Robot *     Inputs:  char *s             string to find
807*16467b97STreehugger Robot *
808*16467b97STreehugger Robot *     Returns: NSInteger                 hashed value
809*16467b97STreehugger Robot *
810*16467b97STreehugger Robot *  Last Revision 9/03/90
811*16467b97STreehugger Robot */
812*16467b97STreehugger Robot#endif
813*16467b97STreehugger Robot-(NSInteger)hash:(NSString *)s       /*    form hash value for string s */
814*16467b97STreehugger Robot{
815*16467b97STreehugger Robot    NSInteger hashval;
816*16467b97STreehugger Robot    const char *tmp;
817*16467b97STreehugger Robot
818*16467b97STreehugger Robot    tmp = [s cStringUsingEncoding:NSASCIIStringEncoding];
819*16467b97STreehugger Robot    for( hashval = 0; *tmp != '\0'; )
820*16467b97STreehugger Robot        hashval += *tmp++;
821*16467b97STreehugger Robot    self->LastHash = hashval % Capacity;
822*16467b97STreehugger Robot    return( self->LastHash );
823*16467b97STreehugger Robot}
824*16467b97STreehugger Robot
825*16467b97STreehugger Robot/**
826*16467b97STreehugger Robot * Applies a supplemental hash function to a given hashCode, which
827*16467b97STreehugger Robot * defends against poor quality hash functions.  This is critical
828*16467b97STreehugger Robot * because HashMap uses power-of-two length hash tables, that
829*16467b97STreehugger Robot * otherwise encounter collisions for hashCodes that do not differ
830*16467b97STreehugger Robot * in lower bits. Note: Null keys always map to hash 0, thus idx 0.
831*16467b97STreehugger Robot */
832*16467b97STreehugger Robot- (NSInteger) hashInt:(NSInteger) h
833*16467b97STreehugger Robot{
834*16467b97STreehugger Robot    // This function ensures that hashCodes that differ only by
835*16467b97STreehugger Robot    // constant multiples at each bit position have a bounded
836*16467b97STreehugger Robot    // number of collisions (approximately 8 at default load factor).
837*16467b97STreehugger Robot    h ^= (h >> 20) ^ (h >> 12);
838*16467b97STreehugger Robot    return h ^ (h >> 7) ^ (h >> 4);
839*16467b97STreehugger Robot}
840*16467b97STreehugger Robot
841*16467b97STreehugger Robot/**
842*16467b97STreehugger Robot * Returns idx for hash code h.
843*16467b97STreehugger Robot */
844*16467b97STreehugger Robot- (NSInteger) indexFor:(NSInteger)h length:(NSInteger)length
845*16467b97STreehugger Robot{
846*16467b97STreehugger Robot    return h & (length - 1);
847*16467b97STreehugger Robot}
848*16467b97STreehugger Robot
849*16467b97STreehugger Robot#ifdef USERDOC
850*16467b97STreehugger Robot/*
851*16467b97STreehugger Robot *  FINDSCOPE  search hashed list for entry
852*16467b97STreehugger Robot *  HashMap *findscope( HashMap *self, NSInteger scope );
853*16467b97STreehugger Robot *
854*16467b97STreehugger Robot *     Inputs:  NSInteger       scope -- scope level to find
855*16467b97STreehugger Robot *
856*16467b97STreehugger Robot *     Returns: HashMap   pointer to ptrBuffer of proper scope level
857*16467b97STreehugger Robot *
858*16467b97STreehugger Robot *  Last Revision 9/03/90
859*16467b97STreehugger Robot */
860*16467b97STreehugger Robot#endif
861*16467b97STreehugger Robot-(HashMap *)findscope:(NSInteger)scope
862*16467b97STreehugger Robot{
863*16467b97STreehugger Robot    if ( self->Scope == scope ) {
864*16467b97STreehugger Robot        return( self );
865*16467b97STreehugger Robot    }
866*16467b97STreehugger Robot    else if ( fNext ) {
867*16467b97STreehugger Robot        return( [((HashMap *)fNext) findscope:scope] );
868*16467b97STreehugger Robot    }
869*16467b97STreehugger Robot    return( nil );              /*   not found      */
870*16467b97STreehugger Robot}
871*16467b97STreehugger Robot
872*16467b97STreehugger Robot#ifdef USERDOC
873*16467b97STreehugger Robot/*
874*16467b97STreehugger Robot *  LOOKUP  search hashed list for entry
875*16467b97STreehugger Robot *  MapElement *lookup( HashMap *self, char *s, NSInteger scope );
876*16467b97STreehugger Robot *
877*16467b97STreehugger Robot *     Inputs:  char     *s          string to find
878*16467b97STreehugger Robot *
879*16467b97STreehugger Robot *     Returns: MapElement  *           pointer to entry
880*16467b97STreehugger Robot *
881*16467b97STreehugger Robot *  Last Revision 9/03/90
882*16467b97STreehugger Robot */
883*16467b97STreehugger Robot#endif
884*16467b97STreehugger Robot-(id)lookup:(NSString *)s Scope:(NSInteger)scope
885*16467b97STreehugger Robot{
886*16467b97STreehugger Robot    MapElement *np;
887*16467b97STreehugger Robot
888*16467b97STreehugger Robot    for( np = self->ptrBuffer[[self hash:s]]; np != nil; np = [np getfNext] ) {
889*16467b97STreehugger Robot        if ( [s isEqualToString:[np getName]] ) {
890*16467b97STreehugger Robot            return( np );        /*   found it       */
891*16467b97STreehugger Robot        }
892*16467b97STreehugger Robot    }
893*16467b97STreehugger Robot    return( nil );              /*   not found      */
894*16467b97STreehugger Robot}
895*16467b97STreehugger Robot
896*16467b97STreehugger Robot#ifdef USERDOC
897*16467b97STreehugger Robot/*
898*16467b97STreehugger Robot *  INSTALL search hashed list for entry
899*16467b97STreehugger Robot *  NSInteger install( HashMap *self, MapElement *sym, NSInteger scope );
900*16467b97STreehugger Robot *
901*16467b97STreehugger Robot *     Inputs:  MapElement    *sym   -- symbol ptr to install
902*16467b97STreehugger Robot *              NSInteger         scope -- level to find
903*16467b97STreehugger Robot *
904*16467b97STreehugger Robot *     Returns: Boolean     TRUE   if installed
905*16467b97STreehugger Robot *                          FALSE  if already in table
906*16467b97STreehugger Robot *
907*16467b97STreehugger Robot *  Last Revision 9/03/90
908*16467b97STreehugger Robot */
909*16467b97STreehugger Robot#endif
910*16467b97STreehugger Robot-(MapElement *)install:(MapElement *)sym Scope:(NSInteger)scope
911*16467b97STreehugger Robot{
912*16467b97STreehugger Robot    MapElement *np;
913*16467b97STreehugger Robot
914*16467b97STreehugger Robot    np = [self lookup:[sym getName] Scope:scope ];
915*16467b97STreehugger Robot    if ( np == nil ) {
916*16467b97STreehugger Robot        [sym retain];
917*16467b97STreehugger Robot        [sym setFNext:self->ptrBuffer[ self->LastHash ]];
918*16467b97STreehugger Robot        self->ptrBuffer[ self->LastHash ] = sym;
919*16467b97STreehugger Robot        return( self->ptrBuffer[ self->LastHash ] );
920*16467b97STreehugger Robot    }
921*16467b97STreehugger Robot    return( nil );            /*   not found      */
922*16467b97STreehugger Robot}
923*16467b97STreehugger Robot
924*16467b97STreehugger Robot#ifdef USERDOC
925*16467b97STreehugger Robot/*
926*16467b97STreehugger Robot *  RemoveSym  search hashed list for entry
927*16467b97STreehugger Robot *  NSInteger RemoveSym( HashMap *self, char *s );
928*16467b97STreehugger Robot *
929*16467b97STreehugger Robot *     Inputs:  char     *s          string to find
930*16467b97STreehugger Robot *
931*16467b97STreehugger Robot *     Returns: NSInteger      indicator of SUCCESS OR FAILURE
932*16467b97STreehugger Robot *
933*16467b97STreehugger Robot *  Last Revision 9/03/90
934*16467b97STreehugger Robot */
935*16467b97STreehugger Robot#endif
936*16467b97STreehugger Robot-(NSInteger)RemoveSym:(NSString *)s
937*16467b97STreehugger Robot{
938*16467b97STreehugger Robot    MapElement *np, *tmp;
939*16467b97STreehugger Robot    NSInteger idx;
940*16467b97STreehugger Robot
941*16467b97STreehugger Robot    idx = [self hash:s];
942*16467b97STreehugger Robot    for ( tmp = self->ptrBuffer[idx], np = self->ptrBuffer[idx]; np != nil; np = [np getfNext] ) {
943*16467b97STreehugger Robot        if ( [s isEqualToString:[np getName]] ) {
944*16467b97STreehugger Robot            tmp = [np getfNext];             /* get the next link  */
945*16467b97STreehugger Robot            [np release];
946*16467b97STreehugger Robot            return( SUCCESS );            /* report SUCCESS     */
947*16467b97STreehugger Robot        }
948*16467b97STreehugger Robot        tmp = [np getfNext];              //  BAD!!!!!!
949*16467b97STreehugger Robot    }
950*16467b97STreehugger Robot    return( FAILURE );                    /*   not found      */
951*16467b97STreehugger Robot}
952*16467b97STreehugger Robot
953*16467b97STreehugger Robot-(void)delete_chain:(MapElement *)np
954*16467b97STreehugger Robot{
955*16467b97STreehugger Robot    if ( [np getfNext] != nil )
956*16467b97STreehugger Robot        [self delete_chain:[np getfNext]];
957*16467b97STreehugger Robot    [np dealloc];
958*16467b97STreehugger Robot}
959*16467b97STreehugger Robot
960*16467b97STreehugger Robot#ifdef DONTUSEYET
961*16467b97STreehugger Robot-(NSInteger)bld_symtab:(KW_TABLE *)toknams
962*16467b97STreehugger Robot{
963*16467b97STreehugger Robot    NSInteger i;
964*16467b97STreehugger Robot    MapElement *np;
965*16467b97STreehugger Robot
966*16467b97STreehugger Robot    for( i = 0; *(toknams[i].name) != '\0'; i++ ) {
967*16467b97STreehugger Robot        // install symbol in ptrBuffer
968*16467b97STreehugger Robot        np = [MapElement newMapElement:[NSString stringWithFormat:@"%s", toknams[i].name]];
969*16467b97STreehugger Robot        //        np->fType = toknams[i].toknum;
970*16467b97STreehugger Robot        [self install:np Scope:0];
971*16467b97STreehugger Robot    }
972*16467b97STreehugger Robot    return( SUCCESS );
973*16467b97STreehugger Robot}
974*16467b97STreehugger Robot#endif
975*16467b97STreehugger Robot
976*16467b97STreehugger Robot-(MapElement *)getptrBufferEntry:(NSInteger)idx
977*16467b97STreehugger Robot{
978*16467b97STreehugger Robot    return( ptrBuffer[idx] );
979*16467b97STreehugger Robot}
980*16467b97STreehugger Robot
981*16467b97STreehugger Robot-(MapElement **)getptrBuffer
982*16467b97STreehugger Robot{
983*16467b97STreehugger Robot    return( ptrBuffer );
984*16467b97STreehugger Robot}
985*16467b97STreehugger Robot
986*16467b97STreehugger Robot-(void)setptrBuffer:(MapElement *)np Index:(NSInteger)idx
987*16467b97STreehugger Robot{
988*16467b97STreehugger Robot    if ( idx < Capacity ) {
989*16467b97STreehugger Robot        [np retain];
990*16467b97STreehugger Robot        ptrBuffer[idx] = np;
991*16467b97STreehugger Robot    }
992*16467b97STreehugger Robot}
993*16467b97STreehugger Robot
994*16467b97STreehugger Robot-(NSInteger)getScope
995*16467b97STreehugger Robot{
996*16467b97STreehugger Robot    return( Scope );
997*16467b97STreehugger Robot}
998*16467b97STreehugger Robot
999*16467b97STreehugger Robot-(void)setScopeScope:(NSInteger)i
1000*16467b97STreehugger Robot{
1001*16467b97STreehugger Robot    Scope = i;
1002*16467b97STreehugger Robot}
1003*16467b97STreehugger Robot
1004*16467b97STreehugger Robot- (MapElement *)getTType:(NSString *)name
1005*16467b97STreehugger Robot{
1006*16467b97STreehugger Robot    return [self lookup:name Scope:0];
1007*16467b97STreehugger Robot}
1008*16467b97STreehugger Robot
1009*16467b97STreehugger Robot/*
1010*16467b97STreehugger Robot * works only for maplist indexed not by name but by TokenNumber
1011*16467b97STreehugger Robot */
1012*16467b97STreehugger Robot- (MapElement *)getNameInList:(NSInteger)ttype
1013*16467b97STreehugger Robot{
1014*16467b97STreehugger Robot    MapElement *np;
1015*16467b97STreehugger Robot    NSInteger aTType;
1016*16467b97STreehugger Robot
1017*16467b97STreehugger Robot    aTType = ttype % Capacity;
1018*16467b97STreehugger Robot    for( np = self->ptrBuffer[aTType]; np != nil; np = [np getfNext] ) {
1019*16467b97STreehugger Robot        if ( [(ACNumber *)np.node integerValue] == ttype ) {
1020*16467b97STreehugger Robot            return( np );        /*   found it       */
1021*16467b97STreehugger Robot        }
1022*16467b97STreehugger Robot    }
1023*16467b97STreehugger Robot    return( nil );              /*   not found      */
1024*16467b97STreehugger Robot}
1025*16467b97STreehugger Robot
1026*16467b97STreehugger Robot- (LinkBase *)getName:(NSString *)name
1027*16467b97STreehugger Robot{
1028*16467b97STreehugger Robot    return [self lookup:name Scope:0]; /*  nil if not found      */
1029*16467b97STreehugger Robot}
1030*16467b97STreehugger Robot
1031*16467b97STreehugger Robot- (void)putNode:(NSString *)name TokenType:(NSInteger)ttype
1032*16467b97STreehugger Robot{
1033*16467b97STreehugger Robot    MapElement *np;
1034*16467b97STreehugger Robot
1035*16467b97STreehugger Robot    // install symbol in ptrBuffer
1036*16467b97STreehugger Robot    np = [MapElement newMapElementWithName:[NSString stringWithString:name] Type:ttype];
1037*16467b97STreehugger Robot    //        np->fType = toknams[i].toknum;
1038*16467b97STreehugger Robot    [self install:np Scope:0];
1039*16467b97STreehugger Robot}
1040*16467b97STreehugger Robot
1041*16467b97STreehugger Robot- (NSInteger)getMode
1042*16467b97STreehugger Robot{
1043*16467b97STreehugger Robot    return mode;
1044*16467b97STreehugger Robot}
1045*16467b97STreehugger Robot
1046*16467b97STreehugger Robot- (void)setMode:(NSInteger)aMode
1047*16467b97STreehugger Robot{
1048*16467b97STreehugger Robot    mode = aMode;
1049*16467b97STreehugger Robot}
1050*16467b97STreehugger Robot
1051*16467b97STreehugger Robot- (void) addObject:(id)aRule
1052*16467b97STreehugger Robot{
1053*16467b97STreehugger Robot    NSInteger idx;
1054*16467b97STreehugger Robot
1055*16467b97STreehugger Robot    idx = [self count];
1056*16467b97STreehugger Robot    if ( idx >= Capacity ) {
1057*16467b97STreehugger Robot        idx %= Capacity;
1058*16467b97STreehugger Robot    }
1059*16467b97STreehugger Robot    ptrBuffer[idx] = aRule;
1060*16467b97STreehugger Robot}
1061*16467b97STreehugger Robot
1062*16467b97STreehugger Robot/* this may have to handle linking into the chain
1063*16467b97STreehugger Robot */
1064*16467b97STreehugger Robot- (void) insertObject:(id)aRule atIndex:(NSInteger)idx
1065*16467b97STreehugger Robot{
1066*16467b97STreehugger Robot    if ( idx >= Capacity ) {
1067*16467b97STreehugger Robot        idx %= Capacity;
1068*16467b97STreehugger Robot    }
1069*16467b97STreehugger Robot    if ( aRule != ptrBuffer[idx] ) {
1070*16467b97STreehugger Robot        if ( ptrBuffer[idx] ) [ptrBuffer[idx] release];
1071*16467b97STreehugger Robot        [aRule retain];
1072*16467b97STreehugger Robot    }
1073*16467b97STreehugger Robot    ptrBuffer[idx] = aRule;
1074*16467b97STreehugger Robot}
1075*16467b97STreehugger Robot
1076*16467b97STreehugger Robot- (id)objectAtIndex:(NSInteger)idx
1077*16467b97STreehugger Robot{
1078*16467b97STreehugger Robot    if ( idx >= Capacity ) {
1079*16467b97STreehugger Robot        idx %= Capacity;
1080*16467b97STreehugger Robot    }
1081*16467b97STreehugger Robot    return ptrBuffer[idx];
1082*16467b97STreehugger Robot}
1083*16467b97STreehugger Robot
1084*16467b97STreehugger Robot/**
1085*16467b97STreehugger Robot * Returns <tt>true</tt> if this map contains no key-value mappings.
1086*16467b97STreehugger Robot *
1087*16467b97STreehugger Robot * @return <tt>true</tt> if this map contains no key-value mappings
1088*16467b97STreehugger Robot */
1089*16467b97STreehugger Robot- (BOOL) empty
1090*16467b97STreehugger Robot{
1091*16467b97STreehugger Robot    return count == 0;
1092*16467b97STreehugger Robot}
1093*16467b97STreehugger Robot
1094*16467b97STreehugger Robot/**
1095*16467b97STreehugger Robot * Offloaded version of get() to look up null keys.  Null keys map
1096*16467b97STreehugger Robot * to idx 0.  This null case is split out into separate methods
1097*16467b97STreehugger Robot * for the sake of performance in the two most commonly used
1098*16467b97STreehugger Robot * operations (get and put), but incorporated with conditionals in
1099*16467b97STreehugger Robot * others.
1100*16467b97STreehugger Robot */
1101*16467b97STreehugger Robot- (id) getForNullKey
1102*16467b97STreehugger Robot{
1103*16467b97STreehugger Robot
1104*16467b97STreehugger Robot    for (HMEntry *e = (HMEntry *)ptrBuffer[0]; e != nil; e = e.next) {
1105*16467b97STreehugger Robot        if (e.key == nil)
1106*16467b97STreehugger Robot            return e.value;
1107*16467b97STreehugger Robot    }
1108*16467b97STreehugger Robot
1109*16467b97STreehugger Robot    return nil;
1110*16467b97STreehugger Robot}
1111*16467b97STreehugger Robot
1112*16467b97STreehugger Robot/**
1113*16467b97STreehugger Robot * Returns the value to which the specified key is mapped,
1114*16467b97STreehugger Robot * or {@code null} if this map contains no mapping for the key.
1115*16467b97STreehugger Robot *
1116*16467b97STreehugger Robot * <p>More formally, if this map contains a mapping from a key
1117*16467b97STreehugger Robot * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
1118*16467b97STreehugger Robot * key.equals(k))}, then this method returns {@code v}; otherwise
1119*16467b97STreehugger Robot * it returns {@code null}.  (There can be at most one such mapping.)
1120*16467b97STreehugger Robot *
1121*16467b97STreehugger Robot * <p>A return value of {@code null} does not <i>necessarily</i>
1122*16467b97STreehugger Robot * indicate that the map contains no mapping for the key; it's also
1123*16467b97STreehugger Robot * possible that the map explicitly maps the key to {@code null}.
1124*16467b97STreehugger Robot * The {@link #containsKey containsKey} operation may be used to
1125*16467b97STreehugger Robot * distinguish these two cases.
1126*16467b97STreehugger Robot *
1127*16467b97STreehugger Robot * @see #put(Object, Object)
1128*16467b97STreehugger Robot */
1129*16467b97STreehugger Robot- (id) get:(NSString *)key
1130*16467b97STreehugger Robot{
1131*16467b97STreehugger Robot    if (key == nil)
1132*16467b97STreehugger Robot        return [self getForNullKey];
1133*16467b97STreehugger Robot    //    NSInteger hash = [self hashInt:[self hash:key]];
1134*16467b97STreehugger Robot    NSInteger hash = [self hashInt:[key hash]];
1135*16467b97STreehugger Robot
1136*16467b97STreehugger Robot    for (HMEntry *e = (HMEntry *)ptrBuffer[[self indexFor:hash length:[self capacity]]]; e != nil; e = e.next) {
1137*16467b97STreehugger Robot        NSString *k;
1138*16467b97STreehugger Robot        if (e.hash == hash && ((k = e.key) == key || [key isEqualTo:k]))
1139*16467b97STreehugger Robot            return e.value;
1140*16467b97STreehugger Robot    }
1141*16467b97STreehugger Robot
1142*16467b97STreehugger Robot    return nil;
1143*16467b97STreehugger Robot}
1144*16467b97STreehugger Robot
1145*16467b97STreehugger Robot
1146*16467b97STreehugger Robot/**
1147*16467b97STreehugger Robot * Returns <tt>true</tt> if this map contains a mapping for the
1148*16467b97STreehugger Robot * specified key.
1149*16467b97STreehugger Robot *
1150*16467b97STreehugger Robot * @param   key   The key whose presence in this map is to be tested
1151*16467b97STreehugger Robot * @return <tt>true</tt> if this map contains a mapping for the specified
1152*16467b97STreehugger Robot * key.
1153*16467b97STreehugger Robot */
1154*16467b97STreehugger Robot- (BOOL) containsKey:(NSString *)key
1155*16467b97STreehugger Robot{
1156*16467b97STreehugger Robot    return [self getEntry:key] != nil;
1157*16467b97STreehugger Robot}
1158*16467b97STreehugger Robot
1159*16467b97STreehugger Robot/**
1160*16467b97STreehugger Robot * Returns the entry associated with the specified key in the
1161*16467b97STreehugger Robot * HashMap.  Returns null if the HashMap contains no mapping
1162*16467b97STreehugger Robot * for the key.
1163*16467b97STreehugger Robot */
1164*16467b97STreehugger Robot- (HMEntry *) getEntry:(NSString *)key
1165*16467b97STreehugger Robot{
1166*16467b97STreehugger Robot    //    NSInteger hash = (key == nil) ? 0 : [self hashInt:[self hash:key]];
1167*16467b97STreehugger Robot    NSInteger hash = (key == nil) ? 0 : [self hashInt:[key hash]];
1168*16467b97STreehugger Robot
1169*16467b97STreehugger Robot    for (HMEntry *e = (HMEntry *)ptrBuffer[[self indexFor:hash length:Capacity]]; e != nil; e = e.next) {
1170*16467b97STreehugger Robot        NSString *k;
1171*16467b97STreehugger Robot        if (e.hash == hash && ((k = e.key) == key || (key != nil && [key isEqualTo:k])))
1172*16467b97STreehugger Robot            return e;
1173*16467b97STreehugger Robot    }
1174*16467b97STreehugger Robot
1175*16467b97STreehugger Robot    return nil;
1176*16467b97STreehugger Robot}
1177*16467b97STreehugger Robot
1178*16467b97STreehugger Robot
1179*16467b97STreehugger Robot/**
1180*16467b97STreehugger Robot * Associates the specified value with the specified key in this map.
1181*16467b97STreehugger Robot * If the map previously contained a mapping for the key, the old
1182*16467b97STreehugger Robot * value is replaced.
1183*16467b97STreehugger Robot *
1184*16467b97STreehugger Robot * @param key key with which the specified value is to be associated
1185*16467b97STreehugger Robot * @param value value to be associated with the specified key
1186*16467b97STreehugger Robot * @return the previous value associated with <tt>key</tt>, or
1187*16467b97STreehugger Robot * <tt>null</tt> if there was no mapping for <tt>key</tt>.
1188*16467b97STreehugger Robot * (A <tt>null</tt> return can also indicate that the map
1189*16467b97STreehugger Robot * previously associated <tt>null</tt> with <tt>key</tt>.)
1190*16467b97STreehugger Robot */
1191*16467b97STreehugger Robot- (id) put:(NSString *)key value:(id)value
1192*16467b97STreehugger Robot{
1193*16467b97STreehugger Robot    if (key == nil)
1194*16467b97STreehugger Robot        return [self putForNullKey:value];
1195*16467b97STreehugger Robot//    NSInteger hash = [self hashInt:[self hash:key]];
1196*16467b97STreehugger Robot    NSInteger hash = [self hashInt:[key hash]];
1197*16467b97STreehugger Robot    NSInteger i = [self indexFor:hash length:[self capacity]];
1198*16467b97STreehugger Robot
1199*16467b97STreehugger Robot    for (HMEntry *e = (HMEntry *)ptrBuffer[i]; e != nil; e = e.next) {
1200*16467b97STreehugger Robot        NSString *k;
1201*16467b97STreehugger Robot        if (e.hash == hash && ((k = e.key) == key || [key isEqualTo:k])) {
1202*16467b97STreehugger Robot            id oldValue = e.value;
1203*16467b97STreehugger Robot            e.value = value;
1204*16467b97STreehugger Robot            [e recordAccess:self];
1205*16467b97STreehugger Robot            return oldValue;
1206*16467b97STreehugger Robot        }
1207*16467b97STreehugger Robot    }
1208*16467b97STreehugger Robot
1209*16467b97STreehugger Robot    modCount++;
1210*16467b97STreehugger Robot    [self addEntry:hash key:key value:value bucketIndex:i];
1211*16467b97STreehugger Robot    return nil;
1212*16467b97STreehugger Robot}
1213*16467b97STreehugger Robot
1214*16467b97STreehugger Robot
1215*16467b97STreehugger Robot/**
1216*16467b97STreehugger Robot * Offloaded version of put for null keys
1217*16467b97STreehugger Robot */
1218*16467b97STreehugger Robot- (id) putForNullKey:(id)value
1219*16467b97STreehugger Robot{
1220*16467b97STreehugger Robot
1221*16467b97STreehugger Robot    for (HMEntry *e = (HMEntry *)ptrBuffer[0]; e != nil; e = e.next) {
1222*16467b97STreehugger Robot        if (e.key == nil) {
1223*16467b97STreehugger Robot            id oldValue = e.value;
1224*16467b97STreehugger Robot            e.value = value;
1225*16467b97STreehugger Robot            [e recordAccess:self];
1226*16467b97STreehugger Robot            return oldValue;
1227*16467b97STreehugger Robot        }
1228*16467b97STreehugger Robot    }
1229*16467b97STreehugger Robot
1230*16467b97STreehugger Robot    modCount++;
1231*16467b97STreehugger Robot    [self addEntry:0 key:nil value:value bucketIndex:0];
1232*16467b97STreehugger Robot    return nil;
1233*16467b97STreehugger Robot}
1234*16467b97STreehugger Robot
1235*16467b97STreehugger Robot/**
1236*16467b97STreehugger Robot * This method is used instead of put by constructors and
1237*16467b97STreehugger Robot * pseudoconstructors (clone, readObject).  It does not resize the table,
1238*16467b97STreehugger Robot * check for comodification, etc.  It calls createEntry rather than
1239*16467b97STreehugger Robot * addEntry.
1240*16467b97STreehugger Robot */
1241*16467b97STreehugger Robot- (void) putForCreate:(NSString *)key value:(id)value
1242*16467b97STreehugger Robot{
1243*16467b97STreehugger Robot    NSInteger hash = (key == nil) ? 0 : [self hashInt:[self hash:key]];
1244*16467b97STreehugger Robot    NSInteger i = [self indexFor:hash length:[self capacity]];
1245*16467b97STreehugger Robot
1246*16467b97STreehugger Robot    for (HMEntry *e = (HMEntry *)ptrBuffer[i]; e != nil; e = e.next) {
1247*16467b97STreehugger Robot        NSString *k;
1248*16467b97STreehugger Robot        if (e.hash == hash && ((k = e.key) == key || (key != nil && [key isEqualTo:k]))) {
1249*16467b97STreehugger Robot            e.value = value;
1250*16467b97STreehugger Robot            return;
1251*16467b97STreehugger Robot        }
1252*16467b97STreehugger Robot    }
1253*16467b97STreehugger Robot
1254*16467b97STreehugger Robot    [self createEntry:hash key:key value:value bucketIndex:i];
1255*16467b97STreehugger Robot}
1256*16467b97STreehugger Robot
1257*16467b97STreehugger Robot- (void) putAllForCreate:(HashMap *)m
1258*16467b97STreehugger Robot{
1259*16467b97STreehugger Robot
1260*16467b97STreehugger Robot    for (HMEntry *e in [m entrySet])
1261*16467b97STreehugger Robot        [self putForCreate:[e key] value:[e value]];
1262*16467b97STreehugger Robot
1263*16467b97STreehugger Robot}
1264*16467b97STreehugger Robot
1265*16467b97STreehugger Robot/**
1266*16467b97STreehugger Robot * Rehashes the contents of this map into a new array with a
1267*16467b97STreehugger Robot * larger capacity.  This method is called automatically when the
1268*16467b97STreehugger Robot * number of keys in this map reaches its threshold.
1269*16467b97STreehugger Robot *
1270*16467b97STreehugger Robot * If current capacity is MAXIMUM_CAPACITY, this method does not
1271*16467b97STreehugger Robot * resize the map, but sets threshold to Integer.MAX_VALUE.
1272*16467b97STreehugger Robot * This has the effect of preventing future calls.
1273*16467b97STreehugger Robot *
1274*16467b97STreehugger Robot * @param newCapacity the new capacity, MUST be a power of two;
1275*16467b97STreehugger Robot * must be greater than current capacity unless current
1276*16467b97STreehugger Robot * capacity is MAXIMUM_CAPACITY (in which case value
1277*16467b97STreehugger Robot * is irrelevant).
1278*16467b97STreehugger Robot */
1279*16467b97STreehugger Robot- (void) resize:(NSInteger)newCapacity
1280*16467b97STreehugger Robot{
1281*16467b97STreehugger Robot//    NSArray * oldTable = ptrBuffer;
1282*16467b97STreehugger Robot    NSInteger oldCapacity = Capacity;
1283*16467b97STreehugger Robot    if (oldCapacity == MAXIMUM_CAPACITY) {
1284*16467b97STreehugger Robot        threshold = NSIntegerMax;
1285*16467b97STreehugger Robot        return;
1286*16467b97STreehugger Robot    }
1287*16467b97STreehugger Robot//    NSArray * newTable = [NSArray array];
1288*16467b97STreehugger Robot//    [self transfer:newTable];
1289*16467b97STreehugger Robot    BuffSize = newCapacity * sizeof(id);
1290*16467b97STreehugger Robot    Capacity = newCapacity;
1291*16467b97STreehugger Robot    [buffer setLength:BuffSize];
1292*16467b97STreehugger Robot    ptrBuffer = [buffer mutableBytes];
1293*16467b97STreehugger Robot    threshold = (NSInteger)(newCapacity * loadFactor);
1294*16467b97STreehugger Robot}
1295*16467b97STreehugger Robot
1296*16467b97STreehugger Robot
1297*16467b97STreehugger Robot/**
1298*16467b97STreehugger Robot * Transfers all entries from current table to newTable.
1299*16467b97STreehugger Robot */
1300*16467b97STreehugger Robot- (void) transfer:(AMutableArray *)newTable
1301*16467b97STreehugger Robot{
1302*16467b97STreehugger Robot    NSInteger newCapacity = [newTable count];
1303*16467b97STreehugger Robot
1304*16467b97STreehugger Robot    for (NSInteger j = 0; j < [self capacity]; j++) {
1305*16467b97STreehugger Robot        HMEntry *e = (HMEntry *)ptrBuffer[j];
1306*16467b97STreehugger Robot        if (e != nil) {
1307*16467b97STreehugger Robot            ptrBuffer[j] = nil;
1308*16467b97STreehugger Robot
1309*16467b97STreehugger Robot            do {
1310*16467b97STreehugger Robot                HMEntry *next = e.next;
1311*16467b97STreehugger Robot                NSInteger i = [self indexFor:e.hash length:newCapacity];
1312*16467b97STreehugger Robot                e.next = [newTable objectAtIndex:i];
1313*16467b97STreehugger Robot                [newTable replaceObjectAtIndex:i withObject:e];
1314*16467b97STreehugger Robot                e = next;
1315*16467b97STreehugger Robot            }
1316*16467b97STreehugger Robot            while (e != nil);
1317*16467b97STreehugger Robot        }
1318*16467b97STreehugger Robot    }
1319*16467b97STreehugger Robot
1320*16467b97STreehugger Robot}
1321*16467b97STreehugger Robot
1322*16467b97STreehugger Robot
1323*16467b97STreehugger Robot/**
1324*16467b97STreehugger Robot * Copies all of the mappings from the specified map to this map.
1325*16467b97STreehugger Robot * These mappings will replace any mappings that this map had for
1326*16467b97STreehugger Robot * any of the keys currently in the specified map.
1327*16467b97STreehugger Robot *
1328*16467b97STreehugger Robot * @param m mappings to be stored in this map
1329*16467b97STreehugger Robot * @throws NullPointerException if the specified map is null
1330*16467b97STreehugger Robot */
1331*16467b97STreehugger Robot- (void) putAll:(HashMap *)m
1332*16467b97STreehugger Robot{
1333*16467b97STreehugger Robot    NSInteger numKeysToBeAdded = [m count];
1334*16467b97STreehugger Robot    if (numKeysToBeAdded == 0)
1335*16467b97STreehugger Robot        return;
1336*16467b97STreehugger Robot    if (numKeysToBeAdded > threshold) {
1337*16467b97STreehugger Robot        NSInteger targetCapacity = (NSInteger)(numKeysToBeAdded / loadFactor + 1);
1338*16467b97STreehugger Robot        if (targetCapacity > MAXIMUM_CAPACITY)
1339*16467b97STreehugger Robot            targetCapacity = MAXIMUM_CAPACITY;
1340*16467b97STreehugger Robot        NSInteger newCapacity = Capacity;
1341*16467b97STreehugger Robot
1342*16467b97STreehugger Robot        while (newCapacity < targetCapacity)
1343*16467b97STreehugger Robot            newCapacity <<= 1;
1344*16467b97STreehugger Robot
1345*16467b97STreehugger Robot        if (newCapacity > Capacity)
1346*16467b97STreehugger Robot            [self resize:newCapacity];
1347*16467b97STreehugger Robot    }
1348*16467b97STreehugger Robot
1349*16467b97STreehugger Robot    for (HMEntry *e in [m entrySet])
1350*16467b97STreehugger Robot        [self put:[e key] value:[e value]];
1351*16467b97STreehugger Robot
1352*16467b97STreehugger Robot}
1353*16467b97STreehugger Robot
1354*16467b97STreehugger Robot/**
1355*16467b97STreehugger Robot * Removes the mapping for the specified key from this map if present.
1356*16467b97STreehugger Robot *
1357*16467b97STreehugger Robot * @param  key key whose mapping is to be removed from the map
1358*16467b97STreehugger Robot * @return the previous value associated with <tt>key</tt>, or
1359*16467b97STreehugger Robot * <tt>null</tt> if there was no mapping for <tt>key</tt>.
1360*16467b97STreehugger Robot * (A <tt>null</tt> return can also indicate that the map
1361*16467b97STreehugger Robot * previously associated <tt>null</tt> with <tt>key</tt>.)
1362*16467b97STreehugger Robot */
1363*16467b97STreehugger Robot- (id) remove:(NSString *)key
1364*16467b97STreehugger Robot{
1365*16467b97STreehugger Robot    HMEntry *e = [self removeEntryForKey:key];
1366*16467b97STreehugger Robot    return (e == nil ? nil : e.value);
1367*16467b97STreehugger Robot}
1368*16467b97STreehugger Robot
1369*16467b97STreehugger Robot
1370*16467b97STreehugger Robot/**
1371*16467b97STreehugger Robot * Removes and returns the entry associated with the specified key
1372*16467b97STreehugger Robot * in the HashMap.  Returns null if the HashMap contains no mapping
1373*16467b97STreehugger Robot * for this key.
1374*16467b97STreehugger Robot */
1375*16467b97STreehugger Robot- (HMEntry *) removeEntryForKey:(NSString *)key
1376*16467b97STreehugger Robot{
1377*16467b97STreehugger Robot    NSInteger hash = (key == nil) ? 0 : [self hashInt:[self hash:key]];
1378*16467b97STreehugger Robot    NSInteger i = [self indexFor:hash length:Capacity];
1379*16467b97STreehugger Robot    HMEntry *prev = (HMEntry *)ptrBuffer[i];
1380*16467b97STreehugger Robot    HMEntry *e = prev;
1381*16467b97STreehugger Robot
1382*16467b97STreehugger Robot    while (e != nil) {
1383*16467b97STreehugger Robot        HMEntry *next = e.next;
1384*16467b97STreehugger Robot        NSString *k;
1385*16467b97STreehugger Robot        if (e.hash == hash && ((k = e.key) == key || (key != nil && [key isEqualTo:k]))) {
1386*16467b97STreehugger Robot            modCount++;
1387*16467b97STreehugger Robot            count--;
1388*16467b97STreehugger Robot            if (prev == e)
1389*16467b97STreehugger Robot                ptrBuffer[i] = (id) next;
1390*16467b97STreehugger Robot            else
1391*16467b97STreehugger Robot                prev.next = next;
1392*16467b97STreehugger Robot            [e recordRemoval:self];
1393*16467b97STreehugger Robot            return e;
1394*16467b97STreehugger Robot        }
1395*16467b97STreehugger Robot        prev = e;
1396*16467b97STreehugger Robot        e = next;
1397*16467b97STreehugger Robot    }
1398*16467b97STreehugger Robot
1399*16467b97STreehugger Robot    return e;
1400*16467b97STreehugger Robot}
1401*16467b97STreehugger Robot
1402*16467b97STreehugger Robot/**
1403*16467b97STreehugger Robot * Special version of remove for EntrySet.
1404*16467b97STreehugger Robot */
1405*16467b97STreehugger Robot- (HMEntry *) removeMapping:(id)o
1406*16467b97STreehugger Robot{
1407*16467b97STreehugger Robot//    if (!([o conformsToProtocol:@protocol(HMEntry)]))
1408*16467b97STreehugger Robot//        return nil;
1409*16467b97STreehugger Robot    HMEntry *entry = (HMEntry *)o;
1410*16467b97STreehugger Robot    NSString *key = entry.key;
1411*16467b97STreehugger Robot    NSInteger hash = (key == nil) ? 0 : [self hashInt:[self hash:key]];
1412*16467b97STreehugger Robot    NSInteger i = [self indexFor:hash length:Capacity];
1413*16467b97STreehugger Robot    HMEntry *prev = (HMEntry *)ptrBuffer[i];
1414*16467b97STreehugger Robot    HMEntry *e = prev;
1415*16467b97STreehugger Robot
1416*16467b97STreehugger Robot    while (e != nil) {
1417*16467b97STreehugger Robot        HMEntry *next = e.next;
1418*16467b97STreehugger Robot        if (e.hash == hash && [e isEqualTo:entry]) {
1419*16467b97STreehugger Robot            modCount++;
1420*16467b97STreehugger Robot            count--;
1421*16467b97STreehugger Robot            if (prev == e)
1422*16467b97STreehugger Robot                ptrBuffer[i] = (id)next;
1423*16467b97STreehugger Robot            else
1424*16467b97STreehugger Robot                prev.next = next;
1425*16467b97STreehugger Robot            [e recordRemoval:self];
1426*16467b97STreehugger Robot            return e;
1427*16467b97STreehugger Robot        }
1428*16467b97STreehugger Robot        prev = e;
1429*16467b97STreehugger Robot        e = next;
1430*16467b97STreehugger Robot    }
1431*16467b97STreehugger Robot
1432*16467b97STreehugger Robot    return e;
1433*16467b97STreehugger Robot}
1434*16467b97STreehugger Robot
1435*16467b97STreehugger Robot/**
1436*16467b97STreehugger Robot * Removes all of the mappings from this map.
1437*16467b97STreehugger Robot * The map will be empty after this call returns.
1438*16467b97STreehugger Robot */
1439*16467b97STreehugger Robot- (void) clear
1440*16467b97STreehugger Robot{
1441*16467b97STreehugger Robot    modCount++;
1442*16467b97STreehugger Robot    id tmp;
1443*16467b97STreehugger Robot
1444*16467b97STreehugger Robot    for (NSInteger i = 0; i < Capacity; i++) {
1445*16467b97STreehugger Robot        tmp = ptrBuffer[i];
1446*16467b97STreehugger Robot        if ( tmp ) {
1447*16467b97STreehugger Robot            [tmp release];
1448*16467b97STreehugger Robot        }
1449*16467b97STreehugger Robot        ptrBuffer[i] = nil;
1450*16467b97STreehugger Robot    }
1451*16467b97STreehugger Robot    count = 0;
1452*16467b97STreehugger Robot}
1453*16467b97STreehugger Robot
1454*16467b97STreehugger Robot
1455*16467b97STreehugger Robot/**
1456*16467b97STreehugger Robot * Special-case code for containsValue with null argument
1457*16467b97STreehugger Robot */
1458*16467b97STreehugger Robot- (BOOL) containsNullValue
1459*16467b97STreehugger Robot{
1460*16467b97STreehugger Robot    for (NSInteger i = 0; i < Capacity; i++)
1461*16467b97STreehugger Robot
1462*16467b97STreehugger Robot        for (HMEntry *e = (HMEntry *)ptrBuffer[i]; e != nil; e = e.next)
1463*16467b97STreehugger Robot            if (e.value == nil)
1464*16467b97STreehugger Robot                return YES;
1465*16467b97STreehugger Robot    return NO;
1466*16467b97STreehugger Robot}
1467*16467b97STreehugger Robot
1468*16467b97STreehugger Robot/**
1469*16467b97STreehugger Robot * Returns <tt>true</tt> if this map maps one or more keys to the
1470*16467b97STreehugger Robot * specified value.
1471*16467b97STreehugger Robot *
1472*16467b97STreehugger Robot * @param value value whose presence in this map is to be tested
1473*16467b97STreehugger Robot * @return <tt>true</tt> if this map maps one or more keys to the
1474*16467b97STreehugger Robot * specified value
1475*16467b97STreehugger Robot */
1476*16467b97STreehugger Robot- (BOOL) containsValue:(id)value
1477*16467b97STreehugger Robot{
1478*16467b97STreehugger Robot    if (value == nil)
1479*16467b97STreehugger Robot        return [self containsNullValue];
1480*16467b97STreehugger Robot
1481*16467b97STreehugger Robot    for (NSInteger i = 0; i < Capacity; i++)
1482*16467b97STreehugger Robot
1483*16467b97STreehugger Robot        for (HMEntry *e = (HMEntry *)ptrBuffer[i]; e != nil; e = e.next)
1484*16467b97STreehugger Robot            if ([value isEqualTo:e.value])
1485*16467b97STreehugger Robot                return YES;
1486*16467b97STreehugger Robot
1487*16467b97STreehugger Robot
1488*16467b97STreehugger Robot    return NO;
1489*16467b97STreehugger Robot}
1490*16467b97STreehugger Robot
1491*16467b97STreehugger Robot/**
1492*16467b97STreehugger Robot * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
1493*16467b97STreehugger Robot * values themselves are not cloned.
1494*16467b97STreehugger Robot *
1495*16467b97STreehugger Robot * @return a shallow copy of this map
1496*16467b97STreehugger Robot */
1497*16467b97STreehugger Robot- (id) copyWithZone:(NSZone *)zone
1498*16467b97STreehugger Robot{
1499*16467b97STreehugger Robot    HashMap *result = nil;
1500*16467b97STreehugger Robot
1501*16467b97STreehugger Robot    //    @try {
1502*16467b97STreehugger Robot    result = [HashMap allocWithZone:zone];
1503*16467b97STreehugger Robot//        result = (HashMap *)[super copyWithZone:zone];
1504*16467b97STreehugger Robot//    }
1505*16467b97STreehugger Robot//    @catch (CloneNotSupportedException * e) {
1506*16467b97STreehugger Robot//    }
1507*16467b97STreehugger Robot    result.ptrBuffer = ptrBuffer;
1508*16467b97STreehugger Robot    result.entrySet = nil;
1509*16467b97STreehugger Robot    //    result.modCount = 0;
1510*16467b97STreehugger Robot    //    result.count = 0;
1511*16467b97STreehugger Robot    //    [result init];
1512*16467b97STreehugger Robot    [result putAllForCreate:self];
1513*16467b97STreehugger Robot    result.count = count;
1514*16467b97STreehugger Robot    result.threshold = threshold;
1515*16467b97STreehugger Robot    result.loadFactor = loadFactor;
1516*16467b97STreehugger Robot    result.modCount = modCount;
1517*16467b97STreehugger Robot    result.entrySet = entrySet;
1518*16467b97STreehugger Robot    return result;
1519*16467b97STreehugger Robot}
1520*16467b97STreehugger Robot
1521*16467b97STreehugger Robot
1522*16467b97STreehugger Robot/**
1523*16467b97STreehugger Robot * Returns a string representation of this map.  The string representation
1524*16467b97STreehugger Robot * consists of a list of key-value mappings in the order returned by the
1525*16467b97STreehugger Robot * map's <tt>entrySet</tt> view's iterator, enclosed in braces
1526*16467b97STreehugger Robot * (<tt>"{}"</tt>).  Adjacent mappings are separated by the characters
1527*16467b97STreehugger Robot * <tt>", "</tt> (comma and space).  Each key-value mapping is rendered as
1528*16467b97STreehugger Robot * the key followed by an equals sign (<tt>"="</tt>) followed by the
1529*16467b97STreehugger Robot * associated value.  Keys and values are converted to strings as by
1530*16467b97STreehugger Robot * {@link String#valueOf(Object)}.
1531*16467b97STreehugger Robot *
1532*16467b97STreehugger Robot * @return a string representation of this map
1533*16467b97STreehugger Robot */
1534*16467b97STreehugger Robot- (NSString *)description
1535*16467b97STreehugger Robot{
1536*16467b97STreehugger Robot    HashIterator *it = [[self entrySet] iterator];
1537*16467b97STreehugger Robot    if (![it hasNext])
1538*16467b97STreehugger Robot        return @"{}";
1539*16467b97STreehugger Robot
1540*16467b97STreehugger Robot    NSMutableString *sb = [NSMutableString stringWithCapacity:40];
1541*16467b97STreehugger Robot    [sb appendString:@"{"];
1542*16467b97STreehugger Robot    while ( YES ) {
1543*16467b97STreehugger Robot        HMEntry *e = [it next];
1544*16467b97STreehugger Robot        NSString *key = e.key;
1545*16467b97STreehugger Robot        id value = e.value;
1546*16467b97STreehugger Robot        [sb appendFormat:@"%@=%@", (key == self ? @"[self Map]" : key), (value == self ? @"[self Map]" : value)];
1547*16467b97STreehugger Robot        if ( ![it hasNext] ) {
1548*16467b97STreehugger Robot            [sb appendString:@"}"];
1549*16467b97STreehugger Robot            return sb;
1550*16467b97STreehugger Robot        }
1551*16467b97STreehugger Robot        [sb appendString:@", "];
1552*16467b97STreehugger Robot    }
1553*16467b97STreehugger Robot}
1554*16467b97STreehugger Robot
1555*16467b97STreehugger Robot/**
1556*16467b97STreehugger Robot * Adds a new entry with the specified key, value and hash code to
1557*16467b97STreehugger Robot * the specified bucket.  It is the responsibility of this
1558*16467b97STreehugger Robot * method to resize the table if appropriate.
1559*16467b97STreehugger Robot *
1560*16467b97STreehugger Robot * Subclass overrides this to alter the behavior of put method.
1561*16467b97STreehugger Robot */
1562*16467b97STreehugger Robot- (void) addEntry:(NSInteger)hash key:(NSString *)key value:(id)value bucketIndex:(NSInteger)bucketIndex
1563*16467b97STreehugger Robot{
1564*16467b97STreehugger Robot    HMEntry *e = (HMEntry *)ptrBuffer[bucketIndex];
1565*16467b97STreehugger Robot    ptrBuffer[bucketIndex] = [[HMEntry alloc] init:hash key:key value:value next:e];
1566*16467b97STreehugger Robot    if (count++ >= threshold)
1567*16467b97STreehugger Robot        [self resize:2 * BuffSize];
1568*16467b97STreehugger Robot}
1569*16467b97STreehugger Robot
1570*16467b97STreehugger Robot/**
1571*16467b97STreehugger Robot * Like addEntry except that this version is used when creating entries
1572*16467b97STreehugger Robot * as part of Map construction or "pseudo-construction" (cloning,
1573*16467b97STreehugger Robot * deserialization).  This version needn't worry about resizing the table.
1574*16467b97STreehugger Robot *
1575*16467b97STreehugger Robot * Subclass overrides this to alter the behavior of HashMap(Map),
1576*16467b97STreehugger Robot * clone, and readObject.
1577*16467b97STreehugger Robot */
1578*16467b97STreehugger Robot- (void) createEntry:(NSInteger)hash key:(NSString *)key value:(id)value bucketIndex:(NSInteger)bucketIndex
1579*16467b97STreehugger Robot{
1580*16467b97STreehugger Robot    HMEntry *e = (HMEntry *)ptrBuffer[bucketIndex];
1581*16467b97STreehugger Robot    ptrBuffer[bucketIndex] = [[HMEntry alloc] init:hash key:key value:value next:e];
1582*16467b97STreehugger Robot    count++;
1583*16467b97STreehugger Robot}
1584*16467b97STreehugger Robot
1585*16467b97STreehugger Robot- (HMKeyIterator *) newKeyIterator
1586*16467b97STreehugger Robot{
1587*16467b97STreehugger Robot    return [HMKeyIterator newIterator:self];
1588*16467b97STreehugger Robot}
1589*16467b97STreehugger Robot
1590*16467b97STreehugger Robot- (HMValueIterator *) newValueIterator
1591*16467b97STreehugger Robot{
1592*16467b97STreehugger Robot    return [HMValueIterator newIterator:self];
1593*16467b97STreehugger Robot}
1594*16467b97STreehugger Robot
1595*16467b97STreehugger Robot- (HMEntryIterator *) newEntryIterator
1596*16467b97STreehugger Robot{
1597*16467b97STreehugger Robot    return [HMEntryIterator newIterator:self];
1598*16467b97STreehugger Robot}
1599*16467b97STreehugger Robot
1600*16467b97STreehugger Robot
1601*16467b97STreehugger Robot/**
1602*16467b97STreehugger Robot * Returns a {@link Set} view of the keys contained in this map.
1603*16467b97STreehugger Robot * The set is backed by the map, so changes to the map are
1604*16467b97STreehugger Robot * reflected in the set, and vice-versa.  If the map is modified
1605*16467b97STreehugger Robot * while an iteration over the set is in progress (except through
1606*16467b97STreehugger Robot * the iterator's own <tt>remove</tt> operation), the results of
1607*16467b97STreehugger Robot * the iteration are undefined.  The set supports element removal,
1608*16467b97STreehugger Robot * which removes the corresponding mapping from the map, via the
1609*16467b97STreehugger Robot * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
1610*16467b97STreehugger Robot * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
1611*16467b97STreehugger Robot * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
1612*16467b97STreehugger Robot * operations.
1613*16467b97STreehugger Robot */
1614*16467b97STreehugger Robot- (HMKeySet *) keySet
1615*16467b97STreehugger Robot{
1616*16467b97STreehugger Robot    HMKeySet *ks = keySet;
1617*16467b97STreehugger Robot    return (ks != nil ? ks : (keySet = [HMKeySet newKeySet:self]));
1618*16467b97STreehugger Robot}
1619*16467b97STreehugger Robot
1620*16467b97STreehugger Robot
1621*16467b97STreehugger Robot/**
1622*16467b97STreehugger Robot * Returns a {@link Collection} view of the values contained in this map.
1623*16467b97STreehugger Robot * The collection is backed by the map, so changes to the map are
1624*16467b97STreehugger Robot * reflected in the collection, and vice-versa.  If the map is
1625*16467b97STreehugger Robot * modified while an iteration over the collection is in progress
1626*16467b97STreehugger Robot * (except through the iterator's own <tt>remove</tt> operation),
1627*16467b97STreehugger Robot * the results of the iteration are undefined.  The collection
1628*16467b97STreehugger Robot * supports element removal, which removes the corresponding
1629*16467b97STreehugger Robot * mapping from the map, via the <tt>Iterator.remove</tt>,
1630*16467b97STreehugger Robot * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
1631*16467b97STreehugger Robot * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
1632*16467b97STreehugger Robot * support the <tt>add</tt> or <tt>addAll</tt> operations.
1633*16467b97STreehugger Robot */
1634*16467b97STreehugger Robot- (Values *) values
1635*16467b97STreehugger Robot{
1636*16467b97STreehugger Robot    Values *vs = values;
1637*16467b97STreehugger Robot    return (vs != nil ? vs : (values = [Values newValueSet:self]));
1638*16467b97STreehugger Robot}
1639*16467b97STreehugger Robot
1640*16467b97STreehugger Robot
1641*16467b97STreehugger Robot/**
1642*16467b97STreehugger Robot * Returns a {@link Set} view of the mappings contained in this map.
1643*16467b97STreehugger Robot * The set is backed by the map, so changes to the map are
1644*16467b97STreehugger Robot * reflected in the set, and vice-versa.  If the map is modified
1645*16467b97STreehugger Robot * while an iteration over the set is in progress (except through
1646*16467b97STreehugger Robot * the iterator's own <tt>remove</tt> operation, or through the
1647*16467b97STreehugger Robot * <tt>setValue</tt> operation on a map entry returned by the
1648*16467b97STreehugger Robot * iterator) the results of the iteration are undefined.  The set
1649*16467b97STreehugger Robot * supports element removal, which removes the corresponding
1650*16467b97STreehugger Robot * mapping from the map, via the <tt>Iterator.remove</tt>,
1651*16467b97STreehugger Robot * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
1652*16467b97STreehugger Robot * <tt>clear</tt> operations.  It does not support the
1653*16467b97STreehugger Robot * <tt>add</tt> or <tt>addAll</tt> operations.
1654*16467b97STreehugger Robot *
1655*16467b97STreehugger Robot * @return a set view of the mappings contained in this map
1656*16467b97STreehugger Robot */
1657*16467b97STreehugger Robot- (HMEntrySet *) entrySet0
1658*16467b97STreehugger Robot{
1659*16467b97STreehugger Robot    HMEntrySet *es = entrySet;
1660*16467b97STreehugger Robot    return es != nil ? es : (entrySet = [HMEntrySet newEntrySet:self]);
1661*16467b97STreehugger Robot}
1662*16467b97STreehugger Robot
1663*16467b97STreehugger Robot- (HMEntrySet *) entrySet
1664*16467b97STreehugger Robot{
1665*16467b97STreehugger Robot    return [self entrySet0];
1666*16467b97STreehugger Robot}
1667*16467b97STreehugger Robot
1668*16467b97STreehugger Robot
1669*16467b97STreehugger Robot/**
1670*16467b97STreehugger Robot * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
1671*16467b97STreehugger Robot * serialize it).
1672*16467b97STreehugger Robot *
1673*16467b97STreehugger Robot * @serialData The <i>capacity</i> of the HashMap (the length of the
1674*16467b97STreehugger Robot * bucket array) is emitted (NSInteger), followed by the
1675*16467b97STreehugger Robot * <i>count</i> (an NSInteger, the number of key-value
1676*16467b97STreehugger Robot * mappings), followed by the key (Object) and value (Object)
1677*16467b97STreehugger Robot * for each key-value mapping.  The key-value mappings are
1678*16467b97STreehugger Robot * emitted in no particular order.
1679*16467b97STreehugger Robot */
1680*16467b97STreehugger Robot- (void) writeObject:(NSOutputStream *)s
1681*16467b97STreehugger Robot{
1682*16467b97STreehugger Robot/*
1683*16467b97STreehugger Robot    NSEnumerator * i = (count > 0) ? [[self entrySet0] iterator] : nil;
1684*16467b97STreehugger Robot    [s defaultWriteObject];
1685*16467b97STreehugger Robot    [s writeInt:[buffer length]];
1686*16467b97STreehugger Robot    [s writeInt:count];
1687*16467b97STreehugger Robot    if (i != nil) {
1688*16467b97STreehugger Robot        while ([i hasNext]) {
1689*16467b97STreehugger Robot            HMEntry *e = [i nextObject];
1690*16467b97STreehugger Robot            [s writeObject:[e key]];
1691*16467b97STreehugger Robot            [s writeObject:[e value]];
1692*16467b97STreehugger Robot        }
1693*16467b97STreehugger Robot
1694*16467b97STreehugger Robot    }
1695*16467b97STreehugger Robot */
1696*16467b97STreehugger Robot}
1697*16467b97STreehugger Robot
1698*16467b97STreehugger Robot
1699*16467b97STreehugger Robot/**
1700*16467b97STreehugger Robot * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
1701*16467b97STreehugger Robot * deserialize it).
1702*16467b97STreehugger Robot */
1703*16467b97STreehugger Robot- (void) readObject:(NSInputStream *)s
1704*16467b97STreehugger Robot{
1705*16467b97STreehugger Robot/*
1706*16467b97STreehugger Robot    [s defaultReadObject];
1707*16467b97STreehugger Robot    NSInteger numBuckets = [s readInt];
1708*16467b97STreehugger Robot    ptrBuffer = [NSArray array];
1709*16467b97STreehugger Robot    [self init];
1710*16467b97STreehugger Robot    NSInteger count = [s readInt];
1711*16467b97STreehugger Robot
1712*16467b97STreehugger Robot    for (NSInteger i = 0; i < count; i++) {
1713*16467b97STreehugger Robot        NSString * key = (NSString *)[s readObject];
1714*16467b97STreehugger Robot        id value = (id)[s readObject];
1715*16467b97STreehugger Robot        [self putForCreate:key value:value];
1716*16467b97STreehugger Robot    }
1717*16467b97STreehugger Robot */
1718*16467b97STreehugger Robot}
1719*16467b97STreehugger Robot
1720*16467b97STreehugger Robot- (NSInteger) capacity
1721*16467b97STreehugger Robot{
1722*16467b97STreehugger Robot    return Capacity;
1723*16467b97STreehugger Robot}
1724*16467b97STreehugger Robot
1725*16467b97STreehugger Robot- (float) loadFactor
1726*16467b97STreehugger Robot{
1727*16467b97STreehugger Robot    return loadFactor;
1728*16467b97STreehugger Robot}
1729*16467b97STreehugger Robot
1730*16467b97STreehugger Robot/* this will never link into the chain
1731*16467b97STreehugger Robot */
1732*16467b97STreehugger Robot- (void) setObject:(id)aRule atIndex:(NSInteger)idx
1733*16467b97STreehugger Robot{
1734*16467b97STreehugger Robot    if ( idx >= Capacity ) {
1735*16467b97STreehugger Robot        idx %= Capacity;
1736*16467b97STreehugger Robot    }
1737*16467b97STreehugger Robot    if ( aRule != ptrBuffer[idx] ) {
1738*16467b97STreehugger Robot        if ( ptrBuffer[idx] ) [ptrBuffer[idx] release];
1739*16467b97STreehugger Robot        [aRule retain];
1740*16467b97STreehugger Robot    }
1741*16467b97STreehugger Robot    ptrBuffer[idx] = aRule;
1742*16467b97STreehugger Robot}
1743*16467b97STreehugger Robot
1744*16467b97STreehugger Robot- (void)putName:(NSString *)name Node:(id)aNode
1745*16467b97STreehugger Robot{
1746*16467b97STreehugger Robot    MapElement *np;
1747*16467b97STreehugger Robot
1748*16467b97STreehugger Robot    np = [self lookup:name Scope:0 ];
1749*16467b97STreehugger Robot    if ( np == nil ) {
1750*16467b97STreehugger Robot        np = [MapElement newMapElementWithName:name Node:aNode];
1751*16467b97STreehugger Robot        if ( ptrBuffer[LastHash] )
1752*16467b97STreehugger Robot            [ptrBuffer[LastHash] release];
1753*16467b97STreehugger Robot        [np retain];
1754*16467b97STreehugger Robot        np.fNext = ptrBuffer[ LastHash ];
1755*16467b97STreehugger Robot        ptrBuffer[ LastHash ] = np;
1756*16467b97STreehugger Robot    }
1757*16467b97STreehugger Robot    return;
1758*16467b97STreehugger Robot}
1759*16467b97STreehugger Robot
1760*16467b97STreehugger Robot- (NSEnumerator *)objectEnumerator
1761*16467b97STreehugger Robot{
1762*16467b97STreehugger Robot#pragma mark fix this its broken
1763*16467b97STreehugger Robot    NSEnumerator *anEnumerator;
1764*16467b97STreehugger Robot
1765*16467b97STreehugger Robot    itIndex = 0;
1766*16467b97STreehugger Robot    return anEnumerator;
1767*16467b97STreehugger Robot}
1768*16467b97STreehugger Robot
1769*16467b97STreehugger Robot- (BOOL)hasNext
1770*16467b97STreehugger Robot{
1771*16467b97STreehugger Robot    if (self && [self count] < Capacity-1) {
1772*16467b97STreehugger Robot        return YES;
1773*16467b97STreehugger Robot    }
1774*16467b97STreehugger Robot    return NO;
1775*16467b97STreehugger Robot}
1776*16467b97STreehugger Robot
1777*16467b97STreehugger Robot- (MapElement *)nextObject
1778*16467b97STreehugger Robot{
1779*16467b97STreehugger Robot    if (self && itIndex < Capacity-1) {
1780*16467b97STreehugger Robot        return ptrBuffer[itIndex];
1781*16467b97STreehugger Robot    }
1782*16467b97STreehugger Robot    return nil;
1783*16467b97STreehugger Robot}
1784*16467b97STreehugger Robot
1785*16467b97STreehugger Robot@end
1786*16467b97STreehugger Robot
1787