| 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), | 6 /* patch */ factory HashMap({ bool equals(K key1, K key2), |
| 7 int hashCode(K key), | 7 int hashCode(K key), |
| 8 bool isValidKey(potentialKey) }) { | 8 bool isValidKey(potentialKey) }) { |
| 9 if (isValidKey == null) { | 9 if (isValidKey == null) { |
| 10 if (hashCode == null) { | 10 if (hashCode == null) { |
| 11 if (equals == null) { | 11 if (equals == null) { |
| 12 return new _HashMap<K, V>(); | 12 return new _HashMap<K, V>(); |
| 13 } | 13 } |
| 14 if (identical(identical, equals)) { | 14 hashCode = _defaultHashCode; |
| 15 } else { |
| 16 if (identical(identityHashCode, hashCode) && |
| 17 identical(identical, equals)) { |
| 15 return new _IdentityHashMap<K, V>(); | 18 return new _IdentityHashMap<K, V>(); |
| 16 } | 19 } |
| 17 hashCode = _defaultHashCode; | 20 if (equals == null) { |
| 18 } else if (equals == null) { | 21 equals = _defaultEquals; |
| 19 equals = _defaultEquals; | 22 } |
| 20 } | 23 } |
| 21 } else { | 24 } else { |
| 22 if (hashCode == null) { | 25 if (hashCode == null) { |
| 23 hashCode = _defaultHashCode; | 26 hashCode = _defaultHashCode; |
| 24 } | 27 } |
| 25 if (equals == null) { | 28 if (equals == null) { |
| 26 equals = _defaultEquals; | 29 equals = _defaultEquals; |
| 27 } | 30 } |
| 28 } | 31 } |
| 29 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); | 32 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); |
| 30 } | 33 } |
| 34 |
| 35 /* patch */ factory HashMap.identity() = _IdentityHashMap<K, V>; |
| 31 } | 36 } |
| 32 | 37 |
| 38 |
| 33 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; | 39 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; |
| 34 | 40 |
| 35 class _HashMap<K, V> implements HashMap<K, V> { | 41 class _HashMap<K, V> implements HashMap<K, V> { |
| 36 static const int _INITIAL_CAPACITY = 8; | 42 static const int _INITIAL_CAPACITY = 8; |
| 37 | 43 |
| 38 | 44 |
| 39 int _elementCount = 0; | 45 int _elementCount = 0; |
| 40 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); | 46 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); |
| 41 int _modificationCount = 0; | 47 int _modificationCount = 0; |
| 42 | 48 |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 } | 319 } |
| 314 return null; | 320 return null; |
| 315 } | 321 } |
| 316 | 322 |
| 317 String toString() => Maps.mapToString(this); | 323 String toString() => Maps.mapToString(this); |
| 318 } | 324 } |
| 319 | 325 |
| 320 class _IdentityHashMap<K, V> extends _HashMap<K, V> { | 326 class _IdentityHashMap<K, V> extends _HashMap<K, V> { |
| 321 | 327 |
| 322 bool containsKey(Object key) { | 328 bool containsKey(Object key) { |
| 323 int hashCode = key.hashCode; | 329 int hashCode = identityHashCode(key); |
| 324 List buckets = _buckets; | 330 List buckets = _buckets; |
| 325 int index = hashCode & (buckets.length - 1); | 331 int index = hashCode & (buckets.length - 1); |
| 326 _HashMapEntry entry = buckets[index]; | 332 _HashMapEntry entry = buckets[index]; |
| 327 while (entry != null) { | 333 while (entry != null) { |
| 328 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; | 334 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; |
| 329 entry = entry.next; | 335 entry = entry.next; |
| 330 } | 336 } |
| 331 return false; | 337 return false; |
| 332 } | 338 } |
| 333 | 339 |
| 334 V operator[](Object key) { | 340 V operator[](Object key) { |
| 335 int hashCode = key.hashCode; | 341 int hashCode = identityHashCode(key); |
| 336 List buckets = _buckets; | 342 List buckets = _buckets; |
| 337 int index = hashCode & (buckets.length - 1); | 343 int index = hashCode & (buckets.length - 1); |
| 338 _HashMapEntry entry = buckets[index]; | 344 _HashMapEntry entry = buckets[index]; |
| 339 while (entry != null) { | 345 while (entry != null) { |
| 340 if (hashCode == entry.hashCode && identical(entry.key, key)) { | 346 if (hashCode == entry.hashCode && identical(entry.key, key)) { |
| 341 return entry.value; | 347 return entry.value; |
| 342 } | 348 } |
| 343 entry = entry.next; | 349 entry = entry.next; |
| 344 } | 350 } |
| 345 return null; | 351 return null; |
| 346 } | 352 } |
| 347 | 353 |
| 348 void operator []=(K key, V value) { | 354 void operator []=(K key, V value) { |
| 349 int hashCode = key.hashCode; | 355 int hashCode = identityHashCode(key); |
| 350 List buckets = _buckets; | 356 List buckets = _buckets; |
| 351 int length = buckets.length; | 357 int length = buckets.length; |
| 352 int index = hashCode & (length - 1); | 358 int index = hashCode & (length - 1); |
| 353 _HashMapEntry entry = buckets[index]; | 359 _HashMapEntry entry = buckets[index]; |
| 354 while (entry != null) { | 360 while (entry != null) { |
| 355 if (hashCode == entry.hashCode && identical(entry.key, key)) { | 361 if (hashCode == entry.hashCode && identical(entry.key, key)) { |
| 356 entry.value = value; | 362 entry.value = value; |
| 357 return; | 363 return; |
| 358 } | 364 } |
| 359 entry = entry.next; | 365 entry = entry.next; |
| 360 } | 366 } |
| 361 _addEntry(buckets, index, length, key, value, hashCode); | 367 _addEntry(buckets, index, length, key, value, hashCode); |
| 362 } | 368 } |
| 363 | 369 |
| 364 V putIfAbsent(K key, V ifAbsent()) { | 370 V putIfAbsent(K key, V ifAbsent()) { |
| 365 int hashCode = key.hashCode; | 371 int hashCode = identityHashCode(key); |
| 366 List buckets = _buckets; | 372 List buckets = _buckets; |
| 367 int length = buckets.length; | 373 int length = buckets.length; |
| 368 int index = hashCode & (length - 1); | 374 int index = hashCode & (length - 1); |
| 369 _HashMapEntry entry = buckets[index]; | 375 _HashMapEntry entry = buckets[index]; |
| 370 while (entry != null) { | 376 while (entry != null) { |
| 371 if (hashCode == entry.hashCode && identical(entry.key, key)) { | 377 if (hashCode == entry.hashCode && identical(entry.key, key)) { |
| 372 return entry.value; | 378 return entry.value; |
| 373 } | 379 } |
| 374 entry = entry.next; | 380 entry = entry.next; |
| 375 } | 381 } |
| 376 int stamp = _modificationCount; | 382 int stamp = _modificationCount; |
| 377 V value = ifAbsent(); | 383 V value = ifAbsent(); |
| 378 if (stamp == _modificationCount) { | 384 if (stamp == _modificationCount) { |
| 379 _addEntry(buckets, index, length, key, value, hashCode); | 385 _addEntry(buckets, index, length, key, value, hashCode); |
| 380 } else { | 386 } else { |
| 381 this[key] = value; | 387 this[key] = value; |
| 382 } | 388 } |
| 383 return value; | 389 return value; |
| 384 } | 390 } |
| 385 | 391 |
| 386 V remove(Object key) { | 392 V remove(Object key) { |
| 387 int hashCode = key.hashCode; | 393 int hashCode = identityHashCode(key); |
| 388 List buckets = _buckets; | 394 List buckets = _buckets; |
| 389 int index = hashCode & (buckets.length - 1); | 395 int index = hashCode & (buckets.length - 1); |
| 390 _HashMapEntry entry = buckets[index]; | 396 _HashMapEntry entry = buckets[index]; |
| 391 _HashMapEntry previous = null; | 397 _HashMapEntry previous = null; |
| 392 while (entry != null) { | 398 while (entry != null) { |
| 393 _HashMapEntry next = entry.next; | 399 _HashMapEntry next = entry.next; |
| 394 if (hashCode == entry.hashCode && identical(entry.key, key)) { | 400 if (hashCode == entry.hashCode && identical(entry.key, key)) { |
| 395 _removeEntry(entry, previous, index); | 401 _removeEntry(entry, previous, index); |
| 396 _elementCount--; | 402 _elementCount--; |
| 397 _modificationCount = | 403 _modificationCount = |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 | 508 |
| 503 patch class HashSet<E> { | 509 patch class HashSet<E> { |
| 504 /* patch */ factory HashSet({ bool equals(E e1, E e2), | 510 /* patch */ factory HashSet({ bool equals(E e1, E e2), |
| 505 int hashCode(E e), | 511 int hashCode(E e), |
| 506 bool isValidKey(potentialKey) }) { | 512 bool isValidKey(potentialKey) }) { |
| 507 if (isValidKey == null) { | 513 if (isValidKey == null) { |
| 508 if (hashCode == null) { | 514 if (hashCode == null) { |
| 509 if (equals == null) { | 515 if (equals == null) { |
| 510 return new _HashSet<E>(); | 516 return new _HashSet<E>(); |
| 511 } | 517 } |
| 512 if (identical(identical, equals)) { | 518 hashCode = _defaultHashCode; |
| 519 } else { |
| 520 if (identical(identityHashCode, hashCode) && |
| 521 identical(identical, equals)) { |
| 513 return new _IdentityHashSet<E>(); | 522 return new _IdentityHashSet<E>(); |
| 514 } | 523 } |
| 515 _hashCode = _defaultHashCode; | 524 if (equals == null) { |
| 516 } else if (equals == null) { | 525 equals = _defaultEquals; |
| 517 _equals = _defaultEquals; | 526 } |
| 518 } | 527 } |
| 519 isValidKey = new _TypeTest<E>().test; | |
| 520 } else { | 528 } else { |
| 521 if (hashCode == null) hashCode = _defaultHashCode; | 529 if (hashCode == null) { |
| 522 if (equals == null) equals = _defaultEquals; | 530 hashCode = _defaultHashCode; |
| 531 } |
| 532 if (equals == null) { |
| 533 equals = _defaultEquals; |
| 534 } |
| 523 } | 535 } |
| 524 return new _CustomHashSet<E>(equals, hashCode, isValidKey); | 536 return new _CustomHashSet<E>(equals, hashCode, isValidKey); |
| 525 } | 537 } |
| 538 |
| 539 /* patch */ factory HashSet.identity() = _IdentityHashSet<E>; |
| 526 } | 540 } |
| 527 | 541 |
| 528 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { | 542 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { |
| 529 static const int _INITIAL_CAPACITY = 8; | 543 static const int _INITIAL_CAPACITY = 8; |
| 530 | 544 |
| 531 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); | 545 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); |
| 532 int _elementCount = 0; | 546 int _elementCount = 0; |
| 533 int _modificationCount = 0; | 547 int _modificationCount = 0; |
| 534 | 548 |
| 535 bool _equals(e1, e2) => e1 == e2; | 549 bool _equals(e1, e2) => e1 == e2; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 entry = next; | 695 entry = next; |
| 682 } | 696 } |
| 683 } | 697 } |
| 684 _buckets = newBuckets; | 698 _buckets = newBuckets; |
| 685 } | 699 } |
| 686 | 700 |
| 687 HashSet<E> _newSet() => new _HashSet<E>(); | 701 HashSet<E> _newSet() => new _HashSet<E>(); |
| 688 } | 702 } |
| 689 | 703 |
| 690 class _IdentityHashSet<E> extends _HashSet<E> { | 704 class _IdentityHashSet<E> extends _HashSet<E> { |
| 705 int _hashCode(e) => identityHashCode(e); |
| 691 bool _equals(e1, e2) => identical(e1, e2); | 706 bool _equals(e1, e2) => identical(e1, e2); |
| 692 HashSet<E> _newSet() => new _IdentityHashSet<E>(); | 707 HashSet<E> _newSet() => new _IdentityHashSet<E>(); |
| 693 } | 708 } |
| 694 | 709 |
| 695 class _CustomHashSet<E> extends _HashSet<E> { | 710 class _CustomHashSet<E> extends _HashSet<E> { |
| 696 final _Equality<E> _equality; | 711 final _Equality<E> _equality; |
| 697 final _Hasher<E> _hasher; | 712 final _Hasher<E> _hasher; |
| 698 final _Predicate _validKey; | 713 final _Predicate _validKey; |
| 699 _CustomHashSet(this._equality, this._hasher, this._validKey); | 714 _CustomHashSet(this._equality, this._hasher, bool validKey(Object o)) |
| 715 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test; |
| 700 | 716 |
| 701 bool remove(Object element) { | 717 bool remove(Object element) { |
| 702 if (!_validKey(element)) return false; | 718 if (!_validKey(element)) return false; |
| 703 return super.remove(element); | 719 return super.remove(element); |
| 704 } | 720 } |
| 705 | 721 |
| 706 bool contains(Object element) { | 722 bool contains(Object element) { |
| 707 if (!_validKey(element)) return false; | 723 if (!_validKey(element)) return false; |
| 708 return super.contains(element); | 724 return super.contains(element); |
| 709 } | 725 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 var _previousEntry; | 886 var _previousEntry; |
| 871 | 887 |
| 872 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2), | 888 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2), |
| 873 int hashCode(K key), | 889 int hashCode(K key), |
| 874 bool isValidKey(potentialKey) }) { | 890 bool isValidKey(potentialKey) }) { |
| 875 if (isValidKey == null) { | 891 if (isValidKey == null) { |
| 876 if (hashCode == null) { | 892 if (hashCode == null) { |
| 877 if (equals == null) { | 893 if (equals == null) { |
| 878 return new _LinkedHashMap<K, V>(); | 894 return new _LinkedHashMap<K, V>(); |
| 879 } | 895 } |
| 880 if (identical(identical, equals)) { | 896 hashCode = _defaultHashCode; |
| 897 } else { |
| 898 if (identical(identityHashCode, hashCode) && |
| 899 identical(identical, equals)) { |
| 881 return new _LinkedIdentityHashMap<K, V>(); | 900 return new _LinkedIdentityHashMap<K, V>(); |
| 882 } | 901 } |
| 883 hashCode = _defaultHashCode; | 902 if (equals == null) { |
| 884 } else if (equals == null) { | 903 equals = _defaultEquals; |
| 885 equals = _defaultEquals; | 904 } |
| 886 } | 905 } |
| 887 } else { | 906 } else { |
| 888 if (hashCode == null) { | 907 if (hashCode == null) { |
| 889 hashCode = _defaultHashCode; | 908 hashCode = _defaultHashCode; |
| 890 } | 909 } |
| 891 if (equals == null) { | 910 if (equals == null) { |
| 892 equals = _defaultEquals; | 911 equals = _defaultEquals; |
| 893 } | 912 } |
| 894 } | 913 } |
| 895 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); | 914 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); |
| 896 } | 915 } |
| 916 |
| 917 /* patch */ factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>; |
| 897 } | 918 } |
| 898 | 919 |
| 899 // Methods that are exactly the same in all three linked hash map variants. | 920 // Methods that are exactly the same in all three linked hash map variants. |
| 900 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> { | 921 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> { |
| 901 var _nextEntry; | 922 var _nextEntry; |
| 902 var _previousEntry; | 923 var _previousEntry; |
| 903 | 924 |
| 904 | 925 |
| 905 bool containsValue(Object value) { | 926 bool containsValue(Object value) { |
| 906 int modificationCount = _modificationCount; | 927 int modificationCount = _modificationCount; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 | 1018 |
| 998 patch class LinkedHashSet<E> { | 1019 patch class LinkedHashSet<E> { |
| 999 /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2), | 1020 /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2), |
| 1000 int hashCode(E e), | 1021 int hashCode(E e), |
| 1001 bool isValidKey(potentialKey) }) { | 1022 bool isValidKey(potentialKey) }) { |
| 1002 if (isValidKey == null) { | 1023 if (isValidKey == null) { |
| 1003 if (hashCode == null) { | 1024 if (hashCode == null) { |
| 1004 if (equals == null) { | 1025 if (equals == null) { |
| 1005 return new _LinkedHashSet<E>(); | 1026 return new _LinkedHashSet<E>(); |
| 1006 } | 1027 } |
| 1007 if (identical(identical, equals)) { | 1028 hashCode = _defaultHashCode; |
| 1029 } else { |
| 1030 if (identical(identityHashCode, hashCode) && |
| 1031 identical(identical, equals)) { |
| 1008 return new _LinkedIdentityHashSet<E>(); | 1032 return new _LinkedIdentityHashSet<E>(); |
| 1009 } | 1033 } |
| 1010 _hashCode = _defaultHashCode; | 1034 if (equals == null) { |
| 1011 } else if (equals == null) { | 1035 equals = _defaultEquals; |
| 1012 _equals = _defaultEquals; | 1036 } |
| 1013 } | 1037 } |
| 1014 isValidKey = new _TypeTest<E>().test; | |
| 1015 } else { | 1038 } else { |
| 1016 if (hashCode == null) hashCode = _defaultHashCode; | 1039 if (hashCode == null) { |
| 1017 if (equals == null) equals = _defaultEquals; | 1040 hashCode = _defaultHashCode; |
| 1041 } |
| 1042 if (equals == null) { |
| 1043 equals = _defaultEquals; |
| 1044 } |
| 1018 } | 1045 } |
| 1019 return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey); | 1046 return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey); |
| 1020 } | 1047 } |
| 1048 |
| 1049 /* patch */ factory LinkedHashSet.identity() = _LinkedIdentityHashSet<E>; |
| 1021 } | 1050 } |
| 1022 | 1051 |
| 1023 class _LinkedHashSetEntry extends _HashSetEntry { | 1052 class _LinkedHashSetEntry extends _HashSetEntry { |
| 1024 /// Links this element into a double-linked list of elements of a hash set. | 1053 /// Links this element into a double-linked list of elements of a hash set. |
| 1025 /// The hash set object itself is used as the head entry of the list, so | 1054 /// The hash set object itself is used as the head entry of the list, so |
| 1026 /// the field is typed as "var". | 1055 /// the field is typed as "var". |
| 1027 /// Both links are initialized to `this` when the object is created. | 1056 /// Both links are initialized to `this` when the object is created. |
| 1028 var _nextEntry; | 1057 var _nextEntry; |
| 1029 var _previousEntry; | 1058 var _previousEntry; |
| 1030 _LinkedHashSetEntry(var key, int hashCode, _LinkedHashSetEntry next, | 1059 _LinkedHashSetEntry(var key, int hashCode, _LinkedHashSetEntry next, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 | 1151 |
| 1123 void clear() { | 1152 void clear() { |
| 1124 _nextEntry = _previousEntry = this; | 1153 _nextEntry = _previousEntry = this; |
| 1125 super.clear(); | 1154 super.clear(); |
| 1126 } | 1155 } |
| 1127 | 1156 |
| 1128 HashSet<E> _newSet() => new _LinkedHashSet<E>(); | 1157 HashSet<E> _newSet() => new _LinkedHashSet<E>(); |
| 1129 } | 1158 } |
| 1130 | 1159 |
| 1131 class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> { | 1160 class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> { |
| 1161 int _hashCode(e) => identityHashCode(e); |
| 1132 bool _equals(e1, e2) => identical(e1, e2); | 1162 bool _equals(e1, e2) => identical(e1, e2); |
| 1133 HashSet<E> _newSet() => new _LinkedIdentityHashSet<E>(); | 1163 HashSet<E> _newSet() => new _LinkedIdentityHashSet<E>(); |
| 1134 } | 1164 } |
| 1135 | 1165 |
| 1136 class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> { | 1166 class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> { |
| 1137 final _Equality<E> _equality; | 1167 final _Equality<E> _equality; |
| 1138 final _Hasher<E> _hasher; | 1168 final _Hasher<E> _hasher; |
| 1139 final _Predicate _validKey; | 1169 final _Predicate _validKey; |
| 1140 | 1170 |
| 1141 _LinkedCustomHashSet(this._equality, this._hasher, bool validKey(object)) | 1171 _LinkedCustomHashSet(this._equality, this._hasher, bool validKey(Object o)) |
| 1142 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test; | 1172 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test; |
| 1143 | 1173 |
| 1144 bool _equals(e1, e2) => _equality(e1, e2); | 1174 bool _equals(e1, e2) => _equality(e1, e2); |
| 1145 | 1175 |
| 1146 int _hashCode(e) => _hasher(e); | 1176 int _hashCode(e) => _hasher(e); |
| 1147 | 1177 |
| 1148 bool contains(Object o) { | 1178 bool contains(Object o) { |
| 1149 if (!_validKey(o)) return false; | 1179 if (!_validKey(o)) return false; |
| 1150 return super.contains(o); | 1180 return super.contains(o); |
| 1151 } | 1181 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 return false; | 1228 return false; |
| 1199 } | 1229 } |
| 1200 _LinkedHashSetEntry entry = _next; | 1230 _LinkedHashSetEntry entry = _next; |
| 1201 _current = entry.key; | 1231 _current = entry.key; |
| 1202 _next = entry._nextEntry; | 1232 _next = entry._nextEntry; |
| 1203 return true; | 1233 return true; |
| 1204 } | 1234 } |
| 1205 | 1235 |
| 1206 E get current => _current; | 1236 E get current => _current; |
| 1207 } | 1237 } |
| OLD | NEW |