| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 patch class HashMap<K, V> { | 5 patch class HashMap<K, V> { |
| 6 /* patch */ factory HashMap({ bool equals(K key1, K key2), | |
| 7 int hashCode(K key) }) { | |
| 8 if (hashCode == null) { | |
| 9 if (equals == null) { | |
| 10 return new _HashMapImpl<K, V>(); | |
| 11 } | |
| 12 if (identical(identical, equals)) { | |
| 13 return new _IdentityHashMap<K, V>(); | |
| 14 } | |
| 15 hashCode = _defaultHashCode; | |
| 16 } else if (equals == null) { | |
| 17 equals = _defaultEquals; | |
| 18 } | |
| 19 return new _CustomHashMap<K, V>(equals, hashCode); | |
| 20 } | |
| 21 } | |
| 22 | |
| 23 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; | |
| 24 | |
| 25 class _HashMapImpl<K, V> implements HashMap<K, V> { | |
| 26 static const int _INITIAL_CAPACITY = 8; | 6 static const int _INITIAL_CAPACITY = 8; |
| 7 static const int _MODIFICATION_COUNT_MASK = 0x3fffffff; |
| 27 | 8 |
| 28 int _elementCount = 0; | 9 int _elementCount = 0; |
| 29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); | 10 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); |
| 30 int _modificationCount = 0; | 11 int _modificationCount = 0; |
| 31 | 12 |
| 32 int get length => _elementCount; | 13 /* patch */ HashMap._internal(); |
| 33 bool get isEmpty => _elementCount == 0; | |
| 34 bool get isNotEmpty => _elementCount != 0; | |
| 35 | 14 |
| 36 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); | 15 /* patch */ int get length => _elementCount; |
| 37 Iterable<V> get values => new _HashMapValueIterable<V>(this); | 16 /* patch */ bool get isEmpty => _elementCount == 0; |
| 17 /* patch */ bool get isNotEmpty => _elementCount != 0; |
| 38 | 18 |
| 39 bool containsKey(Object key) { | 19 /* patch */ Iterable<K> get keys => new _HashMapKeyIterable<K>(this); |
| 20 /* patch */ Iterable<V> get values => new _HashMapValueIterable<V>(this); |
| 21 |
| 22 /* patch */ bool containsKey(Object key) { |
| 40 int hashCode = key.hashCode; | 23 int hashCode = key.hashCode; |
| 41 List buckets = _buckets; | 24 List buckets = _buckets; |
| 42 int index = hashCode & (buckets.length - 1); | 25 int index = hashCode & (buckets.length - 1); |
| 43 _HashMapEntry entry = buckets[index]; | 26 _HashMapEntry entry = buckets[index]; |
| 44 while (entry != null) { | 27 while (entry != null) { |
| 45 if (hashCode == entry.hashCode && entry.key == key) return true; | 28 if (hashCode == entry.hashCode && entry.key == key) return true; |
| 46 entry = entry.next; | 29 entry = entry.next; |
| 47 } | 30 } |
| 48 return false; | 31 return false; |
| 49 } | 32 } |
| 50 | 33 |
| 51 bool containsValue(Object value) { | 34 /* patch */ bool containsValue(Object value) { |
| 52 List buckets = _buckets; | 35 List buckets = _buckets; |
| 53 int length = buckets.length; | 36 int length = buckets.length; |
| 54 for (int i = 0; i < length; i++) { | 37 for (int i = 0; i < length; i++) { |
| 55 _HashMapEntry entry = buckets[i]; | 38 _HashMapEntry entry = buckets[i]; |
| 56 while (entry != null) { | 39 while (entry != null) { |
| 57 if (entry.value == value) return true; | 40 if (entry.value == value) return true; |
| 58 entry = entry.next; | 41 entry = entry.next; |
| 59 } | 42 } |
| 60 } | 43 } |
| 61 return false; | 44 return false; |
| 62 } | 45 } |
| 63 | 46 |
| 64 V operator[](Object key) { | 47 /* patch */ V operator[](Object key) { |
| 65 int hashCode = key.hashCode; | 48 int hashCode = key.hashCode; |
| 66 List buckets = _buckets; | 49 List buckets = _buckets; |
| 67 int index = hashCode & (buckets.length - 1); | 50 int index = hashCode & (buckets.length - 1); |
| 68 _HashMapEntry entry = buckets[index]; | 51 _HashMapEntry entry = buckets[index]; |
| 69 while (entry != null) { | 52 while (entry != null) { |
| 70 if (hashCode == entry.hashCode && entry.key == key) { | 53 if (hashCode == entry.hashCode && entry.key == key) { |
| 71 return entry.value; | 54 return entry.value; |
| 72 } | 55 } |
| 73 entry = entry.next; | 56 entry = entry.next; |
| 74 } | 57 } |
| 75 return null; | 58 return null; |
| 76 } | 59 } |
| 77 | 60 |
| 78 void operator []=(K key, V value) { | 61 /* patch */ void operator []=(K key, V value) { |
| 79 int hashCode = key.hashCode; | 62 int hashCode = key.hashCode; |
| 80 List buckets = _buckets; | 63 List buckets = _buckets; |
| 81 int length = buckets.length; | 64 int length = buckets.length; |
| 82 int index = hashCode & (length - 1); | 65 int index = hashCode & (length - 1); |
| 83 _HashMapEntry entry = buckets[index]; | 66 _HashMapEntry entry = buckets[index]; |
| 84 while (entry != null) { | 67 while (entry != null) { |
| 85 if (hashCode == entry.hashCode && entry.key == key) { | 68 if (hashCode == entry.hashCode && entry.key == key) { |
| 86 entry.value = value; | 69 entry.value = value; |
| 87 return; | 70 return; |
| 88 } | 71 } |
| 89 entry = entry.next; | 72 entry = entry.next; |
| 90 } | 73 } |
| 91 _addEntry(buckets, index, length, key, value, hashCode); | 74 _addEntry(buckets, index, length, key, value, hashCode); |
| 92 } | 75 } |
| 93 | 76 |
| 94 V putIfAbsent(K key, V ifAbsent()) { | 77 /* patch */ V putIfAbsent(K key, V ifAbsent()) { |
| 95 int hashCode = key.hashCode; | 78 int hashCode = key.hashCode; |
| 96 List buckets = _buckets; | 79 List buckets = _buckets; |
| 97 int length = buckets.length; | 80 int length = buckets.length; |
| 98 int index = hashCode & (length - 1); | 81 int index = hashCode & (length - 1); |
| 99 _HashMapEntry entry = buckets[index]; | 82 _HashMapEntry entry = buckets[index]; |
| 100 while (entry != null) { | 83 while (entry != null) { |
| 101 if (hashCode == entry.hashCode && entry.key == key) { | 84 if (hashCode == entry.hashCode && entry.key == key) { |
| 102 return entry.value; | 85 return entry.value; |
| 103 } | 86 } |
| 104 entry = entry.next; | 87 entry = entry.next; |
| 105 } | 88 } |
| 106 int stamp = _modificationCount; | 89 int stamp = _modificationCount; |
| 107 V value = ifAbsent(); | 90 V value = ifAbsent(); |
| 108 if (stamp == _modificationCount) { | 91 if (stamp == _modificationCount) { |
| 109 _addEntry(buckets, index, length, key, value, hashCode); | 92 _addEntry(buckets, index, length, key, value, hashCode); |
| 110 } else { | 93 } else { |
| 111 this[key] = value; | 94 this[key] = value; |
| 112 } | 95 } |
| 113 return value; | 96 return value; |
| 114 } | 97 } |
| 115 | 98 |
| 116 void addAll(Map<K, V> other) { | 99 /* patch */ void addAll(Map<K, V> other) { |
| 117 other.forEach((K key, V value) { | 100 other.forEach((K key, V value) { |
| 118 this[key] = value; | 101 this[key] = value; |
| 119 }); | 102 }); |
| 120 } | 103 } |
| 121 | 104 |
| 122 void forEach(void action(K key, V value)) { | 105 /* patch */ void forEach(void action(K key, V value)) { |
| 123 int stamp = _modificationCount; | 106 int stamp = _modificationCount; |
| 124 List buckets = _buckets; | 107 List buckets = _buckets; |
| 125 int length = buckets.length; | 108 int length = buckets.length; |
| 126 for (int i = 0; i < length; i++) { | 109 for (int i = 0; i < length; i++) { |
| 127 _HashMapEntry entry = buckets[i]; | 110 _HashMapEntry entry = buckets[i]; |
| 128 while (entry != null) { | 111 while (entry != null) { |
| 129 action(entry.key, entry.value); | 112 action(entry.key, entry.value); |
| 130 if (stamp != _modificationCount) { | 113 if (stamp != _modificationCount) { |
| 131 throw new ConcurrentModificationError(this); | 114 throw new ConcurrentModificationError(this); |
| 132 } | 115 } |
| 133 entry = entry.next; | 116 entry = entry.next; |
| 134 } | 117 } |
| 135 } | 118 } |
| 136 } | 119 } |
| 137 | 120 |
| 138 V remove(Object key) { | 121 /* patch */ V remove(Object key) { |
| 139 int hashCode = key.hashCode; | 122 int hashCode = key.hashCode; |
| 140 List buckets = _buckets; | 123 List buckets = _buckets; |
| 141 int index = hashCode & (buckets.length - 1); | 124 int index = hashCode & (buckets.length - 1); |
| 142 _HashMapEntry entry = buckets[index]; | 125 _HashMapEntry entry = buckets[index]; |
| 143 _HashMapEntry previous = null; | 126 _HashMapEntry previous = null; |
| 144 while (entry != null) { | 127 while (entry != null) { |
| 145 _HashMapEntry next = entry.next; | 128 _HashMapEntry next = entry.next; |
| 146 if (hashCode == entry.hashCode && entry.key == key) { | 129 if (hashCode == entry.hashCode && entry.key == key) { |
| 147 if (previous == null) { | 130 if (previous == null) { |
| 148 buckets[index] = next; | 131 buckets[index] = next; |
| 149 } else { | 132 } else { |
| 150 previous.next = next; | 133 previous.next = next; |
| 151 } | 134 } |
| 152 _elementCount--; | 135 _elementCount--; |
| 153 _modificationCount = | 136 _modificationCount = |
| 154 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 137 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
| 155 return entry.value; | 138 return entry.value; |
| 156 } | 139 } |
| 157 previous = entry; | 140 previous = entry; |
| 158 entry = next; | 141 entry = next; |
| 159 } | 142 } |
| 160 return null; | 143 return null; |
| 161 } | 144 } |
| 162 | 145 |
| 163 void clear() { | 146 /* patch */ void clear() { |
| 164 _elementCount = 0; | 147 _elementCount = 0; |
| 165 _buckets = new List(_INITIAL_CAPACITY); | 148 _buckets = new List(_INITIAL_CAPACITY); |
| 166 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 149 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
| 167 } | 150 } |
| 168 | 151 |
| 169 void _addEntry(List buckets, int index, int length, | 152 void _addEntry(List buckets, int index, int length, |
| 170 K key, V value, int hashCode) { | 153 K key, V value, int hashCode) { |
| 171 _HashMapEntry entry = | 154 _HashMapEntry entry = |
| 172 new _HashMapEntry(key, value, hashCode, buckets[index]); | 155 new _HashMapEntry(key, value, hashCode, buckets[index]); |
| 173 buckets[index] = entry; | 156 buckets[index] = entry; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 192 int index = hashCode & (newLength - 1); | 175 int index = hashCode & (newLength - 1); |
| 193 entry.next = newBuckets[index]; | 176 entry.next = newBuckets[index]; |
| 194 newBuckets[index] = entry; | 177 newBuckets[index] = entry; |
| 195 entry = next; | 178 entry = next; |
| 196 } | 179 } |
| 197 } | 180 } |
| 198 _buckets = newBuckets; | 181 _buckets = newBuckets; |
| 199 } | 182 } |
| 200 } | 183 } |
| 201 | 184 |
| 202 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> { | |
| 203 final Function _equals; | |
| 204 final Function _hashCode; | |
| 205 _CustomHashMap(this._equals, this._hashCode); | |
| 206 | |
| 207 bool containsKey(Object key) { | |
| 208 int hashCode = _hashCode(key); | |
| 209 List buckets = _buckets; | |
| 210 int index = hashCode & (buckets.length - 1); | |
| 211 _HashMapEntry entry = buckets[index]; | |
| 212 while (entry != null) { | |
| 213 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; | |
| 214 entry = entry.next; | |
| 215 } | |
| 216 return false; | |
| 217 } | |
| 218 | |
| 219 V operator[](Object key) { | |
| 220 int hashCode = _hashCode(key); | |
| 221 List buckets = _buckets; | |
| 222 int index = hashCode & (buckets.length - 1); | |
| 223 _HashMapEntry entry = buckets[index]; | |
| 224 while (entry != null) { | |
| 225 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
| 226 return entry.value; | |
| 227 } | |
| 228 entry = entry.next; | |
| 229 } | |
| 230 return null; | |
| 231 } | |
| 232 | |
| 233 void operator []=(K key, V value) { | |
| 234 int hashCode = _hashCode(key); | |
| 235 List buckets = _buckets; | |
| 236 int length = buckets.length; | |
| 237 int index = hashCode & (length - 1); | |
| 238 _HashMapEntry entry = buckets[index]; | |
| 239 while (entry != null) { | |
| 240 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
| 241 entry.value = value; | |
| 242 return; | |
| 243 } | |
| 244 entry = entry.next; | |
| 245 } | |
| 246 _addEntry(buckets, index, length, key, value, hashCode); | |
| 247 } | |
| 248 | |
| 249 V putIfAbsent(K key, V ifAbsent()) { | |
| 250 int hashCode = _hashCode(key); | |
| 251 List buckets = _buckets; | |
| 252 int length = buckets.length; | |
| 253 int index = hashCode & (length - 1); | |
| 254 _HashMapEntry entry = buckets[index]; | |
| 255 while (entry != null) { | |
| 256 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
| 257 return entry.value; | |
| 258 } | |
| 259 entry = entry.next; | |
| 260 } | |
| 261 int stamp = _modificationCount; | |
| 262 V value = ifAbsent(); | |
| 263 if (stamp == _modificationCount) { | |
| 264 _addEntry(buckets, index, length, key, value, hashCode); | |
| 265 } else { | |
| 266 this[key] = value; | |
| 267 } | |
| 268 return value; | |
| 269 } | |
| 270 | |
| 271 V remove(Object key) { | |
| 272 int hashCode = _hashCode(key); | |
| 273 List buckets = _buckets; | |
| 274 int index = hashCode & (buckets.length - 1); | |
| 275 _HashMapEntry entry = buckets[index]; | |
| 276 _HashMapEntry previous = null; | |
| 277 while (entry != null) { | |
| 278 _HashMapEntry next = entry.next; | |
| 279 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
| 280 if (previous == null) { | |
| 281 buckets[index] = next; | |
| 282 } else { | |
| 283 previous.next = next; | |
| 284 } | |
| 285 _elementCount--; | |
| 286 _modificationCount = | |
| 287 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | |
| 288 return entry.value; | |
| 289 } | |
| 290 previous = entry; | |
| 291 entry = next; | |
| 292 } | |
| 293 return null; | |
| 294 } | |
| 295 } | |
| 296 | |
| 297 class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> { | |
| 298 bool containsKey(Object key) { | |
| 299 int hashCode = key.hashCode; | |
| 300 List buckets = _buckets; | |
| 301 int index = hashCode & (buckets.length - 1); | |
| 302 _HashMapEntry entry = buckets[index]; | |
| 303 while (entry != null) { | |
| 304 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; | |
| 305 entry = entry.next; | |
| 306 } | |
| 307 return false; | |
| 308 } | |
| 309 | |
| 310 V operator[](Object key) { | |
| 311 int hashCode = key.hashCode; | |
| 312 List buckets = _buckets; | |
| 313 int index = hashCode & (buckets.length - 1); | |
| 314 _HashMapEntry entry = buckets[index]; | |
| 315 while (entry != null) { | |
| 316 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
| 317 return entry.value; | |
| 318 } | |
| 319 entry = entry.next; | |
| 320 } | |
| 321 return null; | |
| 322 } | |
| 323 | |
| 324 void operator []=(K key, V value) { | |
| 325 int hashCode = key.hashCode; | |
| 326 List buckets = _buckets; | |
| 327 int length = buckets.length; | |
| 328 int index = hashCode & (length - 1); | |
| 329 _HashMapEntry entry = buckets[index]; | |
| 330 while (entry != null) { | |
| 331 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
| 332 entry.value = value; | |
| 333 return; | |
| 334 } | |
| 335 entry = entry.next; | |
| 336 } | |
| 337 _addEntry(buckets, index, length, key, value, hashCode); | |
| 338 } | |
| 339 | |
| 340 V putIfAbsent(K key, V ifAbsent()) { | |
| 341 int hashCode = key.hashCode; | |
| 342 List buckets = _buckets; | |
| 343 int length = buckets.length; | |
| 344 int index = hashCode & (length - 1); | |
| 345 _HashMapEntry entry = buckets[index]; | |
| 346 while (entry != null) { | |
| 347 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
| 348 return entry.value; | |
| 349 } | |
| 350 entry = entry.next; | |
| 351 } | |
| 352 int stamp = _modificationCount; | |
| 353 V value = ifAbsent(); | |
| 354 if (stamp == _modificationCount) { | |
| 355 _addEntry(buckets, index, length, key, value, hashCode); | |
| 356 } else { | |
| 357 this[key] = value; | |
| 358 } | |
| 359 return value; | |
| 360 } | |
| 361 | |
| 362 V remove(Object key) { | |
| 363 int hashCode = key.hashCode; | |
| 364 List buckets = _buckets; | |
| 365 int index = hashCode & (buckets.length - 1); | |
| 366 _HashMapEntry entry = buckets[index]; | |
| 367 _HashMapEntry previous = null; | |
| 368 while (entry != null) { | |
| 369 _HashMapEntry next = entry.next; | |
| 370 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
| 371 if (previous == null) { | |
| 372 buckets[index] = next; | |
| 373 } else { | |
| 374 previous.next = next; | |
| 375 } | |
| 376 _elementCount--; | |
| 377 _modificationCount = | |
| 378 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | |
| 379 return entry.value; | |
| 380 } | |
| 381 previous = entry; | |
| 382 entry = next; | |
| 383 } | |
| 384 return null; | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 | |
| 389 class _HashMapEntry { | 185 class _HashMapEntry { |
| 390 final key; | 186 final key; |
| 391 var value; | 187 var value; |
| 392 final int hashCode; | 188 final int hashCode; |
| 393 _HashMapEntry next; | 189 _HashMapEntry next; |
| 394 _HashMapEntry(this.key, this.value, this.hashCode, this.next); | 190 _HashMapEntry(this.key, this.value, this.hashCode, this.next); |
| 395 } | 191 } |
| 396 | 192 |
| 397 abstract class _HashMapIterable<E> extends IterableBase<E> { | 193 abstract class _HashMapIterable<E> extends IterableBase<E> { |
| 398 final HashMap _map; | 194 final HashMap _map; |
| (...skipping 1112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 | 1307 |
| 1512 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); | 1308 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); |
| 1513 | 1309 |
| 1514 V _value(int offset) => _table[offset + _VALUE_INDEX]; | 1310 V _value(int offset) => _table[offset + _VALUE_INDEX]; |
| 1515 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } | 1311 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } |
| 1516 | 1312 |
| 1517 _copyEntry(List oldTable, int fromOffset, int toOffset) { | 1313 _copyEntry(List oldTable, int fromOffset, int toOffset) { |
| 1518 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; | 1314 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; |
| 1519 } | 1315 } |
| 1520 } | 1316 } |
| OLD | NEW |