1 35 37 package com.google.gwt.dev.js.rhino; 38 39 import java.io.Serializable ; 40 import java.io.IOException ; 41 import java.io.ObjectInputStream ; 42 import java.io.ObjectOutputStream ; 43 44 53 54 public class ObjToIntMap implements Serializable { 55 56 public static final Object NULL_VALUE = new String (""); 57 58 61 63 public static class Iterator { 64 65 Iterator(ObjToIntMap master) { 66 this.master = master; 67 } 68 69 final void init(Object [] keys, int[] values, int keyCount) { 70 this.keys = keys; 71 this.values = values; 72 this.cursor = -1; 73 this.remaining = keyCount; 74 } 75 76 public void start() { 77 master.initIterator(this); 78 next(); 79 } 80 81 public boolean done() { 82 return remaining < 0; 83 } 84 85 public void next() { 86 if (remaining == -1) Context.codeBug(); 87 if (remaining == 0) { 88 remaining = -1; 89 cursor = -1; 90 }else { 91 for (++cursor; ; ++cursor) { 92 Object key = keys[cursor]; 93 if (key != null && key != DELETED) { 94 --remaining; 95 break; 96 } 97 } 98 } 99 } 100 101 public Object getKey() { 102 Object key = keys[cursor]; 103 if (key == NULL_VALUE) { key = null; } 104 return key; 105 } 106 107 public int getValue() { 108 return values[cursor]; 109 } 110 111 public void setValue(int value) { 112 values[cursor] = value; 113 } 114 115 ObjToIntMap master; 116 private int cursor; 117 private int remaining; 118 private Object [] keys; 119 private int[] values; 120 } 121 122 public ObjToIntMap() { 123 this(4); 124 } 125 126 public ObjToIntMap(int keyCountHint) { 127 if (keyCountHint < 0) Context.codeBug(); 128 int minimalCapacity = keyCountHint * 4 / 3; 130 int i; 131 for (i = 2; (1 << i) < minimalCapacity; ++i) { } 132 power = i; 133 if (check && power < 2) Context.codeBug(); 134 } 135 136 public boolean isEmpty() { 137 return keyCount == 0; 138 } 139 140 public int size() { 141 return keyCount; 142 } 143 144 public boolean has(Object key) { 145 if (key == null) { key = NULL_VALUE; } 146 return 0 <= findIndex(key); 147 } 148 149 153 public int get(Object key, int defaultValue) { 154 if (key == null) { key = NULL_VALUE; } 155 int index = findIndex(key); 156 if (0 <= index) { 157 return values[index]; 158 } 159 return defaultValue; 160 } 161 162 167 public int getExisting(Object key) { 168 if (key == null) { key = NULL_VALUE; } 169 int index = findIndex(key); 170 if (0 <= index) { 171 return values[index]; 172 } 173 Context.codeBug(); 175 return 0; 176 } 177 178 public void put(Object key, int value) { 179 if (key == null) { key = NULL_VALUE; } 180 int index = ensureIndex(key); 181 values[index] = value; 182 } 183 184 189 public Object intern(Object keyArg) { 190 boolean nullKey = false; 191 if (keyArg == null) { 192 nullKey = true; 193 keyArg = NULL_VALUE; 194 } 195 int index = ensureIndex(keyArg); 196 values[index] = 0; 197 return (nullKey) ? null : keys[index]; 198 } 199 200 public void remove(Object key) { 201 if (key == null) { key = NULL_VALUE; } 202 int index = findIndex(key); 203 if (0 <= index) { 204 keys[index] = DELETED; 205 --keyCount; 206 } 207 } 208 209 public void clear() { 210 int i = keys.length; 211 while (i != 0) { 212 keys[--i] = null; 213 } 214 keyCount = 0; 215 occupiedCount = 0; 216 } 217 218 public Iterator newIterator() { 219 return new Iterator(this); 220 } 221 222 final void initIterator(Iterator i) { 226 i.init(keys, values, keyCount); 227 } 228 229 230 public Object [] getKeys() { 231 Object [] array = new Object [keyCount]; 232 getKeys(array, 0); 233 return array; 234 } 235 236 public void getKeys(Object [] array, int offset) { 237 int count = keyCount; 238 for (int i = 0; count != 0; ++i) { 239 Object key = keys[i]; 240 if (key != null && key != DELETED) { 241 if (key == NULL_VALUE) { key = null; } 242 array[offset] = key; 243 ++offset; 244 --count; 245 } 246 } 247 } 248 249 private static int tableLookupStep(int fraction, int mask, int power) { 250 int shift = 32 - 2 * power; 251 if (shift >= 0) { 252 return ((fraction >>> shift) & mask) | 1; 253 } 254 else { 255 return (fraction & (mask >>> -shift)) | 1; 256 } 257 } 258 259 private int findIndex(Object key) { 260 if (keys != null) { 261 int hash = key.hashCode(); 262 int fraction = hash * A; 263 int index = fraction >>> (32 - power); 264 Object test = keys[index]; 265 if (test != null) { 266 int N = 1 << power; 267 if (test == key 268 || (values[N + index] == hash && test.equals(key))) 269 { 270 return index; 271 } 272 int mask = N - 1; 274 int step = tableLookupStep(fraction, mask, power); 275 int n = 0; 276 for (;;) { 277 if (check) { 278 if (n >= occupiedCount) Context.codeBug(); 279 ++n; 280 } 281 index = (index + step) & mask; 282 test = keys[index]; 283 if (test == null) { 284 break; 285 } 286 if (test == key 287 || (values[N + index] == hash && test.equals(key))) 288 { 289 return index; 290 } 291 } 292 } 293 } 294 return -1; 295 } 296 297 private int insertNewKey(Object key, int hash) { 300 if (check && occupiedCount != keyCount) Context.codeBug(); 301 if (check && keyCount == 1 << power) Context.codeBug(); 302 int fraction = hash * A; 303 int index = fraction >>> (32 - power); 304 int N = 1 << power; 305 if (keys[index] != null) { 306 int mask = N - 1; 307 int step = tableLookupStep(fraction, mask, power); 308 int firstIndex = index; 309 do { 310 if (check && keys[index] == DELETED) Context.codeBug(); 311 index = (index + step) & mask; 312 if (check && firstIndex == index) Context.codeBug(); 313 } while (keys[index] != null); 314 } 315 keys[index] = key; 316 values[N + index] = hash; 317 ++occupiedCount; 318 ++keyCount; 319 320 return index; 321 } 322 323 private void rehashTable() { 324 if (keys == null) { 325 if (check && keyCount != 0) Context.codeBug(); 326 if (check && occupiedCount != 0) Context.codeBug(); 327 int N = 1 << power; 328 keys = new Object [N]; 329 values = new int[2 * N]; 330 } 331 else { 332 if (keyCount * 2 >= occupiedCount) { 334 ++power; 336 } 337 int N = 1 << power; 338 Object [] oldKeys = keys; 339 int[] oldValues = values; 340 int oldN = oldKeys.length; 341 keys = new Object [N]; 342 values = new int[2 * N]; 343 344 int remaining = keyCount; 345 occupiedCount = keyCount = 0; 346 for (int i = 0; remaining != 0; ++i) { 347 Object key = oldKeys[i]; 348 if (key != null && key != DELETED) { 349 int keyHash = oldValues[oldN + i]; 350 int index = insertNewKey(key, keyHash); 351 values[index] = oldValues[i]; 352 --remaining; 353 } 354 } 355 } 356 } 357 358 private int ensureIndex(Object key) { 360 int hash = key.hashCode(); 361 int index = -1; 362 int firstDeleted = -1; 363 if (keys != null) { 364 int fraction = hash * A; 365 index = fraction >>> (32 - power); 366 Object test = keys[index]; 367 if (test != null) { 368 int N = 1 << power; 369 if (test == key 370 || (values[N + index] == hash && test.equals(key))) 371 { 372 return index; 373 } 374 if (test == DELETED) { 375 firstDeleted = index; 376 } 377 378 int mask = N - 1; 380 int step = tableLookupStep(fraction, mask, power); 381 int n = 0; 382 for (;;) { 383 if (check) { 384 if (n >= occupiedCount) Context.codeBug(); 385 ++n; 386 } 387 index = (index + step) & mask; 388 test = keys[index]; 389 if (test == null) { 390 break; 391 } 392 if (test == key 393 || (values[N + index] == hash && test.equals(key))) 394 { 395 return index; 396 } 397 if (test == DELETED && firstDeleted < 0) { 398 firstDeleted = index; 399 } 400 } 401 } 402 } 403 if (check && keys != null && keys[index] != null) 405 Context.codeBug(); 406 if (firstDeleted >= 0) { 407 index = firstDeleted; 408 } 409 else { 410 if (keys == null || occupiedCount * 4 >= (1 << power) * 3) { 412 rehashTable(); 414 return insertNewKey(key, hash); 415 } 416 ++occupiedCount; 417 } 418 keys[index] = key; 419 values[(1 << power) + index] = hash; 420 ++keyCount; 421 return index; 422 } 423 424 private void writeObject(ObjectOutputStream out) 425 throws IOException  426 { 427 out.defaultWriteObject(); 428 429 int count = keyCount; 430 for (int i = 0; count != 0; ++i) { 431 Object key = keys[i]; 432 if (key != null && key != DELETED) { 433 --count; 434 out.writeObject(key); 435 out.writeInt(values[i]); 436 } 437 } 438 } 439 440 private void readObject(ObjectInputStream in) 441 throws IOException , ClassNotFoundException  442 { 443 in.defaultReadObject(); 444 445 int writtenKeyCount = keyCount; 446 if (writtenKeyCount != 0) { 447 keyCount = 0; 448 int N = 1 << power; 449 keys = new Object [N]; 450 values = new int[2 * N]; 451 for (int i = 0; i != writtenKeyCount; ++i) { 452 Object key = in.readObject(); 453 int hash = key.hashCode(); 454 int index = insertNewKey(key, hash); 455 values[index] = in.readInt(); 456 } 457 } 458 } 459 460 static final long serialVersionUID = 3396438333234169727L; 461 462 private static final int A = 0x9e3779b9; 465 466 private static final Object DELETED = new Object (); 467 468 473 private transient Object [] keys; 474 private transient int[] values; 475 476 private int power; 477 private int keyCount; 478 private transient int occupiedCount; 480 private static final boolean check = false; 482 483 696 697 } 698 | Popular Tags |