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