| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of dart.collection; | 5 part of dart.collection; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Base class for implementing a [Map]. | 8 * Base class for implementing a [Map]. |
| 9 * | 9 * |
| 10 * This class has a basic implementation of all but five of the members of | 10 * This class has a basic implementation of all but five of the members of |
| 11 * [Map]. | 11 * [Map]. |
| 12 * A basic `Map` class can be implemented by extending this class and | 12 * A basic `Map` class can be implemented by extending this class and |
| 13 * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. | 13 * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. |
| 14 * The remaining operations are implemented in terms of these five. | 14 * The remaining operations are implemented in terms of these five. |
| 15 * | 15 * |
| 16 * The `keys` iterable should have efficient [length] and [contains] | 16 * The `keys` iterable should have efficient [length] and [contains] |
| 17 * operations, and it should catch concurrent modifications of the keys | 17 * operations, and it should catch concurrent modifications of the keys |
| 18 * while iterating. | 18 * while iterating. |
| 19 * | 19 * |
| 20 * A more efficient implementation is usually possible by overriding | 20 * A more efficient implementation is usually possible by overriding |
| 21 * some of the other members as well. | 21 * some of the other members as well. |
| 22 */ | 22 */ |
| 23 abstract class MapBase<K, V> = Object with MapMixin<K, V>; | 23 abstract class MapBase<K, V> = Object with MapMixin<K, V>; |
| 24 | 24 |
| 25 | |
| 26 /** | 25 /** |
| 27 * Mixin implementing a [Map]. | 26 * Mixin implementing a [Map]. |
| 28 * | 27 * |
| 29 * This mixin has a basic implementation of all but five of the members of | 28 * This mixin has a basic implementation of all but five of the members of |
| 30 * [Map]. | 29 * [Map]. |
| 31 * A basic `Map` class can be implemented by mixin in this class and | 30 * A basic `Map` class can be implemented by mixin in this class and |
| 32 * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. | 31 * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. |
| 33 * The remaining operations are implemented in terms of these five. | 32 * The remaining operations are implemented in terms of these five. |
| 34 * | 33 * |
| 35 * The `keys` iterable should have efficient [length] and [contains] | 34 * The `keys` iterable should have efficient [length] and [contains] |
| 36 * operations, and it should catch concurrent modifications of the keys | 35 * operations, and it should catch concurrent modifications of the keys |
| 37 * while iterating. | 36 * while iterating. |
| 38 * | 37 * |
| 39 * A more efficient implementation is usually possible by overriding | 38 * A more efficient implementation is usually possible by overriding |
| 40 * some of the other members as well. | 39 * some of the other members as well. |
| 41 */ | 40 */ |
| 42 abstract class MapMixin<K, V> implements Map<K, V> { | 41 abstract class MapMixin<K, V> implements Map<K, V> { |
| 43 Iterable<K> get keys; | 42 Iterable<K> get keys; |
| 44 V operator[](Object key); | 43 V operator [](Object key); |
| 45 operator []=(K key, V value); | 44 operator []=(K key, V value); |
| 46 V remove(Object key); | 45 V remove(Object key); |
| 47 // The `clear` operation should not be based on `remove`. | 46 // The `clear` operation should not be based on `remove`. |
| 48 // It should clear the map even if some keys are not equal to themselves. | 47 // It should clear the map even if some keys are not equal to themselves. |
| 49 void clear(); | 48 void clear(); |
| 50 | 49 |
| 51 void forEach(void action(K key, V value)) { | 50 void forEach(void action(K key, V value)) { |
| 52 for (K key in keys) { | 51 for (K key in keys) { |
| 53 action(key, this[key]); | 52 action(key, this[key]); |
| 54 } | 53 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 * The remaining non-modifying operations are implemented in terms of `keys` | 93 * The remaining non-modifying operations are implemented in terms of `keys` |
| 95 * and `operator[]`. | 94 * and `operator[]`. |
| 96 * | 95 * |
| 97 * The `keys` iterable should have efficient [length] and [contains] | 96 * The `keys` iterable should have efficient [length] and [contains] |
| 98 * operations, and it should catch concurrent modifications of the keys | 97 * operations, and it should catch concurrent modifications of the keys |
| 99 * while iterating. | 98 * while iterating. |
| 100 * | 99 * |
| 101 * A more efficient implementation is usually possible by overriding | 100 * A more efficient implementation is usually possible by overriding |
| 102 * some of the other members as well. | 101 * some of the other members as well. |
| 103 */ | 102 */ |
| 104 abstract class UnmodifiableMapBase<K, V> = | 103 abstract class UnmodifiableMapBase<K, V> = MapBase<K, V> |
| 105 MapBase<K, V> with _UnmodifiableMapMixin<K, V>; | 104 with _UnmodifiableMapMixin<K, V>; |
| 106 | 105 |
| 107 /** | 106 /** |
| 108 * Implementation of [Map.values] based on the map and its [Map.keys] iterable. | 107 * Implementation of [Map.values] based on the map and its [Map.keys] iterable. |
| 109 * | 108 * |
| 110 * Iterable that iterates over the values of a `Map`. | 109 * Iterable that iterates over the values of a `Map`. |
| 111 * It accesses the values by iterating over the keys of the map, and using the | 110 * It accesses the values by iterating over the keys of the map, and using the |
| 112 * map's `operator[]` to lookup the keys. | 111 * map's `operator[]` to lookup the keys. |
| 113 */ | 112 */ |
| 114 class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> { | 113 class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> { |
| 115 final Map<K, V> _map; | 114 final Map<K, V> _map; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } | 149 } |
| 151 | 150 |
| 152 V get current => _current; | 151 V get current => _current; |
| 153 } | 152 } |
| 154 | 153 |
| 155 /** | 154 /** |
| 156 * Mixin that overrides mutating map operations with implementations that throw. | 155 * Mixin that overrides mutating map operations with implementations that throw. |
| 157 */ | 156 */ |
| 158 abstract class _UnmodifiableMapMixin<K, V> implements Map<K, V> { | 157 abstract class _UnmodifiableMapMixin<K, V> implements Map<K, V> { |
| 159 /** This operation is not supported by an unmodifiable map. */ | 158 /** This operation is not supported by an unmodifiable map. */ |
| 160 void operator[]=(K key, V value) { | 159 void operator []=(K key, V value) { |
| 161 throw new UnsupportedError("Cannot modify unmodifiable map"); | 160 throw new UnsupportedError("Cannot modify unmodifiable map"); |
| 162 } | 161 } |
| 162 |
| 163 /** This operation is not supported by an unmodifiable map. */ | 163 /** This operation is not supported by an unmodifiable map. */ |
| 164 void addAll(Map<K, V> other) { | 164 void addAll(Map<K, V> other) { |
| 165 throw new UnsupportedError("Cannot modify unmodifiable map"); | 165 throw new UnsupportedError("Cannot modify unmodifiable map"); |
| 166 } | 166 } |
| 167 |
| 167 /** This operation is not supported by an unmodifiable map. */ | 168 /** This operation is not supported by an unmodifiable map. */ |
| 168 void clear() { | 169 void clear() { |
| 169 throw new UnsupportedError("Cannot modify unmodifiable map"); | 170 throw new UnsupportedError("Cannot modify unmodifiable map"); |
| 170 } | 171 } |
| 172 |
| 171 /** This operation is not supported by an unmodifiable map. */ | 173 /** This operation is not supported by an unmodifiable map. */ |
| 172 V remove(Object key) { | 174 V remove(Object key) { |
| 173 throw new UnsupportedError("Cannot modify unmodifiable map"); | 175 throw new UnsupportedError("Cannot modify unmodifiable map"); |
| 174 } | 176 } |
| 177 |
| 175 /** This operation is not supported by an unmodifiable map. */ | 178 /** This operation is not supported by an unmodifiable map. */ |
| 176 V putIfAbsent(K key, V ifAbsent()) { | 179 V putIfAbsent(K key, V ifAbsent()) { |
| 177 throw new UnsupportedError("Cannot modify unmodifiable map"); | 180 throw new UnsupportedError("Cannot modify unmodifiable map"); |
| 178 } | 181 } |
| 179 } | 182 } |
| 180 | 183 |
| 181 /** | 184 /** |
| 182 * Wrapper around a class that implements [Map] that only exposes `Map` members. | 185 * Wrapper around a class that implements [Map] that only exposes `Map` members. |
| 183 * | 186 * |
| 184 * A simple wrapper that delegates all `Map` members to the map provided in the | 187 * A simple wrapper that delegates all `Map` members to the map provided in the |
| 185 * constructor. | 188 * constructor. |
| 186 * | 189 * |
| 187 * Base for delegating map implementations like [UnmodifiableMapView]. | 190 * Base for delegating map implementations like [UnmodifiableMapView]. |
| 188 */ | 191 */ |
| 189 class MapView<K, V> implements Map<K, V> { | 192 class MapView<K, V> implements Map<K, V> { |
| 190 final Map<K, V> _map; | 193 final Map<K, V> _map; |
| 191 const MapView(Map<K, V> map) : _map = map; | 194 const MapView(Map<K, V> map) : _map = map; |
| 192 | 195 |
| 193 V operator[](Object key) => _map[key]; | 196 V operator [](Object key) => _map[key]; |
| 194 void operator[]=(K key, V value) { _map[key] = value; } | 197 void operator []=(K key, V value) { |
| 195 void addAll(Map<K, V> other) { _map.addAll(other); } | 198 _map[key] = value; |
| 196 void clear() { _map.clear(); } | 199 } |
| 200 |
| 201 void addAll(Map<K, V> other) { |
| 202 _map.addAll(other); |
| 203 } |
| 204 |
| 205 void clear() { |
| 206 _map.clear(); |
| 207 } |
| 208 |
| 197 V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent); | 209 V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent); |
| 198 bool containsKey(Object key) => _map.containsKey(key); | 210 bool containsKey(Object key) => _map.containsKey(key); |
| 199 bool containsValue(Object value) => _map.containsValue(value); | 211 bool containsValue(Object value) => _map.containsValue(value); |
| 200 void forEach(void action(K key, V value)) { _map.forEach(action); } | 212 void forEach(void action(K key, V value)) { |
| 213 _map.forEach(action); |
| 214 } |
| 215 |
| 201 bool get isEmpty => _map.isEmpty; | 216 bool get isEmpty => _map.isEmpty; |
| 202 bool get isNotEmpty => _map.isNotEmpty; | 217 bool get isNotEmpty => _map.isNotEmpty; |
| 203 int get length => _map.length; | 218 int get length => _map.length; |
| 204 Iterable<K> get keys => _map.keys; | 219 Iterable<K> get keys => _map.keys; |
| 205 V remove(Object key) => _map.remove(key); | 220 V remove(Object key) => _map.remove(key); |
| 206 String toString() => _map.toString(); | 221 String toString() => _map.toString(); |
| 207 Iterable<V> get values => _map.values; | 222 Iterable<V> get values => _map.values; |
| 208 } | 223 } |
| 209 | 224 |
| 210 /** | 225 /** |
| 211 * View of a [Map] that disallow modifying the map. | 226 * View of a [Map] that disallow modifying the map. |
| 212 * | 227 * |
| 213 * A wrapper around a `Map` that forwards all members to the map provided in | 228 * A wrapper around a `Map` that forwards all members to the map provided in |
| 214 * the constructor, except for operations that modify the map. | 229 * the constructor, except for operations that modify the map. |
| 215 * Modifying operations throw instead. | 230 * Modifying operations throw instead. |
| 216 */ | 231 */ |
| 217 class UnmodifiableMapView<K, V> = | 232 class UnmodifiableMapView<K, V> = MapView<K, V> |
| 218 MapView<K, V> with _UnmodifiableMapMixin<K, V>; | 233 with _UnmodifiableMapMixin<K, V>; |
| 219 | 234 |
| 220 /** | 235 /** |
| 221 * Helper class which implements complex [Map] operations | 236 * Helper class which implements complex [Map] operations |
| 222 * in term of basic ones ([Map.keys], [Map.[]], | 237 * in term of basic ones ([Map.keys], [Map.[]], |
| 223 * [Map.[]=] and [Map.remove].) Not all methods are | 238 * [Map.[]=] and [Map.remove].) Not all methods are |
| 224 * necessary to implement each particular operation. | 239 * necessary to implement each particular operation. |
| 225 */ | 240 */ |
| 226 class Maps { | 241 class Maps { |
| 227 static bool containsValue(Map map, Object value) { | 242 static bool containsValue(Map map, Object value) { |
| 228 for (final v in map.values) { | 243 for (final v in map.values) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 * or maps, the contained reference is rendered as [:'{...}':]. This | 299 * or maps, the contained reference is rendered as [:'{...}':]. This |
| 285 * prevents the infinite regress that would otherwise occur. So, for example, | 300 * prevents the infinite regress that would otherwise occur. So, for example, |
| 286 * calling this method on a map whose sole entry maps the string key 'me' | 301 * calling this method on a map whose sole entry maps the string key 'me' |
| 287 * to a reference to the map would return [:'{me: {...}}':]. | 302 * to a reference to the map would return [:'{me: {...}}':]. |
| 288 * | 303 * |
| 289 * A typical implementation of a map's [toString] method will | 304 * A typical implementation of a map's [toString] method will |
| 290 * simply return the results of this method applied to the collection. | 305 * simply return the results of this method applied to the collection. |
| 291 */ | 306 */ |
| 292 static String mapToString(Map m) { | 307 static String mapToString(Map m) { |
| 293 // Reuse the list in IterableBase for detecting toString cycles. | 308 // Reuse the list in IterableBase for detecting toString cycles. |
| 294 if (_isToStringVisiting(m)) { return '{...}'; } | 309 if (_isToStringVisiting(m)) { |
| 310 return '{...}'; |
| 311 } |
| 295 | 312 |
| 296 var result = new StringBuffer(); | 313 var result = new StringBuffer(); |
| 297 try { | 314 try { |
| 298 _toStringVisiting.add(m); | 315 _toStringVisiting.add(m); |
| 299 result.write('{'); | 316 result.write('{'); |
| 300 bool first = true; | 317 bool first = true; |
| 301 m.forEach((k, v) { | 318 m.forEach((k, v) { |
| 302 if(!first) { | 319 if (!first) { |
| 303 result.write(', '); | 320 result.write(', '); |
| 304 } | 321 } |
| 305 first = false; | 322 first = false; |
| 306 result.write(k); | 323 result.write(k); |
| 307 result.write(': '); | 324 result.write(': '); |
| 308 result.write(v); | 325 result.write(v); |
| 309 }); | 326 }); |
| 310 result.write('}'); | 327 result.write('}'); |
| 311 } finally { | 328 } finally { |
| 312 assert(identical(_toStringVisiting.last, m)); | 329 assert(identical(_toStringVisiting.last, m)); |
| 313 _toStringVisiting.removeLast(); | 330 _toStringVisiting.removeLast(); |
| 314 } | 331 } |
| 315 | 332 |
| 316 return result.toString(); | 333 return result.toString(); |
| 317 } | 334 } |
| 318 | 335 |
| 319 static _id(x) => x; | 336 static _id(x) => x; |
| 320 | 337 |
| 321 /** | 338 /** |
| 322 * Fills a map with key/value pairs computed from [iterable]. | 339 * Fills a map with key/value pairs computed from [iterable]. |
| 323 * | 340 * |
| 324 * This method is used by Map classes in the named constructor fromIterable. | 341 * This method is used by Map classes in the named constructor fromIterable. |
| 325 */ | 342 */ |
| 326 static void _fillMapWithMappedIterable(Map map, Iterable iterable, | 343 static void _fillMapWithMappedIterable( |
| 327 key(element), value(element)) { | 344 Map map, Iterable iterable, key(element), value(element)) { |
| 328 if (key == null) key = _id; | 345 if (key == null) key = _id; |
| 329 if (value == null) value = _id; | 346 if (value == null) value = _id; |
| 330 | 347 |
| 331 for (var element in iterable) { | 348 for (var element in iterable) { |
| 332 map[key(element)] = value(element); | 349 map[key(element)] = value(element); |
| 333 } | 350 } |
| 334 } | 351 } |
| 335 | 352 |
| 336 /** | 353 /** |
| 337 * Fills a map by associating the [keys] to [values]. | 354 * Fills a map by associating the [keys] to [values]. |
| 338 * | 355 * |
| 339 * This method is used by Map classes in the named constructor fromIterables. | 356 * This method is used by Map classes in the named constructor fromIterables. |
| 340 */ | 357 */ |
| 341 static void _fillMapWithIterables(Map map, Iterable keys, | 358 static void _fillMapWithIterables(Map map, Iterable keys, Iterable values) { |
| 342 Iterable values) { | |
| 343 Iterator keyIterator = keys.iterator; | 359 Iterator keyIterator = keys.iterator; |
| 344 Iterator valueIterator = values.iterator; | 360 Iterator valueIterator = values.iterator; |
| 345 | 361 |
| 346 bool hasNextKey = keyIterator.moveNext(); | 362 bool hasNextKey = keyIterator.moveNext(); |
| 347 bool hasNextValue = valueIterator.moveNext(); | 363 bool hasNextValue = valueIterator.moveNext(); |
| 348 | 364 |
| 349 while (hasNextKey && hasNextValue) { | 365 while (hasNextKey && hasNextValue) { |
| 350 map[keyIterator.current] = valueIterator.current; | 366 map[keyIterator.current] = valueIterator.current; |
| 351 hasNextKey = keyIterator.moveNext(); | 367 hasNextKey = keyIterator.moveNext(); |
| 352 hasNextValue = valueIterator.moveNext(); | 368 hasNextValue = valueIterator.moveNext(); |
| 353 } | 369 } |
| 354 | 370 |
| 355 if (hasNextKey || hasNextValue) { | 371 if (hasNextKey || hasNextValue) { |
| 356 throw new ArgumentError("Iterables do not have same length."); | 372 throw new ArgumentError("Iterables do not have same length."); |
| 357 } | 373 } |
| 358 } | 374 } |
| 359 } | 375 } |
| OLD | NEW |