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 class UintMap implements Serializable { 55 56 59 public UintMap() { 60 this(4); 61 } 62 63 public UintMap(int initialCapacity) { 64 if (initialCapacity < 0) Context.codeBug(); 65 int minimalCapacity = initialCapacity * 4 / 3; 67 int i; 68 for (i = 2; (1 << i) < minimalCapacity; ++i) { } 69 power = i; 70 if (check && power < 2) Context.codeBug(); 71 } 72 73 public boolean isEmpty() { 74 return keyCount == 0; 75 } 76 77 public int size() { 78 return keyCount; 79 } 80 81 public boolean has(int key) { 82 if (key < 0) Context.codeBug(); 83 return 0 <= findIndex(key); 84 } 85 86 90 public Object getObject(int key) { 91 if (key < 0) Context.codeBug(); 92 if (values != null) { 93 int index = findIndex(key); 94 if (0 <= index) { 95 return values[index]; 96 } 97 } 98 return null; 99 } 100 101 105 public int getInt(int key, int defaultValue) { 106 if (key < 0) Context.codeBug(); 107 int index = findIndex(key); 108 if (0 <= index) { 109 if (ivaluesShift != 0) { 110 return keys[ivaluesShift + index]; 111 } 112 return 0; 113 } 114 return defaultValue; 115 } 116 117 123 public int getExistingInt(int key) { 124 if (key < 0) Context.codeBug(); 125 int index = findIndex(key); 126 if (0 <= index) { 127 if (ivaluesShift != 0) { 128 return keys[ivaluesShift + index]; 129 } 130 return 0; 131 } 132 Context.codeBug(); 134 return 0; 135 } 136 137 141 public void put(int key, Object value) { 142 if (key < 0) Context.codeBug(); 143 int index = ensureIndex(key, false); 144 if (values == null) { 145 values = new Object [1 << power]; 146 } 147 values[index] = value; 148 } 149 150 154 public void put(int key, int value) { 155 if (key < 0) Context.codeBug(); 156 int index = ensureIndex(key, true); 157 if (ivaluesShift == 0) { 158 int N = 1 << power; 159 if (keys.length != N * 2) { 161 int[] tmp = new int[N * 2]; 162 System.arraycopy(keys, 0, tmp, 0, N); 163 keys = tmp; 164 } 165 ivaluesShift = N; 166 } 167 keys[ivaluesShift + index] = value; 168 } 169 170 public void remove(int key) { 171 if (key < 0) Context.codeBug(); 172 int index = findIndex(key); 173 if (0 <= index) { 174 keys[index] = DELETED; 175 --keyCount; 176 if (values != null) { values[index] = null; } 179 if (ivaluesShift != 0) { keys[ivaluesShift + index] = 0; } 180 } 181 } 182 183 public void clear() { 184 int N = 1 << power; 185 if (keys != null) { 186 for (int i = 0; i != N; ++i) { 187 keys[i] = EMPTY; 188 } 189 if (values != null) { 190 for (int i = 0; i != N; ++i) { 191 values[i] = null; 192 } 193 } 194 } 195 ivaluesShift = 0; 196 keyCount = 0; 197 occupiedCount = 0; 198 } 199 200 201 public int[] getKeys() { 202 int[] keys = this.keys; 203 int n = keyCount; 204 int[] result = new int[n]; 205 for (int i = 0; n != 0; ++i) { 206 int entry = keys[i]; 207 if (entry != EMPTY && entry != DELETED) { 208 result[--n] = entry; 209 } 210 } 211 return result; 212 } 213 214 private static int tableLookupStep(int fraction, int mask, int power) { 215 int shift = 32 - 2 * power; 216 if (shift >= 0) { 217 return ((fraction >>> shift) & mask) | 1; 218 } 219 else { 220 return (fraction & (mask >>> -shift)) | 1; 221 } 222 } 223 224 private int findIndex(int key) { 225 int[] keys = this.keys; 226 if (keys != null) { 227 int fraction = key * A; 228 int index = fraction >>> (32 - power); 229 int entry = keys[index]; 230 if (entry == key) { return index; } 231 if (entry != EMPTY) { 232 int mask = (1 << power) - 1; 234 int step = tableLookupStep(fraction, mask, power); 235 int n = 0; 236 do { 237 if (check) { 238 if (n >= occupiedCount) Context.codeBug(); 239 ++n; 240 } 241 index = (index + step) & mask; 242 entry = keys[index]; 243 if (entry == key) { return index; } 244 } while (entry != EMPTY); 245 } 246 } 247 return -1; 248 } 249 250 private int insertNewKey(int key) { 253 if (check && occupiedCount != keyCount) Context.codeBug(); 254 if (check && keyCount == 1 << power) Context.codeBug(); 255 int[] keys = this.keys; 256 int fraction = key * A; 257 int index = fraction >>> (32 - power); 258 if (keys[index] != EMPTY) { 259 int mask = (1 << power) - 1; 260 int step = tableLookupStep(fraction, mask, power); 261 int firstIndex = index; 262 do { 263 if (check && keys[index] == DELETED) Context.codeBug(); 264 index = (index + step) & mask; 265 if (check && firstIndex == index) Context.codeBug(); 266 } while (keys[index] != EMPTY); 267 } 268 keys[index] = key; 269 ++occupiedCount; 270 ++keyCount; 271 return index; 272 } 273 274 private void rehashTable(boolean ensureIntSpace) { 275 if (keys != null) { 276 if (keyCount * 2 >= occupiedCount) { 278 ++power; 280 } 281 } 282 int N = 1 << power; 283 int[] old = keys; 284 int oldShift = ivaluesShift; 285 if (oldShift == 0 && !ensureIntSpace) { 286 keys = new int[N]; 287 } 288 else { 289 ivaluesShift = N; keys = new int[N * 2]; 290 } 291 for (int i = 0; i != N; ++i) { keys[i] = EMPTY; } 292 293 Object [] oldValues = values; 294 if (oldValues != null) { values = new Object [N]; } 295 296 int oldCount = keyCount; 297 occupiedCount = 0; 298 if (oldCount != 0) { 299 keyCount = 0; 300 for (int i = 0, remaining = oldCount; remaining != 0; ++i) { 301 int key = old[i]; 302 if (key != EMPTY && key != DELETED) { 303 int index = insertNewKey(key); 304 if (oldValues != null) { 305 values[index] = oldValues[i]; 306 } 307 if (oldShift != 0) { 308 keys[ivaluesShift + index] = old[oldShift + i]; 309 } 310 --remaining; 311 } 312 } 313 } 314 } 315 316 private int ensureIndex(int key, boolean intType) { 318 int index = -1; 319 int firstDeleted = -1; 320 int[] keys = this.keys; 321 if (keys != null) { 322 int fraction = key * A; 323 index = fraction >>> (32 - power); 324 int entry = keys[index]; 325 if (entry == key) { return index; } 326 if (entry != EMPTY) { 327 if (entry == DELETED) { firstDeleted = index; } 328 int mask = (1 << power) - 1; 330 int step = tableLookupStep(fraction, mask, power); 331 int n = 0; 332 do { 333 if (check) { 334 if (n >= occupiedCount) Context.codeBug(); 335 ++n; 336 } 337 index = (index + step) & mask; 338 entry = keys[index]; 339 if (entry == key) { return index; } 340 if (entry == DELETED && firstDeleted < 0) { 341 firstDeleted = index; 342 } 343 } while (entry != EMPTY); 344 } 345 } 346 if (check && keys != null && keys[index] != EMPTY) 348 Context.codeBug(); 349 if (firstDeleted >= 0) { 350 index = firstDeleted; 351 } 352 else { 353 if (keys == null || occupiedCount * 4 >= (1 << power) * 3) { 355 rehashTable(intType); 357 keys = this.keys; 358 return insertNewKey(key); 359 } 360 ++occupiedCount; 361 } 362 keys[index] = key; 363 ++keyCount; 364 return index; 365 } 366 367 private void writeObject(ObjectOutputStream out) 368 throws IOException 369 { 370 out.defaultWriteObject(); 371 372 int count = keyCount; 373 if (count != 0) { 374 boolean hasIntValues = (ivaluesShift != 0); 375 boolean hasObjectValues = (values != null); 376 out.writeBoolean(hasIntValues); 377 out.writeBoolean(hasObjectValues); 378 379 for (int i = 0; count != 0; ++i) { 380 int key = keys[i]; 381 if (key != EMPTY && key != DELETED) { 382 --count; 383 out.writeInt(key); 384 if (hasIntValues) { 385 out.writeInt(keys[ivaluesShift + i]); 386 } 387 if (hasObjectValues) { 388 out.writeObject(values[i]); 389 } 390 } 391 } 392 } 393 } 394 395 private void readObject(ObjectInputStream in) 396 throws IOException , ClassNotFoundException 397 { 398 in.defaultReadObject(); 399 400 int writtenKeyCount = keyCount; 401 if (writtenKeyCount != 0) { 402 keyCount = 0; 403 boolean hasIntValues = in.readBoolean(); 404 boolean hasObjectValues = in.readBoolean(); 405 406 int N = 1 << power; 407 if (hasIntValues) { 408 keys = new int[2 * N]; 409 ivaluesShift = N; 410 }else { 411 keys = new int[N]; 412 } 413 for (int i = 0; i != N; ++i) { 414 keys[i] = EMPTY; 415 } 416 if (hasObjectValues) { 417 values = new Object [N]; 418 } 419 for (int i = 0; i != writtenKeyCount; ++i) { 420 int key = in.readInt(); 421 int index = insertNewKey(key); 422 if (hasIntValues) { 423 int ivalue = in.readInt(); 424 keys[ivaluesShift + index] = ivalue; 425 } 426 if (hasObjectValues) { 427 values[index] = in.readObject(); 428 } 429 } 430 } 431 } 432 433 static final long serialVersionUID = -6916326879143724506L; 434 435 436 private static final int A = 0x9e3779b9; 439 440 private static final int EMPTY = -1; 441 private static final int DELETED = -2; 442 443 448 private transient int[] keys; 449 private transient Object [] values; 450 451 private int power; 452 private int keyCount; 453 private transient int occupiedCount; 455 private transient int ivaluesShift; 458 459 private static final boolean check = false; 461 462 658 } 659 | Popular Tags |