1 16 17 package org.apache.xerces.util; 18 19 78 public class SymbolTable { 79 80 84 85 protected static final int TABLE_SIZE = 101; 86 87 91 92 protected Entry[] fBuckets = null; 93 94 95 protected int fTableSize; 96 97 98 protected transient int fCount; 99 100 102 protected int fThreshold; 103 104 105 protected float fLoadFactor; 106 107 111 120 public SymbolTable(int initialCapacity, float loadFactor) { 121 122 if (initialCapacity < 0) { 123 throw new IllegalArgumentException ("Illegal Capacity: " + initialCapacity); 124 } 125 126 if (loadFactor <= 0 || Float.isNaN(loadFactor)) { 127 throw new IllegalArgumentException ("Illegal Load: " + loadFactor); 128 } 129 130 if (initialCapacity == 0) { 131 initialCapacity = 1; 132 } 133 134 fLoadFactor = loadFactor; 135 fTableSize = initialCapacity; 136 fBuckets = new Entry[fTableSize]; 137 fThreshold = (int)(fTableSize * loadFactor); 138 fCount = 0; 139 } 140 141 149 public SymbolTable(int initialCapacity) { 150 this(initialCapacity, 0.75f); 151 } 152 153 157 public SymbolTable() { 158 this(TABLE_SIZE, 0.75f); 159 } 160 161 165 173 public String addSymbol(String symbol) { 174 175 int bucket = hash(symbol) % fTableSize; 177 for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { 178 if (entry.symbol.equals(symbol)) { 179 return entry.symbol; 180 } 181 } 182 183 if (fCount >= fThreshold) { 184 rehash(); 186 bucket = hash(symbol) % fTableSize; 187 } 188 189 Entry entry = new Entry(symbol, fBuckets[bucket]); 191 fBuckets[bucket] = entry; 192 ++fCount; 193 return entry.symbol; 194 195 } 197 207 public String addSymbol(char[] buffer, int offset, int length) { 208 209 int bucket = hash(buffer, offset, length) % fTableSize; 211 OUTER: for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { 212 if (length == entry.characters.length) { 213 for (int i = 0; i < length; i++) { 214 if (buffer[offset + i] != entry.characters[i]) { 215 continue OUTER; 216 } 217 } 218 return entry.symbol; 219 } 220 } 221 222 if (fCount >= fThreshold) { 223 rehash(); 225 bucket = hash(buffer, offset, length) % fTableSize; 226 } 227 228 Entry entry = new Entry(buffer, offset, length, fBuckets[bucket]); 230 fBuckets[bucket] = entry; 231 ++fCount; 232 return entry.symbol; 233 234 } 236 244 public int hash(String symbol) { 245 return symbol.hashCode() & 0x7FFFFFF; 246 } 248 259 public int hash(char[] buffer, int offset, int length) { 260 261 int code = 0; 262 for (int i = 0; i < length; ++i) { 263 code = code * 31 + buffer[offset + i]; 264 } 265 return code & 0x7FFFFFF; 266 267 } 269 276 protected void rehash() { 277 278 int oldCapacity = fBuckets.length; 279 Entry[] oldTable = fBuckets; 280 281 int newCapacity = oldCapacity * 2 + 1; 282 Entry[] newTable = new Entry[newCapacity]; 283 284 fThreshold = (int)(newCapacity * fLoadFactor); 285 fBuckets = newTable; 286 fTableSize = fBuckets.length; 287 288 for (int i = oldCapacity ; i-- > 0 ;) { 289 for (Entry old = oldTable[i] ; old != null ; ) { 290 Entry e = old; 291 old = old.next; 292 293 int index = hash(e.characters, 0, e.characters.length) % newCapacity; 294 e.next = newTable[index]; 295 newTable[index] = e; 296 } 297 } 298 } 299 300 306 public boolean containsSymbol(String symbol) { 307 308 int bucket = hash(symbol) % fTableSize; 310 int length = symbol.length(); 311 OUTER: for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { 312 if (length == entry.characters.length) { 313 for (int i = 0; i < length; i++) { 314 if (symbol.charAt(i) != entry.characters[i]) { 315 continue OUTER; 316 } 317 } 318 return true; 319 } 320 } 321 322 return false; 323 324 } 326 334 public boolean containsSymbol(char[] buffer, int offset, int length) { 335 336 int bucket = hash(buffer, offset, length) % fTableSize; 338 OUTER: for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { 339 if (length == entry.characters.length) { 340 for (int i = 0; i < length; i++) { 341 if (buffer[offset + i] != entry.characters[i]) { 342 continue OUTER; 343 } 344 } 345 return true; 346 } 347 } 348 349 return false; 350 351 } 353 357 361 protected static final class Entry { 362 363 367 368 public String symbol; 369 370 374 public char[] characters; 375 376 377 public Entry next; 378 379 383 387 public Entry(String symbol, Entry next) { 388 this.symbol = symbol.intern(); 389 characters = new char[symbol.length()]; 390 symbol.getChars(0, characters.length, characters, 0); 391 this.next = next; 392 } 393 394 398 public Entry(char[] ch, int offset, int length, Entry next) { 399 characters = new char[length]; 400 System.arraycopy(ch, offset, characters, 0, length); 401 symbol = new String (characters).intern(); 402 this.next = next; 403 } 404 405 } 407 } | Popular Tags |