Home | History | Annotate | Download | only in Framework
      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 
     37 extern NSInteger max(NSInteger a, NSInteger b);
     38 
     39 static 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  */
    438 NSInteger 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  */
    445 NSInteger const MAXIMUM_CAPACITY = 1 << 30;
    446 
    447 /**
    448  * The load factor used when none specified in constructor.
    449  */
    450 float 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