| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 // VM-internalized implementation of a default-constructed LinkedHashMap. | |
| 6 // Currently calls the runtime for most operations. | |
| 7 class _InternalLinkedHashMap<K, V> implements HashMap<K, V>, | |
| 8 LinkedHashMap<K, V> { | |
| 9 factory _InternalLinkedHashMap() native "LinkedHashMap_allocate"; | |
| 10 int get length native "LinkedHashMap_getLength"; | |
| 11 V operator [](K key) native "LinkedHashMap_lookUp"; | |
| 12 void operator []=(K key, V value) native "LinkedHashMap_insertOrUpdate"; | |
| 13 V remove(K key) native "LinkedHashMap_remove"; | |
| 14 void clear() native "LinkedHashMap_clear"; | |
| 15 bool containsKey(K key) native "LinkedHashMap_containsKey"; | |
| 16 | |
| 17 bool get isEmpty => length == 0; | |
| 18 bool get isNotEmpty => !isEmpty; | |
| 19 | |
| 20 List _toArray() native "LinkedHashMap_toArray"; | |
| 21 | |
| 22 // "Modificaton marks" are tokens used to detect concurrent modification. | |
| 23 // Considering only modifications (M) and iterator creation (I) events, e.g.: | |
| 24 // M, M, M, I, I, M, I, M, M, I, I, I, M ... | |
| 25 // a new mark is allocated at the start of each run of I's and cleared from | |
| 26 // the map at the start of each run of M's. Iterators' moveNext check whether | |
| 27 // the map's mark was changed or cleared since the iterator was created. | |
| 28 // TODO(koda): Consider a counter instead. | |
| 29 Object _getModMark(bool create) native "LinkedHashMap_getModMark"; | |
| 30 | |
| 31 void addAll(Map<K, V> other) { | |
| 32 other.forEach((K key, V value) { | |
| 33 this[key] = value; | |
| 34 }); | |
| 35 } | |
| 36 | |
| 37 V putIfAbsent(K key, Function ifAbsent) { | |
| 38 if (containsKey(key)) { | |
| 39 return this[key]; | |
| 40 } else { | |
| 41 V value = ifAbsent(); | |
| 42 this[key] = value; | |
| 43 return value; | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 bool containsValue(V value) { | |
| 48 for (V v in values) { | |
| 49 if (v == value) { | |
| 50 return true; | |
| 51 } | |
| 52 } | |
| 53 return false; | |
| 54 } | |
| 55 | |
| 56 void forEach(Function f) { | |
| 57 for (K key in keys) { | |
| 58 f(key, this[key]); | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 // The even-indexed entries of toArray are the keys. | |
| 63 Iterable<K> get keys => | |
| 64 new _ListStepIterable<K>(this, _getModMark(true), _toArray(), -2, 2); | |
| 65 | |
| 66 // The odd-indexed entries of toArray are the values. | |
| 67 Iterable<V> get values => | |
| 68 new _ListStepIterable<V>(this, _getModMark(true), _toArray(), -1, 2); | |
| 69 | |
| 70 String toString() => Maps.mapToString(this); | |
| 71 } | |
| 72 | |
| 73 // Iterates over a list from a given offset and step size. | |
| 74 class _ListStepIterable<E> extends IterableBase<E> { | |
| 75 _InternalLinkedHashMap _map; | |
| 76 Object _modMark; | |
| 77 List _list; | |
| 78 int _offset; | |
| 79 int _step; | |
| 80 | |
| 81 _ListStepIterable(this._map, this._modMark, | |
| 82 this._list, this._offset, this._step); | |
| 83 | |
| 84 Iterator<E> get iterator => | |
| 85 new _ListStepIterator(_map, _modMark, _list, _offset, _step); | |
| 86 | |
| 87 // TODO(koda): Should this check for concurrent modification? | |
| 88 int get length => _map.length; | |
| 89 bool get isEmpty => length == 0; | |
| 90 bool get isNotEmpty => !isEmpty; | |
| 91 } | |
| 92 | |
| 93 class _ListStepIterator<E> implements Iterator<E> { | |
| 94 _InternalLinkedHashMap _map; | |
| 95 Object _modMark; | |
| 96 List _list; | |
| 97 int _offset; | |
| 98 int _step; | |
| 99 | |
| 100 _ListStepIterator(this._map, this._modMark, | |
| 101 this._list, this._offset, this._step); | |
| 102 | |
| 103 bool moveNext() { | |
| 104 if (_map._getModMark(false) != _modMark) { | |
| 105 throw new ConcurrentModificationError(_map); | |
| 106 } | |
| 107 _offset += _step; | |
| 108 return _offset < _list.length; | |
| 109 } | |
| 110 | |
| 111 E get current { | |
| 112 if (_offset < 0 || _offset >= _list.length) { | |
| 113 return null; | |
| 114 } | |
| 115 return _list[_offset]; | |
| 116 } | |
| 117 } | |
| 118 | |
| OLD | NEW |