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