001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.util;
011:
012: import org.eclipse.jdt.core.compiler.CharOperation;
013:
014: /**
015: * Hashtable of {char[] --> Object }
016: */
017: public final class HashtableOfObject implements Cloneable {
018:
019: // to avoid using Enumerations, walk the individual tables skipping nulls
020: public char[] keyTable[];
021: public Object valueTable[];
022:
023: public int elementSize; // number of elements in the table
024: int threshold;
025:
026: public HashtableOfObject() {
027: this (13);
028: }
029:
030: public HashtableOfObject(int size) {
031:
032: this .elementSize = 0;
033: this .threshold = size; // size represents the expected number of elements
034: int extraRoom = (int) (size * 1.75f);
035: if (this .threshold == extraRoom)
036: extraRoom++;
037: this .keyTable = new char[extraRoom][];
038: this .valueTable = new Object[extraRoom];
039: }
040:
041: public void clear() {
042: for (int i = this .keyTable.length; --i >= 0;) {
043: this .keyTable[i] = null;
044: this .valueTable[i] = null;
045: }
046: this .elementSize = 0;
047: }
048:
049: public Object clone() throws CloneNotSupportedException {
050: HashtableOfObject result = (HashtableOfObject) super .clone();
051: result.elementSize = this .elementSize;
052: result.threshold = this .threshold;
053:
054: int length = this .keyTable.length;
055: result.keyTable = new char[length][];
056: System.arraycopy(this .keyTable, 0, result.keyTable, 0, length);
057:
058: length = this .valueTable.length;
059: result.valueTable = new Object[length];
060: System.arraycopy(this .valueTable, 0, result.valueTable, 0,
061: length);
062: return result;
063: }
064:
065: public boolean containsKey(char[] key) {
066: int length = keyTable.length, index = CharOperation
067: .hashCode(key)
068: % length;
069: int keyLength = key.length;
070: char[] currentKey;
071: while ((currentKey = keyTable[index]) != null) {
072: if (currentKey.length == keyLength
073: && CharOperation.equals(currentKey, key))
074: return true;
075: if (++index == length) {
076: index = 0;
077: }
078: }
079: return false;
080: }
081:
082: public Object get(char[] key) {
083: int length = keyTable.length, index = CharOperation
084: .hashCode(key)
085: % length;
086: int keyLength = key.length;
087: char[] currentKey;
088: while ((currentKey = keyTable[index]) != null) {
089: if (currentKey.length == keyLength
090: && CharOperation.equals(currentKey, key))
091: return valueTable[index];
092: if (++index == length) {
093: index = 0;
094: }
095: }
096: return null;
097: }
098:
099: public Object put(char[] key, Object value) {
100: int length = keyTable.length, index = CharOperation
101: .hashCode(key)
102: % length;
103: int keyLength = key.length;
104: char[] currentKey;
105: while ((currentKey = keyTable[index]) != null) {
106: if (currentKey.length == keyLength
107: && CharOperation.equals(currentKey, key))
108: return valueTable[index] = value;
109: if (++index == length) {
110: index = 0;
111: }
112: }
113: keyTable[index] = key;
114: valueTable[index] = value;
115:
116: // assumes the threshold is never equal to the size of the table
117: if (++elementSize > threshold)
118: rehash();
119: return value;
120: }
121:
122: public Object removeKey(char[] key) {
123: int length = keyTable.length, index = CharOperation
124: .hashCode(key)
125: % length;
126: int keyLength = key.length;
127: char[] currentKey;
128: while ((currentKey = keyTable[index]) != null) {
129: if (currentKey.length == keyLength
130: && CharOperation.equals(currentKey, key)) {
131: Object value = valueTable[index];
132: elementSize--;
133: keyTable[index] = null;
134: valueTable[index] = null;
135: rehash();
136: return value;
137: }
138: if (++index == length) {
139: index = 0;
140: }
141: }
142: return null;
143: }
144:
145: private void rehash() {
146:
147: HashtableOfObject newHashtable = new HashtableOfObject(
148: elementSize * 2); // double the number of expected elements
149: char[] currentKey;
150: for (int i = keyTable.length; --i >= 0;)
151: if ((currentKey = keyTable[i]) != null)
152: newHashtable.put(currentKey, valueTable[i]);
153:
154: this .keyTable = newHashtable.keyTable;
155: this .valueTable = newHashtable.valueTable;
156: this .threshold = newHashtable.threshold;
157: }
158:
159: public int size() {
160: return elementSize;
161: }
162:
163: public String toString() {
164: String s = ""; //$NON-NLS-1$
165: Object object;
166: for (int i = 0, length = valueTable.length; i < length; i++)
167: if ((object = valueTable[i]) != null)
168: s += new String(keyTable[i])
169: + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
170: return s;
171: }
172: }
|