| 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 import 'dart:typed_data'; | 5 import 'dart:typed_data'; |
| 6 import 'dart:_internal' as internal; | 6 import 'dart:_internal' as internal; |
| 7 | 7 |
| 8 @patch class HashMap<K, V> { | 8 @patch |
| 9 @patch factory HashMap({ bool equals(K key1, K key2), | 9 class HashMap<K, V> { |
| 10 int hashCode(K key), | 10 @patch |
| 11 bool isValidKey(potentialKey) }) { | 11 factory HashMap( |
| 12 {bool equals(K key1, K key2), |
| 13 int hashCode(K key), |
| 14 bool isValidKey(potentialKey)}) { |
| 12 if (isValidKey == null) { | 15 if (isValidKey == null) { |
| 13 if (hashCode == null) { | 16 if (hashCode == null) { |
| 14 if (equals == null) { | 17 if (equals == null) { |
| 15 return new _HashMap<K, V>(); | 18 return new _HashMap<K, V>(); |
| 16 } | 19 } |
| 17 hashCode = _defaultHashCode; | 20 hashCode = _defaultHashCode; |
| 18 } else { | 21 } else { |
| 19 if (identical(identityHashCode, hashCode) && | 22 if (identical(identityHashCode, hashCode) && |
| 20 identical(identical, equals)) { | 23 identical(identical, equals)) { |
| 21 return new _IdentityHashMap<K, V>(); | 24 return new _IdentityHashMap<K, V>(); |
| 22 } | 25 } |
| 23 if (equals == null) { | 26 if (equals == null) { |
| 24 equals = _defaultEquals; | 27 equals = _defaultEquals; |
| 25 } | 28 } |
| 26 } | 29 } |
| 27 } else { | 30 } else { |
| 28 if (hashCode == null) { | 31 if (hashCode == null) { |
| 29 hashCode = _defaultHashCode; | 32 hashCode = _defaultHashCode; |
| 30 } | 33 } |
| 31 if (equals == null) { | 34 if (equals == null) { |
| 32 equals = _defaultEquals; | 35 equals = _defaultEquals; |
| 33 } | 36 } |
| 34 } | 37 } |
| 35 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); | 38 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); |
| 36 } | 39 } |
| 37 | 40 |
| 38 @patch factory HashMap.identity() = _IdentityHashMap<K, V>; | 41 @patch |
| 42 factory HashMap.identity() = _IdentityHashMap<K, V>; |
| 39 | 43 |
| 40 Set<K> _newKeySet(); | 44 Set<K> _newKeySet(); |
| 41 } | 45 } |
| 42 | 46 |
| 43 | |
| 44 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; | 47 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; |
| 45 | 48 |
| 46 class _HashMap<K, V> implements HashMap<K, V> { | 49 class _HashMap<K, V> implements HashMap<K, V> { |
| 47 static const int _INITIAL_CAPACITY = 8; | 50 static const int _INITIAL_CAPACITY = 8; |
| 48 | 51 |
| 49 | |
| 50 int _elementCount = 0; | 52 int _elementCount = 0; |
| 51 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); | 53 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); |
| 52 int _modificationCount = 0; | 54 int _modificationCount = 0; |
| 53 | 55 |
| 54 int get length => _elementCount; | 56 int get length => _elementCount; |
| 55 bool get isEmpty => _elementCount == 0; | 57 bool get isEmpty => _elementCount == 0; |
| 56 bool get isNotEmpty => _elementCount != 0; | 58 bool get isNotEmpty => _elementCount != 0; |
| 57 | 59 |
| 58 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); | 60 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); |
| 59 Iterable<V> get values => new _HashMapValueIterable<V>(this); | 61 Iterable<V> get values => new _HashMapValueIterable<V>(this); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 76 for (int i = 0; i < length; i++) { | 78 for (int i = 0; i < length; i++) { |
| 77 _HashMapEntry entry = buckets[i]; | 79 _HashMapEntry entry = buckets[i]; |
| 78 while (entry != null) { | 80 while (entry != null) { |
| 79 if (entry.value == value) return true; | 81 if (entry.value == value) return true; |
| 80 entry = entry.next; | 82 entry = entry.next; |
| 81 } | 83 } |
| 82 } | 84 } |
| 83 return false; | 85 return false; |
| 84 } | 86 } |
| 85 | 87 |
| 86 V operator[](Object key) { | 88 V operator [](Object key) { |
| 87 int hashCode = key.hashCode; | 89 int hashCode = key.hashCode; |
| 88 List buckets = _buckets; | 90 List buckets = _buckets; |
| 89 int index = hashCode & (buckets.length - 1); | 91 int index = hashCode & (buckets.length - 1); |
| 90 _HashMapEntry entry = buckets[index]; | 92 _HashMapEntry entry = buckets[index]; |
| 91 while (entry != null) { | 93 while (entry != null) { |
| 92 if (hashCode == entry.hashCode && entry.key == key) { | 94 if (hashCode == entry.hashCode && entry.key == key) { |
| 93 return entry.value; | 95 return entry.value; |
| 94 } | 96 } |
| 95 entry = entry.next; | 97 entry = entry.next; |
| 96 } | 98 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 } | 181 } |
| 180 | 182 |
| 181 void clear() { | 183 void clear() { |
| 182 _buckets = new List(_INITIAL_CAPACITY); | 184 _buckets = new List(_INITIAL_CAPACITY); |
| 183 if (_elementCount > 0) { | 185 if (_elementCount > 0) { |
| 184 _elementCount = 0; | 186 _elementCount = 0; |
| 185 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 187 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
| 186 } | 188 } |
| 187 } | 189 } |
| 188 | 190 |
| 189 void _removeEntry(_HashMapEntry entry, | 191 void _removeEntry( |
| 190 _HashMapEntry previousInBucket, | 192 _HashMapEntry entry, _HashMapEntry previousInBucket, int bucketIndex) { |
| 191 int bucketIndex) { | |
| 192 if (previousInBucket == null) { | 193 if (previousInBucket == null) { |
| 193 _buckets[bucketIndex] = entry.next; | 194 _buckets[bucketIndex] = entry.next; |
| 194 } else { | 195 } else { |
| 195 previousInBucket.next = entry.next; | 196 previousInBucket.next = entry.next; |
| 196 } | 197 } |
| 197 } | 198 } |
| 198 | 199 |
| 199 void _addEntry(List buckets, int index, int length, | 200 void _addEntry( |
| 200 K key, V value, int hashCode) { | 201 List buckets, int index, int length, K key, V value, int hashCode) { |
| 201 _HashMapEntry entry = | 202 _HashMapEntry entry = |
| 202 new _HashMapEntry(key, value, hashCode, buckets[index]); | 203 new _HashMapEntry(key, value, hashCode, buckets[index]); |
| 203 buckets[index] = entry; | 204 buckets[index] = entry; |
| 204 int newElements = _elementCount + 1; | 205 int newElements = _elementCount + 1; |
| 205 _elementCount = newElements; | 206 _elementCount = newElements; |
| 206 // If we end up with more than 75% non-empty entries, we | 207 // If we end up with more than 75% non-empty entries, we |
| 207 // resize the backing store. | 208 // resize the backing store. |
| 208 if ((newElements << 2) > ((length << 1) + length)) _resize(); | 209 if ((newElements << 2) > ((length << 1) + length)) _resize(); |
| 209 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 210 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
| 210 } | 211 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 233 Set<K> _newKeySet() => new _HashSet<K>(); | 234 Set<K> _newKeySet() => new _HashSet<K>(); |
| 234 } | 235 } |
| 235 | 236 |
| 236 class _CustomHashMap<K, V> extends _HashMap<K, V> { | 237 class _CustomHashMap<K, V> extends _HashMap<K, V> { |
| 237 final _Equality<K> _equals; | 238 final _Equality<K> _equals; |
| 238 final _Hasher<K> _hashCode; | 239 final _Hasher<K> _hashCode; |
| 239 final _Predicate _validKey; | 240 final _Predicate _validKey; |
| 240 _CustomHashMap(this._equals, this._hashCode, validKey) | 241 _CustomHashMap(this._equals, this._hashCode, validKey) |
| 241 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test; | 242 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test; |
| 242 | 243 |
| 243 | |
| 244 bool containsKey(Object key) { | 244 bool containsKey(Object key) { |
| 245 if (!_validKey(key)) return false; | 245 if (!_validKey(key)) return false; |
| 246 int hashCode = _hashCode(key); | 246 int hashCode = _hashCode(key); |
| 247 List buckets = _buckets; | 247 List buckets = _buckets; |
| 248 int index = hashCode & (buckets.length - 1); | 248 int index = hashCode & (buckets.length - 1); |
| 249 _HashMapEntry entry = buckets[index]; | 249 _HashMapEntry entry = buckets[index]; |
| 250 while (entry != null) { | 250 while (entry != null) { |
| 251 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; | 251 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; |
| 252 entry = entry.next; | 252 entry = entry.next; |
| 253 } | 253 } |
| 254 return false; | 254 return false; |
| 255 } | 255 } |
| 256 | 256 |
| 257 V operator[](Object key) { | 257 V operator [](Object key) { |
| 258 if (!_validKey(key)) return null; | 258 if (!_validKey(key)) return null; |
| 259 int hashCode = _hashCode(key); | 259 int hashCode = _hashCode(key); |
| 260 List buckets = _buckets; | 260 List buckets = _buckets; |
| 261 int index = hashCode & (buckets.length - 1); | 261 int index = hashCode & (buckets.length - 1); |
| 262 _HashMapEntry entry = buckets[index]; | 262 _HashMapEntry entry = buckets[index]; |
| 263 while (entry != null) { | 263 while (entry != null) { |
| 264 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | 264 if (hashCode == entry.hashCode && _equals(entry.key, key)) { |
| 265 return entry.value; | 265 return entry.value; |
| 266 } | 266 } |
| 267 entry = entry.next; | 267 entry = entry.next; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 } | 328 } |
| 329 return null; | 329 return null; |
| 330 } | 330 } |
| 331 | 331 |
| 332 String toString() => Maps.mapToString(this); | 332 String toString() => Maps.mapToString(this); |
| 333 | 333 |
| 334 Set<K> _newKeySet() => new _CustomHashSet<K>(_equals, _hashCode, _validKey); | 334 Set<K> _newKeySet() => new _CustomHashSet<K>(_equals, _hashCode, _validKey); |
| 335 } | 335 } |
| 336 | 336 |
| 337 class _IdentityHashMap<K, V> extends _HashMap<K, V> { | 337 class _IdentityHashMap<K, V> extends _HashMap<K, V> { |
| 338 | |
| 339 bool containsKey(Object key) { | 338 bool containsKey(Object key) { |
| 340 int hashCode = identityHashCode(key); | 339 int hashCode = identityHashCode(key); |
| 341 List buckets = _buckets; | 340 List buckets = _buckets; |
| 342 int index = hashCode & (buckets.length - 1); | 341 int index = hashCode & (buckets.length - 1); |
| 343 _HashMapEntry entry = buckets[index]; | 342 _HashMapEntry entry = buckets[index]; |
| 344 while (entry != null) { | 343 while (entry != null) { |
| 345 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; | 344 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; |
| 346 entry = entry.next; | 345 entry = entry.next; |
| 347 } | 346 } |
| 348 return false; | 347 return false; |
| 349 } | 348 } |
| 350 | 349 |
| 351 V operator[](Object key) { | 350 V operator [](Object key) { |
| 352 int hashCode = identityHashCode(key); | 351 int hashCode = identityHashCode(key); |
| 353 List buckets = _buckets; | 352 List buckets = _buckets; |
| 354 int index = hashCode & (buckets.length - 1); | 353 int index = hashCode & (buckets.length - 1); |
| 355 _HashMapEntry entry = buckets[index]; | 354 _HashMapEntry entry = buckets[index]; |
| 356 while (entry != null) { | 355 while (entry != null) { |
| 357 if (hashCode == entry.hashCode && identical(entry.key, key)) { | 356 if (hashCode == entry.hashCode && identical(entry.key, key)) { |
| 358 return entry.value; | 357 return entry.value; |
| 359 } | 358 } |
| 360 entry = entry.next; | 359 entry = entry.next; |
| 361 } | 360 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 entry = next; | 418 entry = next; |
| 420 } | 419 } |
| 421 return null; | 420 return null; |
| 422 } | 421 } |
| 423 | 422 |
| 424 String toString() => Maps.mapToString(this); | 423 String toString() => Maps.mapToString(this); |
| 425 | 424 |
| 426 Set<K> _newKeySet() => new _IdentityHashSet<K>(); | 425 Set<K> _newKeySet() => new _IdentityHashSet<K>(); |
| 427 } | 426 } |
| 428 | 427 |
| 429 | |
| 430 class _HashMapEntry { | 428 class _HashMapEntry { |
| 431 final key; | 429 final key; |
| 432 var value; | 430 var value; |
| 433 final int hashCode; | 431 final int hashCode; |
| 434 _HashMapEntry next; | 432 _HashMapEntry next; |
| 435 _HashMapEntry(this.key, this.value, this.hashCode, this.next); | 433 _HashMapEntry(this.key, this.value, this.hashCode, this.next); |
| 436 } | 434 } |
| 437 | 435 |
| 438 abstract class _HashMapIterable<E> extends EfficientLengthIterable<E> { | 436 abstract class _HashMapIterable<E> extends EfficientLengthIterable<E> { |
| 439 final HashMap _map; | 437 final HashMap _map; |
| 440 _HashMapIterable(this._map); | 438 _HashMapIterable(this._map); |
| 441 int get length => _map.length; | 439 int get length => _map.length; |
| 442 bool get isEmpty => _map.isEmpty; | 440 bool get isEmpty => _map.isEmpty; |
| 443 bool get isNotEmpty => _map.isNotEmpty; | 441 bool get isNotEmpty => _map.isNotEmpty; |
| 444 } | 442 } |
| 445 | 443 |
| 446 class _HashMapKeyIterable<K> extends _HashMapIterable<K> { | 444 class _HashMapKeyIterable<K> extends _HashMapIterable<K> { |
| 447 _HashMapKeyIterable(HashMap map) : super(map); | 445 _HashMapKeyIterable(HashMap map) : super(map); |
| 448 Iterator<K> get iterator => new _HashMapKeyIterator<K>(_map); | 446 Iterator<K> get iterator => new _HashMapKeyIterator<K>(_map); |
| 449 bool contains(Object key) => _map.containsKey(key); | 447 bool contains(Object key) => _map.containsKey(key); |
| 450 void forEach(void action(K key)) { | 448 void forEach(void action(K key)) { |
| 451 _map.forEach((K key, _) { | 449 _map.forEach((K key, _) { |
| 452 action(key); | 450 action(key); |
| 453 }); | 451 }); |
| 454 } | 452 } |
| 453 |
| 455 Set<K> toSet() => _map._newKeySet()..addAll(this); | 454 Set<K> toSet() => _map._newKeySet()..addAll(this); |
| 456 } | 455 } |
| 457 | 456 |
| 458 class _HashMapValueIterable<V> extends _HashMapIterable<V> { | 457 class _HashMapValueIterable<V> extends _HashMapIterable<V> { |
| 459 _HashMapValueIterable(HashMap map) : super(map); | 458 _HashMapValueIterable(HashMap map) : super(map); |
| 460 Iterator<V> get iterator => new _HashMapValueIterator<V>(_map); | 459 Iterator<V> get iterator => new _HashMapValueIterator<V>(_map); |
| 461 bool contains(Object value) => _map.containsValue(value); | 460 bool contains(Object value) => _map.containsValue(value); |
| 462 void forEach(void action(V value)) { | 461 void forEach(void action(V value)) { |
| 463 _map.forEach((_, V value) { | 462 _map.forEach((_, V value) { |
| 464 action(value); | 463 action(value); |
| 465 }); | 464 }); |
| 466 } | 465 } |
| 467 } | 466 } |
| 468 | 467 |
| 469 abstract class _HashMapIterator<E> implements Iterator<E> { | 468 abstract class _HashMapIterator<E> implements Iterator<E> { |
| 470 final HashMap _map; | 469 final HashMap _map; |
| 471 final int _stamp; | 470 final int _stamp; |
| 472 | 471 |
| 473 int _index = 0; | 472 int _index = 0; |
| 474 _HashMapEntry _entry; | 473 _HashMapEntry _entry; |
| 475 | 474 |
| 476 _HashMapIterator(HashMap map) | 475 _HashMapIterator(HashMap map) |
| 477 : _map = map, _stamp = map._modificationCount; | 476 : _map = map, |
| 477 _stamp = map._modificationCount; |
| 478 | 478 |
| 479 bool moveNext() { | 479 bool moveNext() { |
| 480 if (_stamp != _map._modificationCount) { | 480 if (_stamp != _map._modificationCount) { |
| 481 throw new ConcurrentModificationError(_map); | 481 throw new ConcurrentModificationError(_map); |
| 482 } | 482 } |
| 483 _HashMapEntry entry = _entry; | 483 _HashMapEntry entry = _entry; |
| 484 if (entry != null) { | 484 if (entry != null) { |
| 485 _HashMapEntry next = entry.next; | 485 _HashMapEntry next = entry.next; |
| 486 if (next != null) { | 486 if (next != null) { |
| 487 _entry = next; | 487 _entry = next; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 513 } | 513 } |
| 514 | 514 |
| 515 class _HashMapValueIterator<V> extends _HashMapIterator<V> { | 515 class _HashMapValueIterator<V> extends _HashMapIterator<V> { |
| 516 _HashMapValueIterator(HashMap map) : super(map); | 516 _HashMapValueIterator(HashMap map) : super(map); |
| 517 V get current { | 517 V get current { |
| 518 _HashMapEntry entry = _entry; | 518 _HashMapEntry entry = _entry; |
| 519 return (entry == null) ? null : entry.value; | 519 return (entry == null) ? null : entry.value; |
| 520 } | 520 } |
| 521 } | 521 } |
| 522 | 522 |
| 523 @patch class HashSet<E> { | 523 @patch |
| 524 @patch factory HashSet({ bool equals(E e1, E e2), | 524 class HashSet<E> { |
| 525 int hashCode(E e), | 525 @patch |
| 526 bool isValidKey(potentialKey) }) { | 526 factory HashSet( |
| 527 {bool equals(E e1, E e2), |
| 528 int hashCode(E e), |
| 529 bool isValidKey(potentialKey)}) { |
| 527 if (isValidKey == null) { | 530 if (isValidKey == null) { |
| 528 if (hashCode == null) { | 531 if (hashCode == null) { |
| 529 if (equals == null) { | 532 if (equals == null) { |
| 530 return new _HashSet<E>(); | 533 return new _HashSet<E>(); |
| 531 } | 534 } |
| 532 hashCode = _defaultHashCode; | 535 hashCode = _defaultHashCode; |
| 533 } else { | 536 } else { |
| 534 if (identical(identityHashCode, hashCode) && | 537 if (identical(identityHashCode, hashCode) && |
| 535 identical(identical, equals)) { | 538 identical(identical, equals)) { |
| 536 return new _IdentityHashSet<E>(); | 539 return new _IdentityHashSet<E>(); |
| 537 } | 540 } |
| 538 if (equals == null) { | 541 if (equals == null) { |
| 539 equals = _defaultEquals; | 542 equals = _defaultEquals; |
| 540 } | 543 } |
| 541 } | 544 } |
| 542 } else { | 545 } else { |
| 543 if (hashCode == null) { | 546 if (hashCode == null) { |
| 544 hashCode = _defaultHashCode; | 547 hashCode = _defaultHashCode; |
| 545 } | 548 } |
| 546 if (equals == null) { | 549 if (equals == null) { |
| 547 equals = _defaultEquals; | 550 equals = _defaultEquals; |
| 548 } | 551 } |
| 549 } | 552 } |
| 550 return new _CustomHashSet<E>(equals, hashCode, isValidKey); | 553 return new _CustomHashSet<E>(equals, hashCode, isValidKey); |
| 551 } | 554 } |
| 552 | 555 |
| 553 @patch factory HashSet.identity() = _IdentityHashSet<E>; | 556 @patch |
| 557 factory HashSet.identity() = _IdentityHashSet<E>; |
| 554 } | 558 } |
| 555 | 559 |
| 556 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { | 560 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { |
| 557 static const int _INITIAL_CAPACITY = 8; | 561 static const int _INITIAL_CAPACITY = 8; |
| 558 | 562 |
| 559 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); | 563 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); |
| 560 int _elementCount = 0; | 564 int _elementCount = 0; |
| 561 int _modificationCount = 0; | 565 int _modificationCount = 0; |
| 562 | 566 |
| 563 bool _equals(e1, e2) => e1 == e2; | 567 bool _equals(e1, e2) => e1 == e2; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 bool remove(Object object) => _remove(object, _hashCode(object)); | 646 bool remove(Object object) => _remove(object, _hashCode(object)); |
| 643 | 647 |
| 644 void removeAll(Iterable<Object> objectsToRemove) { | 648 void removeAll(Iterable<Object> objectsToRemove) { |
| 645 for (Object object in objectsToRemove) { | 649 for (Object object in objectsToRemove) { |
| 646 _remove(object, _hashCode(object)); | 650 _remove(object, _hashCode(object)); |
| 647 } | 651 } |
| 648 } | 652 } |
| 649 | 653 |
| 650 void _filterWhere(bool test(E element), bool removeMatching) { | 654 void _filterWhere(bool test(E element), bool removeMatching) { |
| 651 int length = _buckets.length; | 655 int length = _buckets.length; |
| 652 for (int index = 0; index < length; index++) { | 656 for (int index = 0; index < length; index++) { |
| 653 _HashSetEntry entry = _buckets[index]; | 657 _HashSetEntry entry = _buckets[index]; |
| 654 _HashSetEntry previous = null; | 658 _HashSetEntry previous = null; |
| 655 while (entry != null) { | 659 while (entry != null) { |
| 656 int modificationCount = _modificationCount; | 660 int modificationCount = _modificationCount; |
| 657 bool testResult = test(entry.key); | 661 bool testResult = test(entry.key); |
| 658 if (modificationCount != _modificationCount) { | 662 if (modificationCount != _modificationCount) { |
| 659 throw new ConcurrentModificationError(this); | 663 throw new ConcurrentModificationError(this); |
| 660 } | 664 } |
| 661 if (testResult == removeMatching) { | 665 if (testResult == removeMatching) { |
| 662 _HashSetEntry next = entry.remove(); | 666 _HashSetEntry next = entry.remove(); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 } | 792 } |
| 789 | 793 |
| 790 class _HashSetIterator<E> implements Iterator<E> { | 794 class _HashSetIterator<E> implements Iterator<E> { |
| 791 final _HashSet _set; | 795 final _HashSet _set; |
| 792 final int _modificationCount; | 796 final int _modificationCount; |
| 793 int _index = 0; | 797 int _index = 0; |
| 794 _HashSetEntry _next; | 798 _HashSetEntry _next; |
| 795 E _current; | 799 E _current; |
| 796 | 800 |
| 797 _HashSetIterator(_HashSet hashSet) | 801 _HashSetIterator(_HashSet hashSet) |
| 798 : _set = hashSet, _modificationCount = hashSet._modificationCount; | 802 : _set = hashSet, |
| 803 _modificationCount = hashSet._modificationCount; |
| 799 | 804 |
| 800 bool moveNext() { | 805 bool moveNext() { |
| 801 if (_modificationCount != _set._modificationCount) { | 806 if (_modificationCount != _set._modificationCount) { |
| 802 throw new ConcurrentModificationError(_set); | 807 throw new ConcurrentModificationError(_set); |
| 803 } | 808 } |
| 804 if (_next != null) { | 809 if (_next != null) { |
| 805 _current = _next.key; | 810 _current = _next.key; |
| 806 _next = _next.next; | 811 _next = _next.next; |
| 807 return true; | 812 return true; |
| 808 } | 813 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 823 E get current => _current; | 828 E get current => _current; |
| 824 } | 829 } |
| 825 | 830 |
| 826 class _LinkedHashMapEntry extends _HashMapEntry { | 831 class _LinkedHashMapEntry extends _HashMapEntry { |
| 827 /// Double-linked list of entries of a linked hash map. | 832 /// Double-linked list of entries of a linked hash map. |
| 828 /// The _LinkedHashMap itself is the head of the list, so the type is "var". | 833 /// The _LinkedHashMap itself is the head of the list, so the type is "var". |
| 829 /// Both are initialized to `this` when initialized. | 834 /// Both are initialized to `this` when initialized. |
| 830 var _nextEntry; | 835 var _nextEntry; |
| 831 var _previousEntry; | 836 var _previousEntry; |
| 832 _LinkedHashMapEntry(key, value, int hashCode, _LinkedHashMapEntry next, | 837 _LinkedHashMapEntry(key, value, int hashCode, _LinkedHashMapEntry next, |
| 833 this._previousEntry, this._nextEntry) | 838 this._previousEntry, this._nextEntry) |
| 834 : super(key, value, hashCode, next) { | 839 : super(key, value, hashCode, next) { |
| 835 _previousEntry._nextEntry = this; | 840 _previousEntry._nextEntry = this; |
| 836 _nextEntry._previousEntry = this; | 841 _nextEntry._previousEntry = this; |
| 837 } | 842 } |
| 838 } | 843 } |
| 839 | 844 |
| 840 class _LinkedHashMapKeyIterable<K> extends EfficientLengthIterable<K> { | 845 class _LinkedHashMapKeyIterable<K> extends EfficientLengthIterable<K> { |
| 841 LinkedHashMap<K, dynamic> _map; | 846 LinkedHashMap<K, dynamic> _map; |
| 842 _LinkedHashMapKeyIterable(this._map); | 847 _LinkedHashMapKeyIterable(this._map); |
| 843 Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map); | 848 Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { | 895 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { |
| 891 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map); | 896 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map); |
| 892 K _getValue(_LinkedHashMapEntry entry) => entry.key; | 897 K _getValue(_LinkedHashMapEntry entry) => entry.key; |
| 893 } | 898 } |
| 894 | 899 |
| 895 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { | 900 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { |
| 896 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map); | 901 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map); |
| 897 V _getValue(_LinkedHashMapEntry entry) => entry.value; | 902 V _getValue(_LinkedHashMapEntry entry) => entry.value; |
| 898 } | 903 } |
| 899 | 904 |
| 900 | |
| 901 /** | 905 /** |
| 902 * A hash-based map that iterates keys and values in key insertion order. | 906 * A hash-based map that iterates keys and values in key insertion order. |
| 903 */ | 907 */ |
| 904 @patch class LinkedHashMap<K, V> { | 908 @patch |
| 909 class LinkedHashMap<K, V> { |
| 905 /// Holds a double-linked list of entries in insertion order. | 910 /// Holds a double-linked list of entries in insertion order. |
| 906 /// The fields have the same name as the ones in [_LinkedHashMapEntry], | 911 /// The fields have the same name as the ones in [_LinkedHashMapEntry], |
| 907 /// and this map is itself used as the head entry of the list. | 912 /// and this map is itself used as the head entry of the list. |
| 908 /// Set to `this` when initialized, representing the empty list (containing | 913 /// Set to `this` when initialized, representing the empty list (containing |
| 909 /// only the head entry itself). | 914 /// only the head entry itself). |
| 910 var _nextEntry; | 915 var _nextEntry; |
| 911 var _previousEntry; | 916 var _previousEntry; |
| 912 | 917 |
| 913 @patch factory LinkedHashMap({ bool equals(K key1, K key2), | 918 @patch |
| 914 int hashCode(K key), | 919 factory LinkedHashMap( |
| 915 bool isValidKey(potentialKey) }) { | 920 {bool equals(K key1, K key2), |
| 921 int hashCode(K key), |
| 922 bool isValidKey(potentialKey)}) { |
| 916 if (isValidKey == null) { | 923 if (isValidKey == null) { |
| 917 if (hashCode == null) { | 924 if (hashCode == null) { |
| 918 if (equals == null) { | 925 if (equals == null) { |
| 919 return new _InternalLinkedHashMap<K, V>(); | 926 return new _InternalLinkedHashMap<K, V>(); |
| 920 } | 927 } |
| 921 hashCode = _defaultHashCode; | 928 hashCode = _defaultHashCode; |
| 922 } else { | 929 } else { |
| 923 if (identical(identityHashCode, hashCode) && | 930 if (identical(identityHashCode, hashCode) && |
| 924 identical(identical, equals)) { | 931 identical(identical, equals)) { |
| 925 return new _CompactLinkedIdentityHashMap<K, V>(); | 932 return new _CompactLinkedIdentityHashMap<K, V>(); |
| 926 } | 933 } |
| 927 if (equals == null) { | 934 if (equals == null) { |
| 928 equals = _defaultEquals; | 935 equals = _defaultEquals; |
| 929 } | 936 } |
| 930 } | 937 } |
| 931 } else { | 938 } else { |
| 932 if (hashCode == null) { | 939 if (hashCode == null) { |
| 933 hashCode = _defaultHashCode; | 940 hashCode = _defaultHashCode; |
| 934 } | 941 } |
| 935 if (equals == null) { | 942 if (equals == null) { |
| 936 equals = _defaultEquals; | 943 equals = _defaultEquals; |
| 937 } | 944 } |
| 938 } | 945 } |
| 939 return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); | 946 return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); |
| 940 } | 947 } |
| 941 | 948 |
| 942 @patch factory LinkedHashMap.identity() = | 949 @patch |
| 943 _CompactLinkedIdentityHashMap<K, V>; | 950 factory LinkedHashMap.identity() = _CompactLinkedIdentityHashMap<K, V>; |
| 944 } | 951 } |
| 945 | 952 |
| 946 @patch class LinkedHashSet<E> { | 953 @patch |
| 947 @patch factory LinkedHashSet({ bool equals(E e1, E e2), | 954 class LinkedHashSet<E> { |
| 948 int hashCode(E e), | 955 @patch |
| 949 bool isValidKey(potentialKey) }) { | 956 factory LinkedHashSet( |
| 957 {bool equals(E e1, E e2), |
| 958 int hashCode(E e), |
| 959 bool isValidKey(potentialKey)}) { |
| 950 if (isValidKey == null) { | 960 if (isValidKey == null) { |
| 951 if (hashCode == null) { | 961 if (hashCode == null) { |
| 952 if (equals == null) { | 962 if (equals == null) { |
| 953 return new _CompactLinkedHashSet<E>(); | 963 return new _CompactLinkedHashSet<E>(); |
| 954 } | 964 } |
| 955 hashCode = _defaultHashCode; | 965 hashCode = _defaultHashCode; |
| 956 } else { | 966 } else { |
| 957 if (identical(identityHashCode, hashCode) && | 967 if (identical(identityHashCode, hashCode) && |
| 958 identical(identical, equals)) { | 968 identical(identical, equals)) { |
| 959 return new _CompactLinkedIdentityHashSet<E>(); | 969 return new _CompactLinkedIdentityHashSet<E>(); |
| 960 } | 970 } |
| 961 if (equals == null) { | 971 if (equals == null) { |
| 962 equals = _defaultEquals; | 972 equals = _defaultEquals; |
| 963 } | 973 } |
| 964 } | 974 } |
| 965 } else { | 975 } else { |
| 966 if (hashCode == null) { | 976 if (hashCode == null) { |
| 967 hashCode = _defaultHashCode; | 977 hashCode = _defaultHashCode; |
| 968 } | 978 } |
| 969 if (equals == null) { | 979 if (equals == null) { |
| 970 equals = _defaultEquals; | 980 equals = _defaultEquals; |
| 971 } | 981 } |
| 972 } | 982 } |
| 973 return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey); | 983 return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey); |
| 974 } | 984 } |
| 975 | 985 |
| 976 @patch factory LinkedHashSet.identity() = | 986 @patch |
| 977 _CompactLinkedIdentityHashSet<E>; | 987 factory LinkedHashSet.identity() = _CompactLinkedIdentityHashSet<E>; |
| 978 } | 988 } |
| OLD | NEW |