Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: runtime/lib/collection_patch.dart

Issue 23872008: Reapply "Make LinkedHashMap also have a factory constructor and be customizable"" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 if (hashCode == null) { 8 bool isValidKey(potentialKey) }) {
9 if (isValidKey == null) {
10 if (hashCode == null) {
11 if (equals == null) {
12 return new _HashMap<K, V>();
13 }
14 if (identical(identical, equals)) {
15 return new _IdentityHashMap<K, V>();
16 }
17 hashCode = _defaultHashCode;
18 } else if (equals == null) {
19 equals = _defaultEquals;
20 }
21 } else {
22 if (hashCode == null) {
23 hashCode = _defaultHashCode;
24 }
9 if (equals == null) { 25 if (equals == null) {
10 return new _HashMapImpl<K, V>(); 26 equals = _defaultEquals;
11 } 27 }
12 if (identical(identical, equals)) {
13 return new _IdentityHashMap<K, V>();
14 }
15 hashCode = _defaultHashCode;
16 } else if (equals == null) {
17 equals = _defaultEquals;
18 } 28 }
19 return new _CustomHashMap<K, V>(equals, hashCode); 29 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey);
20 } 30 }
21 } 31 }
22 32
23 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; 33 const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
24 34
25 class _HashMapImpl<K, V> implements HashMap<K, V> { 35 class _HashMap<K, V> implements HashMap<K, V> {
26 static const int _INITIAL_CAPACITY = 8; 36 static const int _INITIAL_CAPACITY = 8;
27 37
38 Type get runtimeType => HashMap;
39
28 int _elementCount = 0; 40 int _elementCount = 0;
29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); 41 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
30 int _modificationCount = 0; 42 int _modificationCount = 0;
31 43
32 int get length => _elementCount; 44 int get length => _elementCount;
33 bool get isEmpty => _elementCount == 0; 45 bool get isEmpty => _elementCount == 0;
34 bool get isNotEmpty => _elementCount != 0; 46 bool get isNotEmpty => _elementCount != 0;
35 47
36 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); 48 Iterable<K> get keys => new _HashMapKeyIterable<K>(this);
37 Iterable<V> get values => new _HashMapValueIterable<V>(this); 49 Iterable<V> get values => new _HashMapValueIterable<V>(this);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 149
138 V remove(Object key) { 150 V remove(Object key) {
139 int hashCode = key.hashCode; 151 int hashCode = key.hashCode;
140 List buckets = _buckets; 152 List buckets = _buckets;
141 int index = hashCode & (buckets.length - 1); 153 int index = hashCode & (buckets.length - 1);
142 _HashMapEntry entry = buckets[index]; 154 _HashMapEntry entry = buckets[index];
143 _HashMapEntry previous = null; 155 _HashMapEntry previous = null;
144 while (entry != null) { 156 while (entry != null) {
145 _HashMapEntry next = entry.next; 157 _HashMapEntry next = entry.next;
146 if (hashCode == entry.hashCode && entry.key == key) { 158 if (hashCode == entry.hashCode && entry.key == key) {
147 if (previous == null) { 159 _removeEntry(entry, previous, index);
148 buckets[index] = next;
149 } else {
150 previous.next = next;
151 }
152 _elementCount--; 160 _elementCount--;
153 _modificationCount = 161 _modificationCount =
154 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 162 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
155 return entry.value; 163 return entry.value;
156 } 164 }
157 previous = entry; 165 previous = entry;
158 entry = next; 166 entry = next;
159 } 167 }
160 return null; 168 return null;
161 } 169 }
162 170
163 void clear() { 171 void clear() {
164 _elementCount = 0; 172 _elementCount = 0;
165 _buckets = new List(_INITIAL_CAPACITY); 173 _buckets = new List(_INITIAL_CAPACITY);
166 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 174 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
167 } 175 }
168 176
177 void _removeEntry(_HashMapEntry entry,
178 _HashMapEntry previousInBucket,
179 int bucketIndex) {
180 if (previousInBucket == null) {
181 _buckets[bucketIndex] = entry.next;
182 } else {
183 previousInBucket.next = entry.next;
184 }
185 }
186
169 void _addEntry(List buckets, int index, int length, 187 void _addEntry(List buckets, int index, int length,
170 K key, V value, int hashCode) { 188 K key, V value, int hashCode) {
171 _HashMapEntry entry = 189 _HashMapEntry entry =
172 new _HashMapEntry(key, value, hashCode, buckets[index]); 190 new _HashMapEntry(key, value, hashCode, buckets[index]);
173 buckets[index] = entry; 191 buckets[index] = entry;
174 int newElements = _elementCount + 1; 192 int newElements = _elementCount + 1;
175 _elementCount = newElements; 193 _elementCount = newElements;
176 // If we end up with more than 75% non-empty entries, we 194 // If we end up with more than 75% non-empty entries, we
177 // resize the backing store. 195 // resize the backing store.
178 if ((newElements << 2) > ((length << 1) + length)) _resize(); 196 if ((newElements << 2) > ((length << 1) + length)) _resize();
(...skipping 15 matching lines...) Expand all
194 newBuckets[index] = entry; 212 newBuckets[index] = entry;
195 entry = next; 213 entry = next;
196 } 214 }
197 } 215 }
198 _buckets = newBuckets; 216 _buckets = newBuckets;
199 } 217 }
200 218
201 String toString() => Maps.mapToString(this); 219 String toString() => Maps.mapToString(this);
202 } 220 }
203 221
204 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> { 222 class _CustomHashMap<K, V> extends _HashMap<K, V> {
205 final _Equality<K> _equals; 223 final _Equality<K> _equals;
206 final _Hasher<K> _hashCode; 224 final _Hasher<K> _hashCode;
207 _CustomHashMap(this._equals, this._hashCode); 225 final _Predicate _validKey;
226 _CustomHashMap(this._equals, this._hashCode, validKey)
227 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test;
228
229 Type get runtimeType => HashMap;
208 230
209 bool containsKey(Object key) { 231 bool containsKey(Object key) {
232 if (!_validKey(key)) return false;
210 int hashCode = _hashCode(key); 233 int hashCode = _hashCode(key);
211 List buckets = _buckets; 234 List buckets = _buckets;
212 int index = hashCode & (buckets.length - 1); 235 int index = hashCode & (buckets.length - 1);
213 _HashMapEntry entry = buckets[index]; 236 _HashMapEntry entry = buckets[index];
214 while (entry != null) { 237 while (entry != null) {
215 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; 238 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true;
216 entry = entry.next; 239 entry = entry.next;
217 } 240 }
218 return false; 241 return false;
219 } 242 }
220 243
221 V operator[](Object key) { 244 V operator[](Object key) {
245 if (!_validKey(key)) return null;
222 int hashCode = _hashCode(key); 246 int hashCode = _hashCode(key);
223 List buckets = _buckets; 247 List buckets = _buckets;
224 int index = hashCode & (buckets.length - 1); 248 int index = hashCode & (buckets.length - 1);
225 _HashMapEntry entry = buckets[index]; 249 _HashMapEntry entry = buckets[index];
226 while (entry != null) { 250 while (entry != null) {
227 if (hashCode == entry.hashCode && _equals(entry.key, key)) { 251 if (hashCode == entry.hashCode && _equals(entry.key, key)) {
228 return entry.value; 252 return entry.value;
229 } 253 }
230 entry = entry.next; 254 entry = entry.next;
231 } 255 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 V value = ifAbsent(); 288 V value = ifAbsent();
265 if (stamp == _modificationCount) { 289 if (stamp == _modificationCount) {
266 _addEntry(buckets, index, length, key, value, hashCode); 290 _addEntry(buckets, index, length, key, value, hashCode);
267 } else { 291 } else {
268 this[key] = value; 292 this[key] = value;
269 } 293 }
270 return value; 294 return value;
271 } 295 }
272 296
273 V remove(Object key) { 297 V remove(Object key) {
298 if (!_validKey(key)) return null;
274 int hashCode = _hashCode(key); 299 int hashCode = _hashCode(key);
275 List buckets = _buckets; 300 List buckets = _buckets;
276 int index = hashCode & (buckets.length - 1); 301 int index = hashCode & (buckets.length - 1);
277 _HashMapEntry entry = buckets[index]; 302 _HashMapEntry entry = buckets[index];
278 _HashMapEntry previous = null; 303 _HashMapEntry previous = null;
279 while (entry != null) { 304 while (entry != null) {
280 _HashMapEntry next = entry.next; 305 _HashMapEntry next = entry.next;
281 if (hashCode == entry.hashCode && _equals(entry.key, key)) { 306 if (hashCode == entry.hashCode && _equals(entry.key, key)) {
282 if (previous == null) { 307 _removeEntry(entry, previous, index);
283 buckets[index] = next;
284 } else {
285 previous.next = next;
286 }
287 _elementCount--; 308 _elementCount--;
288 _modificationCount = 309 _modificationCount =
289 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 310 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
290 return entry.value; 311 return entry.value;
291 } 312 }
292 previous = entry; 313 previous = entry;
293 entry = next; 314 entry = next;
294 } 315 }
295 return null; 316 return null;
296 } 317 }
297 318
298 String toString() => Maps.mapToString(this); 319 String toString() => Maps.mapToString(this);
299 } 320 }
300 321
301 class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> { 322 class _IdentityHashMap<K, V> extends _HashMap<K, V> {
323 Type get runtimeType => HashMap;
324
302 bool containsKey(Object key) { 325 bool containsKey(Object key) {
303 int hashCode = key.hashCode; 326 int hashCode = key.hashCode;
304 List buckets = _buckets; 327 List buckets = _buckets;
305 int index = hashCode & (buckets.length - 1); 328 int index = hashCode & (buckets.length - 1);
306 _HashMapEntry entry = buckets[index]; 329 _HashMapEntry entry = buckets[index];
307 while (entry != null) { 330 while (entry != null) {
308 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; 331 if (hashCode == entry.hashCode && identical(entry.key, key)) return true;
309 entry = entry.next; 332 entry = entry.next;
310 } 333 }
311 return false; 334 return false;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 388
366 V remove(Object key) { 389 V remove(Object key) {
367 int hashCode = key.hashCode; 390 int hashCode = key.hashCode;
368 List buckets = _buckets; 391 List buckets = _buckets;
369 int index = hashCode & (buckets.length - 1); 392 int index = hashCode & (buckets.length - 1);
370 _HashMapEntry entry = buckets[index]; 393 _HashMapEntry entry = buckets[index];
371 _HashMapEntry previous = null; 394 _HashMapEntry previous = null;
372 while (entry != null) { 395 while (entry != null) {
373 _HashMapEntry next = entry.next; 396 _HashMapEntry next = entry.next;
374 if (hashCode == entry.hashCode && identical(entry.key, key)) { 397 if (hashCode == entry.hashCode && identical(entry.key, key)) {
375 if (previous == null) { 398 _removeEntry(entry, previous, index);
376 buckets[index] = next;
377 } else {
378 previous.next = next;
379 }
380 _elementCount--; 399 _elementCount--;
381 _modificationCount = 400 _modificationCount =
382 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 401 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
383 return entry.value; 402 return entry.value;
384 } 403 }
385 previous = entry; 404 previous = entry;
386 entry = next; 405 entry = next;
387 } 406 }
388 return null; 407 return null;
389 } 408 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 LinkedHashMap<dynamic, V> _map; 608 LinkedHashMap<dynamic, V> _map;
590 _LinkedHashMapValueIterable(this._map); 609 _LinkedHashMapValueIterable(this._map);
591 Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map); 610 Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map);
592 bool contains(V value) => _map.containsValue(value); 611 bool contains(V value) => _map.containsValue(value);
593 bool get isEmpty => _map.isEmpty; 612 bool get isEmpty => _map.isEmpty;
594 bool get isNotEmpty => _map.isNotEmpty; 613 bool get isNotEmpty => _map.isNotEmpty;
595 int get length => _map.length; 614 int get length => _map.length;
596 } 615 }
597 616
598 abstract class _LinkedHashMapIterator<T> implements Iterator<T> { 617 abstract class _LinkedHashMapIterator<T> implements Iterator<T> {
599 final _LinkedHashMap _map; 618 final LinkedHashMap _map;
600 var _next; 619 var _next;
601 T _current; 620 T _current;
602 int _modificationCount; 621 int _modificationCount;
603 _LinkedHashMapIterator(_LinkedHashMap map) 622 _LinkedHashMapIterator(LinkedHashMap map)
604 : _map = map, 623 : _map = map,
605 _current = null, 624 _current = null,
606 _next = map._nextEntry, 625 _next = map._nextEntry,
607 _modificationCount = map._modificationCount; 626 _modificationCount = map._modificationCount;
608 627
609 bool moveNext() { 628 bool moveNext() {
610 if (_modificationCount != _map._modificationCount) { 629 if (_modificationCount != _map._modificationCount) {
611 throw new ConcurrentModificationError(_map); 630 throw new ConcurrentModificationError(_map);
612 } 631 }
613 if (identical(_map, _next)) { 632 if (identical(_map, _next)) {
614 _current = null; 633 _current = null;
615 return false; 634 return false;
616 } 635 }
617 _LinkedHashMapEntry entry = _next; 636 _LinkedHashMapEntry entry = _next;
618 _next = entry._nextEntry; 637 _next = entry._nextEntry;
619 _current = _getValue(entry); 638 _current = _getValue(entry);
620 return true; 639 return true;
621 } 640 }
622 641
623 T _getValue(_LinkedHashMapEntry entry); 642 T _getValue(_LinkedHashMapEntry entry);
624 643
625 T get current => _current; 644 T get current => _current;
626 } 645 }
627 646
628 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { 647 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> {
629 _LinkedHashMapKeyIterator(_LinkedHashMap map) : super(map); 648 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map);
630 K _getValue(_LinkedHashMapEntry entry) => entry.key; 649 K _getValue(_LinkedHashMapEntry entry) => entry.key;
631 } 650 }
632 651
633 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { 652 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> {
634 _LinkedHashMapValueIterator(_LinkedHashMap map) : super(map); 653 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map);
635 V _getValue(_LinkedHashMapEntry entry) => entry.value; 654 V _getValue(_LinkedHashMapEntry entry) => entry.value;
636 } 655 }
637 656
638 657
639 /** 658 /**
640 * A hash-based map that iterates keys and values in key insertion order. 659 * A hash-based map that iterates keys and values in key insertion order.
641 */ 660 */
642 patch class LinkedHashMap<K, V> { 661 patch class LinkedHashMap<K, V> {
643 static const int _INITIAL_CAPACITY = 8;
644 static const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
645
646 int _elementCount = 0;
647 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
648 int _modificationCount = 0;
649
650 var _nextEntry; 662 var _nextEntry;
651 var _previousEntry; 663 var _previousEntry;
652 664
653 /* patch */ LinkedHashMap() { 665 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
654 _nextEntry = _previousEntry = this; 666 int hashCode(K key),
667 bool isValidKey(potentialKey) }) {
668 if (isValidKey == null) {
669 if (hashCode == null) {
670 if (equals == null) {
671 return new _LinkedHashMap<K, V>();
672 }
673 if (identical(identical, equals)) {
674 return new _LinkedIdentityHashMap<K, V>();
675 }
676 hashCode = _defaultHashCode;
677 } else if (equals == null) {
678 equals = _defaultEquals;
679 }
680 } else {
681 if (hashCode == null) {
682 hashCode = _defaultHashCode;
683 }
684 if (equals == null) {
685 equals = _defaultEquals;
686 }
687 }
688 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
655 } 689 }
690 }
656 691
657 /* patch */ int get length => _elementCount; 692 // Methods that are exactly the same in all three linked hash map variants.
658 /* patch */ bool get isEmpty => _elementCount == 0; 693 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> {
659 /* patch */ bool get isNotEmpty => _elementCount != 0; 694 var _nextEntry;
695 var _previousEntry;
660 696
661 /* patch */ Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this); 697 Type get runtimeType => LinkedHashMap;
662 /* patch */ Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this) ;
663 698
664 /* patch */ bool containsKey(Object key) { 699 bool containsValue(Object value) {
665 int hashCode = key.hashCode; 700 int modificationCount = _modificationCount;
666 List buckets = _buckets;
667 int index = hashCode & (buckets.length - 1);
668 _HashMapEntry entry = buckets[index];
669 while (entry != null) {
670 if (hashCode == entry.hashCode && entry.key == key) return true;
671 entry = entry.next;
672 }
673 return false;
674 }
675
676 /* patch */ bool containsValue(Object value) {
677 var cursor = _nextEntry; 701 var cursor = _nextEntry;
678 int modificationCount = _modificationCount;
679 while (!identical(cursor, this)) { 702 while (!identical(cursor, this)) {
680 _HashMapEntry entry = cursor; 703 _HashMapEntry entry = cursor;
681 if (entry.value == value) return true; 704 if (entry.value == value) return true;
705 if (modificationCount != _modificationCount) {
706 throw new ConcurrentModificationError(this);
707 }
682 cursor = cursor._nextEntry; 708 cursor = cursor._nextEntry;
683 } 709 }
684 return false; 710 return false;
685 } 711 }
686 712
687 /* patch */ V operator[](Object key) { 713 void forEach(void action(K key, V value)) {
688 int hashCode = key.hashCode; 714 int modificationCount = _modificationCount;
689 List buckets = _buckets;
690 int index = hashCode & (buckets.length - 1);
691 _HashMapEntry entry = buckets[index];
692 while (entry != null) {
693 if (hashCode == entry.hashCode && entry.key == key) {
694 return entry.value;
695 }
696 entry = entry.next;
697 }
698 return null;
699 }
700
701 /* patch */ void operator []=(K key, V value) {
702 int hashCode = key.hashCode;
703 List buckets = _buckets;
704 int length = buckets.length;
705 int index = hashCode & (length - 1);
706 _HashMapEntry entry = buckets[index];
707 while (entry != null) {
708 if (hashCode == entry.hashCode && entry.key == key) {
709 entry.value = value;
710 return;
711 }
712 entry = entry.next;
713 }
714 _addEntry(buckets, index, length, key, value, hashCode);
715 }
716
717 /* patch */ V putIfAbsent(K key, V ifAbsent()) {
718 int hashCode = key.hashCode;
719 List buckets = _buckets;
720 int length = buckets.length;
721 int index = hashCode & (length - 1);
722 _HashMapEntry entry = buckets[index];
723 while (entry != null) {
724 if (hashCode == entry.hashCode && entry.key == key) {
725 return entry.value;
726 }
727 entry = entry.next;
728 }
729 int stamp = _modificationCount;
730 V value = ifAbsent();
731 if (stamp == _modificationCount) {
732 _addEntry(buckets, index, length, key, value, hashCode);
733 } else {
734 this[key] = value;
735 }
736 return value;
737 }
738
739 /* patch */ void addAll(Map<K, V> other) {
740 other.forEach((K key, V value) {
741 this[key] = value;
742 });
743 }
744
745 /* patch */ void forEach(void action(K key, V value)) {
746 int stamp = _modificationCount;
747 var cursor = _nextEntry; 715 var cursor = _nextEntry;
748 while (!identical(cursor, this)) { 716 while (!identical(cursor, this)) {
749 _HashMapEntry entry = cursor; 717 _HashMapEntry entry = cursor;
750 action(entry.key, entry.value); 718 action(entry.key, entry.value);
751 if (stamp != _modificationCount) { 719 if (modificationCount != _modificationCount) {
752 throw new ConcurrentModificationError(this); 720 throw new ConcurrentModificationError(this);
753 } 721 }
754 cursor = cursor._nextEntry; 722 cursor = cursor._nextEntry;
755 } 723 }
756 } 724 }
757 725
758 /* patch */ V remove(Object key) { 726 void clear() {
759 int hashCode = key.hashCode; 727 _nextEntry = _previousEntry = this;
760 List buckets = _buckets;
761 int index = hashCode & (buckets.length - 1);
762 _LinkedHashMapEntry entry = buckets[index];
763 _HashMapEntry previous = null;
764 while (entry != null) {
765 _HashMapEntry next = entry.next;
766 if (hashCode == entry.hashCode && entry.key == key) {
767 if (previous == null) {
768 buckets[index] = next;
769 } else {
770 previous.next = next;
771 }
772 entry._previousEntry._nextEntry = entry._nextEntry;
773 entry._nextEntry._previousEntry = entry._previousEntry;
774 entry._nextEntry = entry._previousEntry = null;
775 _elementCount--;
776 _modificationCount =
777 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
778 return entry.value;
779 }
780 previous = entry;
781 entry = next;
782 }
783 return null;
784 }
785
786 /* patch */ void clear() {
787 _elementCount = 0; 728 _elementCount = 0;
788 _nextEntry = _previousEntry = this; 729 _buckets = new List(_HashMap._INITIAL_CAPACITY);
789 _buckets = new List(_INITIAL_CAPACITY);
790 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 730 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
791 } 731 }
792 732
793 void _addEntry(List buckets, int index, int length, 733 void _addEntry(List buckets, int index, int length,
794 K key, V value, int hashCode) { 734 K key, V value, int hashCode) {
795 _HashMapEntry entry = 735 _HashMapEntry entry =
796 new _LinkedHashMapEntry(key, value, hashCode, buckets[index], 736 new _LinkedHashMapEntry(key, value, hashCode, buckets[index],
797 _previousEntry, this); 737 _previousEntry, this);
798 buckets[index] = entry; 738 buckets[index] = entry;
799 int newElements = _elementCount + 1; 739 int newElements = _elementCount + 1;
800 _elementCount = newElements; 740 _elementCount = newElements;
801 // If we end up with more than 75% non-empty entries, we 741 // If we end up with more than 75% non-empty entries, we
802 // resize the backing store. 742 // resize the backing store.
803 if ((newElements << 2) > ((length << 1) + length)) _resize(); 743 if ((newElements << 2) > ((length << 1) + length)) _resize();
804 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 744 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
805 } 745 }
806 746
807 void _resize() { 747 void _removeEntry(_LinkedHashMapEntry entry,
808 List oldBuckets = _buckets; 748 _HashMapEntry previousInBucket,
809 int oldLength = oldBuckets.length; 749 int bucketIndex) {
810 int newLength = oldLength << 1; 750 var previousInChain = entry._previousEntry;
811 List newBuckets = new List(newLength); 751 var nextInChain = entry._nextEntry;
812 for (int i = 0; i < oldLength; i++) { 752 previousInChain._nextEntry = nextInChain;
813 _HashMapEntry entry = oldBuckets[i]; 753 nextInChain._previousEntry = previousInChain;
814 while (entry != null) { 754 if (previousInBucket == null) {
815 _HashMapEntry next = entry.next; 755 _buckets[bucketIndex] = entry.next;
816 int hashCode = entry.hashCode; 756 } else {
817 int index = hashCode & (newLength - 1); 757 previousInBucket.next = entry.next;
818 entry.next = newBuckets[index];
819 newBuckets[index] = entry;
820 entry = next;
821 }
822 } 758 }
823 _buckets = newBuckets; 759 }
760
761
762 Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this);
763 Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this);
764 }
765
766 class _LinkedHashMap<K, V> extends _HashMap<K, V>
767 with _LinkedHashMapMixin<K, V> {
768 _LinkedHashMap() {
769 _nextEntry = _previousEntry = this;
824 } 770 }
825 } 771 }
826 772
773 class _LinkedIdentityHashMap<K, V> extends _IdentityHashMap<K, V>
774 with _LinkedHashMapMixin<K, V> {
775 _LinkedIdentityHashMap() {
776 _nextEntry = _previousEntry = this;
777 }
778 }
779
780 class _LinkedCustomHashMap<K, V> extends _CustomHashMap<K, V>
781 with _LinkedHashMapMixin<K, V> {
782 _LinkedCustomHashMap(bool equals(K key1, K key2),
783 int hashCode(K key),
784 bool isValidKey(potentialKey))
785 : super(equals, hashCode, isValidKey) {
786 _nextEntry = _previousEntry = this;
787 }
788 }
789
790
827 patch class LinkedHashSet<E> extends _HashSetBase<E> { 791 patch class LinkedHashSet<E> extends _HashSetBase<E> {
828 static const int _INITIAL_CAPACITY = 8; 792 static const int _INITIAL_CAPACITY = 8;
829 _LinkedHashTable<E> _table; 793 _LinkedHashTable<E> _table;
830 794
831 /* patch */ LinkedHashSet() { 795 /* patch */ LinkedHashSet() {
832 _table = new _LinkedHashTable(_INITIAL_CAPACITY); 796 _table = new _LinkedHashTable(_INITIAL_CAPACITY);
833 _table._container = this; 797 _table._container = this;
834 } 798 }
835 799
836 // Iterable. 800 // Iterable.
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1481
1518 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); 1482 _LinkedHashMapTable() : super(_INITIAL_CAPACITY);
1519 1483
1520 V _value(int offset) => _table[offset + _VALUE_INDEX]; 1484 V _value(int offset) => _table[offset + _VALUE_INDEX];
1521 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } 1485 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; }
1522 1486
1523 _copyEntry(List oldTable, int fromOffset, int toOffset) { 1487 _copyEntry(List oldTable, int fromOffset, int toOffset) {
1524 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; 1488 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX];
1525 } 1489 }
1526 } 1490 }
OLDNEW
« no previous file with comments | « pkg/serialization/test/polyfill_identity_map_test.dart ('k') | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698