xref: /aosp_15_r20/external/antlr/runtime/ObjC/Framework/LinkedHashMap.m (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot#import <Foundation/Foundation.h>
2*16467b97STreehugger Robot#import "AMutableArray.h"
3*16467b97STreehugger Robot#import "LinkedHashMap.h"
4*16467b97STreehugger Robot#import "RuntimeException.h"
5*16467b97STreehugger Robot
6*16467b97STreehugger Robotextern NSInteger const DEFAULT_INITIAL_CAPACITY;
7*16467b97STreehugger Robotextern float const DEFAULT_LOAD_FACTOR;
8*16467b97STreehugger Robot
9*16467b97STreehugger Robot@implementation LHMEntry
10*16467b97STreehugger Robot
11*16467b97STreehugger Robot@synthesize before;
12*16467b97STreehugger Robot@synthesize after;
13*16467b97STreehugger Robot@synthesize accessOrder;
14*16467b97STreehugger Robot
15*16467b97STreehugger Robot- (id) newEntry:(NSInteger)aHash key:(NSString *)aKey value:(id)aValue next:(LHMEntry *)aNext
16*16467b97STreehugger Robot{
17*16467b97STreehugger Robot    return [[LHMEntry alloc] init:aHash key:aKey value:aValue next:aNext];
18*16467b97STreehugger Robot}
19*16467b97STreehugger Robot
20*16467b97STreehugger Robot- (id) init:(NSInteger)aHash key:(NSString *)aKey value:(id)aValue next:(LHMEntry *)aNext
21*16467b97STreehugger Robot{
22*16467b97STreehugger Robot    self = [super init:aHash key:aKey value:aValue next:aNext];
23*16467b97STreehugger Robot    if (self) {
24*16467b97STreehugger Robot    }
25*16467b97STreehugger Robot    return self;
26*16467b97STreehugger Robot}
27*16467b97STreehugger Robot
28*16467b97STreehugger Robot
29*16467b97STreehugger Robot- (void) dealloc
30*16467b97STreehugger Robot{
31*16467b97STreehugger Robot    [before release];
32*16467b97STreehugger Robot    [after release];
33*16467b97STreehugger Robot    [super dealloc];
34*16467b97STreehugger Robot}
35*16467b97STreehugger Robot
36*16467b97STreehugger Robot/**
37*16467b97STreehugger Robot * Removes this entry from the linked list.
38*16467b97STreehugger Robot */
39*16467b97STreehugger Robot- (void) removeEntry
40*16467b97STreehugger Robot{
41*16467b97STreehugger Robot    before.after = after;
42*16467b97STreehugger Robot    after.before = before;
43*16467b97STreehugger Robot}
44*16467b97STreehugger Robot
45*16467b97STreehugger Robot
46*16467b97STreehugger Robot/**
47*16467b97STreehugger Robot * Inserts this entry before the specified existing entry in the list.
48*16467b97STreehugger Robot */
49*16467b97STreehugger Robot- (void) addBefore:(LHMEntry *)existingEntry
50*16467b97STreehugger Robot{
51*16467b97STreehugger Robot    after = [existingEntry retain];
52*16467b97STreehugger Robot    before = [existingEntry.before retain];
53*16467b97STreehugger Robot    before.after = [self retain];
54*16467b97STreehugger Robot    after.before = [self retain];
55*16467b97STreehugger Robot}
56*16467b97STreehugger Robot
57*16467b97STreehugger Robot
58*16467b97STreehugger Robot/**
59*16467b97STreehugger Robot * This method is invoked by the superclass whenever the value
60*16467b97STreehugger Robot * of a pre-existing entry is read by Map.get or modified by Map.set.
61*16467b97STreehugger Robot * If the enclosing Map is access-ordered, it moves the entry
62*16467b97STreehugger Robot * to the end of the list; otherwise, it does nothing.
63*16467b97STreehugger Robot */
64*16467b97STreehugger Robot- (void) recordAccess:(LinkedHashMap *)m
65*16467b97STreehugger Robot{
66*16467b97STreehugger Robot    LinkedHashMap *lhm = (LinkedHashMap *)m;
67*16467b97STreehugger Robot    if (lhm.accessOrder) {
68*16467b97STreehugger Robot        lhm.modCount++;
69*16467b97STreehugger Robot        [self removeEntry];
70*16467b97STreehugger Robot        [self addBefore:lhm.header];
71*16467b97STreehugger Robot    }
72*16467b97STreehugger Robot}
73*16467b97STreehugger Robot
74*16467b97STreehugger Robot- (void) recordRemoval:(LinkedHashMap *)m
75*16467b97STreehugger Robot{
76*16467b97STreehugger Robot    [self removeEntry];
77*16467b97STreehugger Robot}
78*16467b97STreehugger Robot
79*16467b97STreehugger Robot@end
80*16467b97STreehugger Robot
81*16467b97STreehugger Robot@implementation LinkedHashIterator
82*16467b97STreehugger Robot
83*16467b97STreehugger Robot@synthesize nextEntry;
84*16467b97STreehugger Robot@synthesize lastReturned;
85*16467b97STreehugger Robot@synthesize lhm;
86*16467b97STreehugger Robot
87*16467b97STreehugger Robot+ (LinkedHashIterator *) newIterator:(LinkedHashMap *)aLHM
88*16467b97STreehugger Robot{
89*16467b97STreehugger Robot    return [[LinkedHashIterator alloc] init:aLHM];
90*16467b97STreehugger Robot}
91*16467b97STreehugger Robot
92*16467b97STreehugger Robot- (id) init:(LinkedHashMap *)aLHM
93*16467b97STreehugger Robot{
94*16467b97STreehugger Robot    self = [super init];
95*16467b97STreehugger Robot    if ( self ) {
96*16467b97STreehugger Robot        lhm = aLHM;
97*16467b97STreehugger Robot        nextEntry = lhm.header.after;
98*16467b97STreehugger Robot        lastReturned = nil;
99*16467b97STreehugger Robot        expectedModCount = lhm.modCount;
100*16467b97STreehugger Robot/*
101*16467b97STreehugger Robot        AMutableArray *a = [AMutableArray arrayWithCapacity:lhm.Capacity];
102*16467b97STreehugger Robot        LHMEntry *tmp = lhm.header.after;
103*16467b97STreehugger Robot        while ( tmp != lhm.header ) {
104*16467b97STreehugger Robot            [a addObject:tmp];
105*16467b97STreehugger Robot            tmp = tmp.after;
106*16467b97STreehugger Robot        }
107*16467b97STreehugger Robot        anArray = [NSArray arrayWithArray:a];
108*16467b97STreehugger Robot */
109*16467b97STreehugger Robot    }
110*16467b97STreehugger Robot    return self;
111*16467b97STreehugger Robot}
112*16467b97STreehugger Robot
113*16467b97STreehugger Robot- (BOOL) hasNext
114*16467b97STreehugger Robot{
115*16467b97STreehugger Robot    return nextEntry != lhm.header;
116*16467b97STreehugger Robot}
117*16467b97STreehugger Robot
118*16467b97STreehugger Robot- (void) remove
119*16467b97STreehugger Robot{
120*16467b97STreehugger Robot    if (lastReturned == nil)
121*16467b97STreehugger Robot        @throw [[IllegalStateException newException] autorelease];
122*16467b97STreehugger Robot    if (lhm.modCount != expectedModCount)
123*16467b97STreehugger Robot        @throw [[ConcurrentModificationException newException:@"Unexpected modCount"] autorelease];
124*16467b97STreehugger Robot    [lhm remove:(NSString *)(lastReturned.key)];
125*16467b97STreehugger Robot    lastReturned = nil;
126*16467b97STreehugger Robot    expectedModCount = lhm.modCount;
127*16467b97STreehugger Robot}
128*16467b97STreehugger Robot
129*16467b97STreehugger Robot- (LHMEntry *) nextEntry
130*16467b97STreehugger Robot{
131*16467b97STreehugger Robot    if (lhm.modCount != expectedModCount)
132*16467b97STreehugger Robot        @throw [[ConcurrentModificationException newException:@"Unexpected modCount"] autorelease];
133*16467b97STreehugger Robot    if (nextEntry == lhm.header)
134*16467b97STreehugger Robot        @throw [[[NoSuchElementException alloc] init] autorelease];
135*16467b97STreehugger Robot    LHMEntry * e = lastReturned = nextEntry;
136*16467b97STreehugger Robot    nextEntry = e.after;
137*16467b97STreehugger Robot    return e;
138*16467b97STreehugger Robot}
139*16467b97STreehugger Robot
140*16467b97STreehugger Robot- (void) dealloc
141*16467b97STreehugger Robot{
142*16467b97STreehugger Robot    [nextEntry release];
143*16467b97STreehugger Robot    [lastReturned release];
144*16467b97STreehugger Robot    [super dealloc];
145*16467b97STreehugger Robot}
146*16467b97STreehugger Robot
147*16467b97STreehugger Robot@end
148*16467b97STreehugger Robot
149*16467b97STreehugger Robot@implementation LHMKeyIterator
150*16467b97STreehugger Robot+ (LHMKeyIterator *)newIterator:(LinkedHashMap *)aLHM
151*16467b97STreehugger Robot{
152*16467b97STreehugger Robot    return [[LHMKeyIterator alloc] init:aLHM];
153*16467b97STreehugger Robot}
154*16467b97STreehugger Robot
155*16467b97STreehugger Robot- (id) init:(LinkedHashMap *)aLHM
156*16467b97STreehugger Robot{
157*16467b97STreehugger Robot    self = [super init:aLHM];
158*16467b97STreehugger Robot    if ( self ) {
159*16467b97STreehugger Robot    }
160*16467b97STreehugger Robot    return self;
161*16467b97STreehugger Robot}
162*16467b97STreehugger Robot
163*16467b97STreehugger Robot- (NSString *) next
164*16467b97STreehugger Robot{
165*16467b97STreehugger Robot    return [self nextEntry].key;
166*16467b97STreehugger Robot}
167*16467b97STreehugger Robot
168*16467b97STreehugger Robot@end
169*16467b97STreehugger Robot
170*16467b97STreehugger Robot@implementation LHMValueIterator
171*16467b97STreehugger Robot+ (LHMValueIterator *)newIterator:(LinkedHashMap *)aLHM
172*16467b97STreehugger Robot{
173*16467b97STreehugger Robot    return [[LHMValueIterator alloc] init:aLHM];
174*16467b97STreehugger Robot}
175*16467b97STreehugger Robot
176*16467b97STreehugger Robot- (id) init:(LinkedHashMap *)aLHM
177*16467b97STreehugger Robot{
178*16467b97STreehugger Robot    self = [super init:aLHM];
179*16467b97STreehugger Robot    if ( self ) {
180*16467b97STreehugger Robot    }
181*16467b97STreehugger Robot    return self;
182*16467b97STreehugger Robot}
183*16467b97STreehugger Robot
184*16467b97STreehugger Robot- (id) next
185*16467b97STreehugger Robot{
186*16467b97STreehugger Robot    return [self nextEntry].value;
187*16467b97STreehugger Robot}
188*16467b97STreehugger Robot
189*16467b97STreehugger Robot@end
190*16467b97STreehugger Robot
191*16467b97STreehugger Robot@implementation LHMEntryIterator
192*16467b97STreehugger Robot+ (LHMEntryIterator *)newIterator:(LinkedHashMap *)aLHM
193*16467b97STreehugger Robot{
194*16467b97STreehugger Robot    return [[LHMEntryIterator alloc] init:aLHM];
195*16467b97STreehugger Robot}
196*16467b97STreehugger Robot
197*16467b97STreehugger Robot- (id) init:(LinkedHashMap *)aLHM
198*16467b97STreehugger Robot{
199*16467b97STreehugger Robot    self = [super init:aLHM];
200*16467b97STreehugger Robot    if ( self ) {
201*16467b97STreehugger Robot    }
202*16467b97STreehugger Robot    return self;
203*16467b97STreehugger Robot}
204*16467b97STreehugger Robot
205*16467b97STreehugger Robot- (LHMEntry *) next
206*16467b97STreehugger Robot{
207*16467b97STreehugger Robot    return [self nextEntry];
208*16467b97STreehugger Robot}
209*16467b97STreehugger Robot
210*16467b97STreehugger Robot@end
211*16467b97STreehugger Robot
212*16467b97STreehugger Robot//long const serialVersionUID = 3801124242820219131L;
213*16467b97STreehugger Robot
214*16467b97STreehugger Robot@implementation LinkedHashMap
215*16467b97STreehugger Robot
216*16467b97STreehugger Robot@synthesize header;
217*16467b97STreehugger Robot@synthesize accessOrder;
218*16467b97STreehugger Robot
219*16467b97STreehugger Robot/**
220*16467b97STreehugger Robot * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
221*16467b97STreehugger Robot * with the specified initial capacity and load factor.
222*16467b97STreehugger Robot *
223*16467b97STreehugger Robot * @param  initialCapacity the initial capacity
224*16467b97STreehugger Robot * @param  loadFactor      the load factor
225*16467b97STreehugger Robot * @throws IllegalArgumentException if the initial capacity is negative
226*16467b97STreehugger Robot * or the load factor is nonpositive
227*16467b97STreehugger Robot */
228*16467b97STreehugger Robot+ (id) newLinkedHashMap:(NSInteger)anInitialCapacity
229*16467b97STreehugger Robot             loadFactor:(float)loadFactor
230*16467b97STreehugger Robot            accessOrder:(BOOL)anAccessOrder
231*16467b97STreehugger Robot{
232*16467b97STreehugger Robot    return [[LinkedHashMap alloc] init:anInitialCapacity
233*16467b97STreehugger Robot                            loadFactor:loadFactor
234*16467b97STreehugger Robot                           accessOrder:(BOOL)anAccessOrder];
235*16467b97STreehugger Robot}
236*16467b97STreehugger Robot
237*16467b97STreehugger Robot+ (id) newLinkedHashMap:(NSInteger)anInitialCapacity loadFactor:(float)loadFactor
238*16467b97STreehugger Robot{
239*16467b97STreehugger Robot    return [[LinkedHashMap alloc] init:anInitialCapacity loadFactor:loadFactor];
240*16467b97STreehugger Robot}
241*16467b97STreehugger Robot
242*16467b97STreehugger Robot+ (id) newLinkedHashMap:(NSInteger)anInitialCapacity
243*16467b97STreehugger Robot{
244*16467b97STreehugger Robot    return [[LinkedHashMap alloc] init:anInitialCapacity loadFactor:DEFAULT_LOAD_FACTOR];
245*16467b97STreehugger Robot}
246*16467b97STreehugger Robot
247*16467b97STreehugger Robot/**
248*16467b97STreehugger Robot * Constructs an empty <tt>LinkedHashMap</tt> instance with the
249*16467b97STreehugger Robot * specified initial capacity, load factor and ordering mode.
250*16467b97STreehugger Robot *
251*16467b97STreehugger Robot * @param  initialCapacity the initial capacity
252*16467b97STreehugger Robot * @param  loadFactor      the load factor
253*16467b97STreehugger Robot * @param  accessOrder     the ordering mode - <tt>true</tt> for
254*16467b97STreehugger Robot * access-order, <tt>false</tt> for insertion-order
255*16467b97STreehugger Robot * @throws IllegalArgumentException if the initial capacity is negative
256*16467b97STreehugger Robot * or the load factor is nonpositive
257*16467b97STreehugger Robot */
258*16467b97STreehugger Robot- (id) init:(NSInteger)anInitialCapacity loadFactor:(float)aLoadFactor accessOrder:(BOOL)anAccessOrder
259*16467b97STreehugger Robot{
260*16467b97STreehugger Robot    self = [super init:anInitialCapacity loadFactor:aLoadFactor];
261*16467b97STreehugger Robot    if ( self ) {
262*16467b97STreehugger Robot        accessOrder = anAccessOrder;
263*16467b97STreehugger Robot        header = [[[LHMEntry alloc] init:-1 key:nil value:nil next:nil] retain];
264*16467b97STreehugger Robot        header.before = header.after = header;
265*16467b97STreehugger Robot    }
266*16467b97STreehugger Robot    return self;
267*16467b97STreehugger Robot}
268*16467b97STreehugger Robot
269*16467b97STreehugger Robot- (id) init:(NSInteger)anInitialCapacity loadFactor:(float)aLoadFactor
270*16467b97STreehugger Robot{
271*16467b97STreehugger Robot    self = [super init:anInitialCapacity loadFactor:aLoadFactor];
272*16467b97STreehugger Robot    if ( self ) {
273*16467b97STreehugger Robot        accessOrder = NO;
274*16467b97STreehugger Robot        header = [[[LHMEntry alloc] init:-1 key:nil value:nil next:nil] retain];
275*16467b97STreehugger Robot        header.before = header.after = header;
276*16467b97STreehugger Robot    }
277*16467b97STreehugger Robot    return self;
278*16467b97STreehugger Robot}
279*16467b97STreehugger Robot
280*16467b97STreehugger Robot/**
281*16467b97STreehugger Robot * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
282*16467b97STreehugger Robot * with the specified initial capacity and a default load factor (0.75).
283*16467b97STreehugger Robot *
284*16467b97STreehugger Robot * @param  initialCapacity the initial capacity
285*16467b97STreehugger Robot * @throws IllegalArgumentException if the initial capacity is negative
286*16467b97STreehugger Robot */
287*16467b97STreehugger Robot- (id) init:(NSInteger)initialCapacity
288*16467b97STreehugger Robot{
289*16467b97STreehugger Robot    self = [super init:initialCapacity loadFactor:DEFAULT_LOAD_FACTOR];
290*16467b97STreehugger Robot    if ( self ) {
291*16467b97STreehugger Robot        accessOrder = NO;
292*16467b97STreehugger Robot        header = [[[LHMEntry alloc] init:-1 key:nil value:nil next:nil] retain];
293*16467b97STreehugger Robot        header.before = header.after = header;
294*16467b97STreehugger Robot    }
295*16467b97STreehugger Robot    return self;
296*16467b97STreehugger Robot}
297*16467b97STreehugger Robot
298*16467b97STreehugger Robot/**
299*16467b97STreehugger Robot * Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
300*16467b97STreehugger Robot * the same mappings as the specified map.  The <tt>LinkedHashMap</tt>
301*16467b97STreehugger Robot * instance is created with a default load factor (0.75) and an initial
302*16467b97STreehugger Robot * capacity sufficient to hold the mappings in the specified map.
303*16467b97STreehugger Robot *
304*16467b97STreehugger Robot * @param  m the map whose mappings are to be placed in this map
305*16467b97STreehugger Robot * @throws NullPointerException if the specified map is null
306*16467b97STreehugger Robot */
307*16467b97STreehugger Robot- (id) initWithM:(LinkedHashMap *)m
308*16467b97STreehugger Robot{
309*16467b97STreehugger Robot    self = [super initWithM:m];
310*16467b97STreehugger Robot    if ( self ) {
311*16467b97STreehugger Robot        accessOrder = NO;
312*16467b97STreehugger Robot        header = [[[LHMEntry alloc] init:-1 key:nil value:nil next:nil] retain];
313*16467b97STreehugger Robot        header.before = header.after = header;
314*16467b97STreehugger Robot    }
315*16467b97STreehugger Robot    return self;
316*16467b97STreehugger Robot}
317*16467b97STreehugger Robot
318*16467b97STreehugger Robot/**
319*16467b97STreehugger Robot * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
320*16467b97STreehugger Robot * with the default initial capacity (16) and load factor (0.75).
321*16467b97STreehugger Robot */
322*16467b97STreehugger Robot- (id) init
323*16467b97STreehugger Robot{
324*16467b97STreehugger Robot    self = [super init];
325*16467b97STreehugger Robot    if ( self ) {
326*16467b97STreehugger Robot        accessOrder = NO;
327*16467b97STreehugger Robot        header = [[[LHMEntry alloc] init:-1 key:nil value:nil next:nil] retain];
328*16467b97STreehugger Robot        header.before = header.after = header;
329*16467b97STreehugger Robot    }
330*16467b97STreehugger Robot    return self;
331*16467b97STreehugger Robot}
332*16467b97STreehugger Robot
333*16467b97STreehugger Robot
334*16467b97STreehugger Robot/**
335*16467b97STreehugger Robot * Transfers all entries to new table array.  This method is called
336*16467b97STreehugger Robot * by superclass resize.  It is overridden for performance, as it is
337*16467b97STreehugger Robot * faster to iterate using our linked list.
338*16467b97STreehugger Robot */
339*16467b97STreehugger Robot- (void) transfer:(AMutableArray *)newTable
340*16467b97STreehugger Robot{
341*16467b97STreehugger Robot    NSInteger newCapacity = [newTable count];
342*16467b97STreehugger Robot
343*16467b97STreehugger Robot    for (LHMEntry * e = header.after; e != header; e = e.after) {
344*16467b97STreehugger Robot        NSInteger index = [self indexFor:e.hash length:newCapacity];
345*16467b97STreehugger Robot        e.next = [newTable objectAtIndex:index];
346*16467b97STreehugger Robot        [newTable replaceObjectAtIndex:index withObject:e];
347*16467b97STreehugger Robot    }
348*16467b97STreehugger Robot
349*16467b97STreehugger Robot}
350*16467b97STreehugger Robot
351*16467b97STreehugger Robot/**
352*16467b97STreehugger Robot * Returns <tt>true</tt> if this map maps one or more keys to the
353*16467b97STreehugger Robot * specified value.
354*16467b97STreehugger Robot *
355*16467b97STreehugger Robot * @param value value whose presence in this map is to be tested
356*16467b97STreehugger Robot * @return <tt>true</tt> if this map maps one or more keys to the
357*16467b97STreehugger Robot * specified value
358*16467b97STreehugger Robot */
359*16467b97STreehugger Robot- (BOOL) containsValue:(id)value
360*16467b97STreehugger Robot{
361*16467b97STreehugger Robot    if (value == nil) {
362*16467b97STreehugger Robot
363*16467b97STreehugger Robot        for (LHMEntry * e = header.after; e != header; e = e.after)
364*16467b97STreehugger Robot            if (e.value == nil)
365*16467b97STreehugger Robot                return YES;
366*16467b97STreehugger Robot
367*16467b97STreehugger Robot    }
368*16467b97STreehugger Robot    else {
369*16467b97STreehugger Robot
370*16467b97STreehugger Robot        for (LHMEntry * e = header.after; e != header; e = e.after)
371*16467b97STreehugger Robot            if ([value isEqualTo:e.value])
372*16467b97STreehugger Robot                return YES;
373*16467b97STreehugger Robot
374*16467b97STreehugger Robot    }
375*16467b97STreehugger Robot    return NO;
376*16467b97STreehugger Robot}
377*16467b97STreehugger Robot
378*16467b97STreehugger Robot/**
379*16467b97STreehugger Robot * Returns the value to which the specified key is mapped,
380*16467b97STreehugger Robot * or {@code null} if this map contains no mapping for the key.
381*16467b97STreehugger Robot *
382*16467b97STreehugger Robot * <p>More formally, if this map contains a mapping from a key
383*16467b97STreehugger Robot * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
384*16467b97STreehugger Robot * key.equals(k))}, then this method returns {@code v}; otherwise
385*16467b97STreehugger Robot * it returns {@code null}.  (There can be at most one such mapping.)
386*16467b97STreehugger Robot *
387*16467b97STreehugger Robot * <p>A return value of {@code null} does not <i>necessarily</i>
388*16467b97STreehugger Robot * indicate that the map contains no mapping for the key; it's also
389*16467b97STreehugger Robot * possible that the map explicitly maps the key to {@code null}.
390*16467b97STreehugger Robot * The {@link #containsKey containsKey} operation may be used to
391*16467b97STreehugger Robot * distinguish these two cases.
392*16467b97STreehugger Robot */
393*16467b97STreehugger Robot- (id) get:(NSString *)aKey
394*16467b97STreehugger Robot{
395*16467b97STreehugger Robot    LHMEntry * e = (LHMEntry *)[self getEntry:aKey];
396*16467b97STreehugger Robot    if (e == nil)
397*16467b97STreehugger Robot        return nil;
398*16467b97STreehugger Robot    [e recordAccess:self];
399*16467b97STreehugger Robot    return e.value;
400*16467b97STreehugger Robot}
401*16467b97STreehugger Robot
402*16467b97STreehugger Robot
403*16467b97STreehugger Robot/**
404*16467b97STreehugger Robot * Removes all of the mappings from this map.
405*16467b97STreehugger Robot * The map will be empty after this call returns.
406*16467b97STreehugger Robot */
407*16467b97STreehugger Robot- (void) clear
408*16467b97STreehugger Robot{
409*16467b97STreehugger Robot    [super clear];
410*16467b97STreehugger Robot    header.before = header.after = header;
411*16467b97STreehugger Robot}
412*16467b97STreehugger Robot
413*16467b97STreehugger Robot- (void) dealloc {
414*16467b97STreehugger Robot    [header release];
415*16467b97STreehugger Robot    [super dealloc];
416*16467b97STreehugger Robot}
417*16467b97STreehugger Robot
418*16467b97STreehugger Robot- (LHMEntryIterator *) newEntryIterator
419*16467b97STreehugger Robot{
420*16467b97STreehugger Robot    return [LHMEntryIterator newIterator:self];
421*16467b97STreehugger Robot}
422*16467b97STreehugger Robot
423*16467b97STreehugger Robot- (LHMKeyIterator *) newKeyIterator
424*16467b97STreehugger Robot{
425*16467b97STreehugger Robot    return [LHMKeyIterator newIterator:self];
426*16467b97STreehugger Robot}
427*16467b97STreehugger Robot
428*16467b97STreehugger Robot- (LHMValueIterator *) newValueIterator
429*16467b97STreehugger Robot{
430*16467b97STreehugger Robot    return [LHMValueIterator newIterator:self];
431*16467b97STreehugger Robot}
432*16467b97STreehugger Robot
433*16467b97STreehugger Robot
434*16467b97STreehugger Robot/**
435*16467b97STreehugger Robot * This override alters behavior of superclass put method. It causes newly
436*16467b97STreehugger Robot * allocated entry to get inserted at the end of the linked list and
437*16467b97STreehugger Robot * removes the eldest entry if appropriate.
438*16467b97STreehugger Robot */
439*16467b97STreehugger Robot- (void) addEntry:(NSInteger)aHash key:(NSString *)aKey value:(id)aValue bucketIndex:(NSInteger)aBucketIndex
440*16467b97STreehugger Robot{
441*16467b97STreehugger Robot    [self createEntry:aHash key:aKey value:aValue bucketIndex:aBucketIndex];
442*16467b97STreehugger Robot    LHMEntry * eldest = header.after;
443*16467b97STreehugger Robot    if ([self removeEldestEntry:eldest]) {
444*16467b97STreehugger Robot        [self removeEntryForKey:eldest.key];
445*16467b97STreehugger Robot    }
446*16467b97STreehugger Robot    else {
447*16467b97STreehugger Robot        if (count >= threshold)
448*16467b97STreehugger Robot            [self resize:2 * [buffer length]];
449*16467b97STreehugger Robot    }
450*16467b97STreehugger Robot}
451*16467b97STreehugger Robot
452*16467b97STreehugger Robot
453*16467b97STreehugger Robot/**
454*16467b97STreehugger Robot * This override differs from addEntry in that it doesn't resize the
455*16467b97STreehugger Robot * table or remove the eldest entry.
456*16467b97STreehugger Robot */
457*16467b97STreehugger Robot- (void) createEntry:(NSInteger)aHash key:(NSString *)aKey value:(id)aValue bucketIndex:(NSInteger)bucketIndex
458*16467b97STreehugger Robot{
459*16467b97STreehugger Robot    LHMEntry *old = (LHMEntry *)ptrBuffer[bucketIndex];
460*16467b97STreehugger Robot    LHMEntry *e = [[[LHMEntry alloc] init:aHash key:aKey value:aValue next:old] retain];
461*16467b97STreehugger Robot    ptrBuffer[bucketIndex] = (id)e;
462*16467b97STreehugger Robot    [e addBefore:header];
463*16467b97STreehugger Robot    count++;
464*16467b97STreehugger Robot}
465*16467b97STreehugger Robot
466*16467b97STreehugger Robot
467*16467b97STreehugger Robot/**
468*16467b97STreehugger Robot * Returns <tt>true</tt> if this map should remove its eldest entry.
469*16467b97STreehugger Robot * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
470*16467b97STreehugger Robot * inserting a new entry into the map.  It provides the implementor
471*16467b97STreehugger Robot * with the opportunity to remove the eldest entry each time a new one
472*16467b97STreehugger Robot * is added.  This is useful if the map represents a cache: it allows
473*16467b97STreehugger Robot * the map to reduce memory consumption by deleting stale entries.
474*16467b97STreehugger Robot *
475*16467b97STreehugger Robot * <p>Sample use: this override will allow the map to grow up to 100
476*16467b97STreehugger Robot * entries and then delete the eldest entry each time a new entry is
477*16467b97STreehugger Robot * added, maintaining a steady state of 100 entries.
478*16467b97STreehugger Robot * <pre>
479*16467b97STreehugger Robot * private static final NSInteger MAX_ENTRIES = 100;
480*16467b97STreehugger Robot *
481*16467b97STreehugger Robot * protected boolean removeEldestEntry(Map.LHMEntry eldest) {
482*16467b97STreehugger Robot * return count() > MAX_ENTRIES;
483*16467b97STreehugger Robot * }
484*16467b97STreehugger Robot * </pre>
485*16467b97STreehugger Robot *
486*16467b97STreehugger Robot * <p>This method typically does not modify the map in any way,
487*16467b97STreehugger Robot * instead allowing the map to modify itself as directed by its
488*16467b97STreehugger Robot * return value.  It <i>is</i> permitted for this method to modify
489*16467b97STreehugger Robot * the map directly, but if it does so, it <i>must</i> return
490*16467b97STreehugger Robot * <tt>false</tt> (indicating that the map should not attempt any
491*16467b97STreehugger Robot * further modification).  The effects of returning <tt>true</tt>
492*16467b97STreehugger Robot * after modifying the map from within this method are unspecified.
493*16467b97STreehugger Robot *
494*16467b97STreehugger Robot * <p>This implementation merely returns <tt>false</tt> (so that this
495*16467b97STreehugger Robot * map acts like a normal map - the eldest element is never removed).
496*16467b97STreehugger Robot *
497*16467b97STreehugger Robot * @param    eldest The least recently inserted entry in the map, or if
498*16467b97STreehugger Robot * this is an access-ordered map, the least recently accessed
499*16467b97STreehugger Robot * entry.  This is the entry that will be removed it this
500*16467b97STreehugger Robot * method returns <tt>true</tt>.  If the map was empty prior
501*16467b97STreehugger Robot * to the <tt>put</tt> or <tt>putAll</tt> invocation resulting
502*16467b97STreehugger Robot * in this invocation, this will be the entry that was just
503*16467b97STreehugger Robot * inserted; in other words, if the map contains a single
504*16467b97STreehugger Robot * entry, the eldest entry is also the newest.
505*16467b97STreehugger Robot * @return   <tt>true</tt> if the eldest entry should be removed
506*16467b97STreehugger Robot * from the map; <tt>false</tt> if it should be retained.
507*16467b97STreehugger Robot */
508*16467b97STreehugger Robot- (BOOL) removeEldestEntry:(LHMEntry *)eldest
509*16467b97STreehugger Robot{
510*16467b97STreehugger Robot    return NO;
511*16467b97STreehugger Robot}
512*16467b97STreehugger Robot
513*16467b97STreehugger Robot@end
514