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