1 /******************************************************************************* 2 * Copyright (c) 2016 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * 14 *******************************************************************************/ 15 package org.eclipse.jdt.internal.compiler.util; 16 17 import org.eclipse.jdt.core.compiler.CharOperation; 18 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; 19 20 public final class HashtableOfModule { 21 // to avoid using Enumerations, walk the individual tables skipping nulls 22 public char[] keyTable[]; 23 public ModuleBinding valueTable[]; 24 25 public int elementSize; // number of elements in the table 26 int threshold; HashtableOfModule()27 public HashtableOfModule() { 28 this(3); // usually not very large 29 } HashtableOfModule(int size)30 public HashtableOfModule(int size) { 31 this.elementSize = 0; 32 this.threshold = size; // size represents the expected number of elements 33 int extraRoom = (int) (size * 1.75f); 34 if (this.threshold == extraRoom) 35 extraRoom++; 36 this.keyTable = new char[extraRoom][]; 37 this.valueTable = new ModuleBinding[extraRoom]; 38 } containsKey(char[] key)39 public boolean containsKey(char[] key) { 40 int length = this.keyTable.length, 41 index = CharOperation.hashCode(key) % length; 42 int keyLength = key.length; 43 char[] currentKey; 44 while ((currentKey = this.keyTable[index]) != null) { 45 if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) 46 return true; 47 if (++index == length) { 48 index = 0; 49 } 50 } 51 return false; 52 } get(char[] key)53 public ModuleBinding get(char[] key) { 54 int length = this.keyTable.length, 55 index = CharOperation.hashCode(key) % length; 56 int keyLength = key.length; 57 char[] currentKey; 58 while ((currentKey = this.keyTable[index]) != null) { 59 if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) 60 return this.valueTable[index]; 61 if (++index == length) { 62 index = 0; 63 } 64 } 65 return null; 66 } put(char[] key, ModuleBinding value)67 public ModuleBinding put(char[] key, ModuleBinding value) { 68 int length = this.keyTable.length, 69 index = CharOperation.hashCode(key) % length; 70 int keyLength = key.length; 71 char[] currentKey; 72 while ((currentKey = this.keyTable[index]) != null) { 73 if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) 74 return this.valueTable[index] = value; 75 if (++index == length) { 76 index = 0; 77 } 78 } 79 this.keyTable[index] = key; 80 this.valueTable[index] = value; 81 82 // assumes the threshold is never equal to the size of the table 83 if (++this.elementSize > this.threshold) 84 rehash(); 85 return value; 86 } rehash()87 private void rehash() { 88 HashtableOfModule newHashtable = new HashtableOfModule(this.elementSize * 2); // double the number of expected elements 89 char[] currentKey; 90 for (int i = this.keyTable.length; --i >= 0;) 91 if ((currentKey = this.keyTable[i]) != null) 92 newHashtable.put(currentKey, this.valueTable[i]); 93 94 this.keyTable = newHashtable.keyTable; 95 this.valueTable = newHashtable.valueTable; 96 this.threshold = newHashtable.threshold; 97 } size()98 public int size() { 99 return this.elementSize; 100 } 101 @Override toString()102 public String toString() { 103 String s = ""; //$NON-NLS-1$ 104 ModuleBinding pkg; 105 for (int i = 0, length = this.valueTable.length; i < length; i++) 106 if ((pkg = this.valueTable[i]) != null) 107 s += pkg.toString() + "\n"; //$NON-NLS-1$ 108 return s; 109 } 110 } 111