1 /*******************************************************************************
2  * Copyright (c) 2000, 2009 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 package org.eclipse.jdt.internal.compiler.util;
15 
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
18 
19 public final class HashtableOfType {
20 	// to avoid using Enumerations, walk the individual tables skipping nulls
21 	public char[] keyTable[];
22 	public ReferenceBinding valueTable[];
23 
24 	public int elementSize; // number of elements in the table
25 	int threshold;
HashtableOfType()26 public HashtableOfType() {
27 	this(3);
28 }
HashtableOfType(int size)29 public HashtableOfType(int size) {
30 	this.elementSize = 0;
31 	this.threshold = size; // size represents the expected number of elements
32 	int extraRoom = (int) (size * 1.75f);
33 	if (this.threshold == extraRoom)
34 		extraRoom++;
35 	this.keyTable = new char[extraRoom][];
36 	this.valueTable = new ReferenceBinding[extraRoom];
37 }
containsKey(char[] key)38 public boolean containsKey(char[] key) {
39 	int length = this.keyTable.length,
40 		index = CharOperation.hashCode(key) % length;
41 	int keyLength = key.length;
42 	char[] currentKey;
43 	while ((currentKey = this.keyTable[index]) != null) {
44 		if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
45 			return true;
46 		if (++index == length) {
47 			index = 0;
48 		}
49 	}
50 	return false;
51 }
get(char[] key)52 public ReferenceBinding get(char[] key) {
53 	int length = this.keyTable.length,
54 		index = CharOperation.hashCode(key) % length;
55 	int keyLength = key.length;
56 	char[] currentKey;
57 	while ((currentKey = this.keyTable[index]) != null) {
58 		if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
59 			return this.valueTable[index];
60 		if (++index == length) {
61 			index = 0;
62 		}
63 	}
64 	return null;
65 }
66 // Returns old value.
getput(char[] key, ReferenceBinding value)67 public ReferenceBinding getput(char[] key, ReferenceBinding value) {
68 	ReferenceBinding retVal = null;
69 	int length = this.keyTable.length,
70 		index = CharOperation.hashCode(key) % length;
71 	int keyLength = key.length;
72 	char[] currentKey;
73 	while ((currentKey = this.keyTable[index]) != null) {
74 		if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) {
75 			retVal = this.valueTable[index];
76 			this.valueTable[index] = value;
77 			return retVal;
78 		}
79 		if (++index == length) {
80 			index = 0;
81 		}
82 	}
83 	this.keyTable[index] = key;
84 	this.valueTable[index] = value;
85 
86 	// assumes the threshold is never equal to the size of the table
87 	if (++this.elementSize > this.threshold)
88 		rehash();
89 	return retVal;
90 }
put(char[] key, ReferenceBinding value)91 public ReferenceBinding put(char[] key, ReferenceBinding value) {
92 	int length = this.keyTable.length,
93 		index = CharOperation.hashCode(key) % length;
94 	int keyLength = key.length;
95 	char[] currentKey;
96 	while ((currentKey = this.keyTable[index]) != null) {
97 		if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
98 			return this.valueTable[index] = value;
99 		if (++index == length) {
100 			index = 0;
101 		}
102 	}
103 	this.keyTable[index] = key;
104 	this.valueTable[index] = value;
105 
106 	// assumes the threshold is never equal to the size of the table
107 	if (++this.elementSize > this.threshold)
108 		rehash();
109 	return value;
110 }
rehash()111 private void rehash() {
112 	HashtableOfType newHashtable = new HashtableOfType(this.elementSize < 100 ? 100 : this.elementSize * 2); // double the number of expected elements
113 	char[] currentKey;
114 	for (int i = this.keyTable.length; --i >= 0;)
115 		if ((currentKey = this.keyTable[i]) != null)
116 			newHashtable.put(currentKey, this.valueTable[i]);
117 
118 	this.keyTable = newHashtable.keyTable;
119 	this.valueTable = newHashtable.valueTable;
120 	this.threshold = newHashtable.threshold;
121 }
size()122 public int size() {
123 	return this.elementSize;
124 }
125 @Override
toString()126 public String toString() {
127 	String s = ""; //$NON-NLS-1$
128 	ReferenceBinding type;
129 	for (int i = 0, length = this.valueTable.length; i < length; i++)
130 		if ((type = this.valueTable[i]) != null)
131 			s += type.toString() + "\n"; //$NON-NLS-1$
132 	return s;
133 }
134 }
135