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