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 |