1) Need to syncronize also the type of variable values not only the values (makes...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / util / HashtableOfObject.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.util;
12
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14
15 /**
16  * Hashtable of {char[] --> Object }
17  */
18 public final class HashtableOfObject implements Cloneable {
19
20         // to avoid using Enumerations, walk the individual tables skipping nulls
21         public char[] keyTable[];
22
23         public Object valueTable[];
24
25         public int elementSize; // number of elements in the table
26
27         int threshold;
28
29         public HashtableOfObject() {
30                 this(13);
31         }
32
33         public HashtableOfObject(int size) {
34
35                 this.elementSize = 0;
36                 this.threshold = size; // size represents the expected number of
37                                                                 // elements
38                 int extraRoom = (int) (size * 1.75f);
39                 if (this.threshold == extraRoom)
40                         extraRoom++;
41                 this.keyTable = new char[extraRoom][];
42                 this.valueTable = new Object[extraRoom];
43         }
44
45         public Object clone() throws CloneNotSupportedException {
46                 HashtableOfObject result = (HashtableOfObject) super.clone();
47                 result.elementSize = this.elementSize;
48                 result.threshold = this.threshold;
49
50                 int length = this.keyTable.length;
51                 result.keyTable = new char[length][];
52                 System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
53
54                 length = this.valueTable.length;
55                 result.valueTable = new Object[length];
56                 System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
57                 return result;
58         }
59
60         public boolean containsKey(char[] key) {
61
62                 int index = CharOperation.hashCode(key) % valueTable.length;
63                 int keyLength = key.length;
64                 char[] currentKey;
65                 while ((currentKey = keyTable[index]) != null) {
66                         if (currentKey.length == keyLength
67                                         && CharOperation.prefixEquals(currentKey, key))
68                                 return true;
69                         index = (index + 1) % keyTable.length;
70                 }
71                 return false;
72         }
73
74         public Object get(char[] key) {
75
76                 int index = CharOperation.hashCode(key) % valueTable.length;
77                 int keyLength = key.length;
78                 char[] currentKey;
79                 while ((currentKey = keyTable[index]) != null) {
80                         if (currentKey.length == keyLength
81                                         && CharOperation.prefixEquals(currentKey, key))
82                                 return valueTable[index];
83                         index = (index + 1) % keyTable.length;
84                 }
85                 return null;
86         }
87
88         public Object put(char[] key, Object value) {
89
90                 int index = CharOperation.hashCode(key) % valueTable.length;
91                 int keyLength = key.length;
92                 char[] currentKey;
93                 while ((currentKey = keyTable[index]) != null) {
94                         if (currentKey.length == keyLength
95                                         && CharOperation.prefixEquals(currentKey, key))
96                                 return valueTable[index] = value;
97                         index = (index + 1) % keyTable.length;
98                 }
99                 keyTable[index] = key;
100                 valueTable[index] = value;
101
102                 // assumes the threshold is never equal to the size of the table
103                 if (++elementSize > threshold)
104                         rehash();
105                 return value;
106         }
107
108         public Object removeKey(char[] key) {
109
110                 int index = CharOperation.hashCode(key) % valueTable.length;
111                 int keyLength = key.length;
112                 char[] currentKey;
113                 while ((currentKey = keyTable[index]) != null) {
114                         if (currentKey.length == keyLength
115                                         && CharOperation.prefixEquals(currentKey, key)) {
116                                 Object value = valueTable[index];
117                                 elementSize--;
118                                 keyTable[index] = null;
119                                 valueTable[index] = null;
120                                 rehash();
121                                 return value;
122                         }
123                         index = (index + 1) % keyTable.length;
124                 }
125                 return null;
126         }
127
128         private void rehash() {
129
130                 HashtableOfObject newHashtable = new HashtableOfObject(elementSize * 2); // double
131                                                                                                                                                                         // the
132                                                                                                                                                                         // number
133                                                                                                                                                                         // of
134                                                                                                                                                                         // expected
135                                                                                                                                                                         // elements
136                 char[] currentKey;
137                 for (int i = keyTable.length; --i >= 0;)
138                         if ((currentKey = keyTable[i]) != null)
139                                 newHashtable.put(currentKey, valueTable[i]);
140
141                 this.keyTable = newHashtable.keyTable;
142                 this.valueTable = newHashtable.valueTable;
143                 this.threshold = newHashtable.threshold;
144         }
145
146         public int size() {
147                 return elementSize;
148         }
149
150         public String toString() {
151                 String s = ""; //$NON-NLS-1$
152                 Object object;
153                 for (int i = 0, length = valueTable.length; i < length; i++)
154                         if ((object = valueTable[i]) != null)
155                                 s += new String(keyTable[i])
156                                                 + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
157                 return s;
158         }
159 }