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