OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /** | |
6 * Delegating wrappers for [Iterable], [List], [Set], [Queue] and [Map]. | |
7 * | |
8 * Also adds unmodifiable views for `Set` and `Map`, and a fixed length | |
9 * view for `List`. The unmodifable list view from `dart:collection` is exported | |
10 * as well, just for completeness. | |
11 */ | |
12 library dart.pkg.collection.wrappers; | |
13 | |
14 import "dart:collection"; | |
15 import "dart:math" show Random; | |
16 | |
17 import "src/unmodifiable_wrappers.dart"; | |
18 | |
19 export "src/canonicalized_map.dart"; | |
20 export "src/unmodifiable_wrappers.dart"; | |
21 | |
22 /** | |
23 * A base class for delegating iterables. | |
24 * | |
25 * Subclasses can provide a [_base] that should be delegated to. Unlike | |
26 * [DelegatingIterable], this allows the base to be created on demand. | |
27 */ | |
28 abstract class _DelegatingIterableBase<E> implements Iterable<E> { | |
29 Iterable<E> get _base; | |
30 | |
31 const _DelegatingIterableBase(); | |
32 | |
33 bool any(bool test(E element)) => _base.any(test); | |
34 | |
35 bool contains(Object element) => _base.contains(element); | |
36 | |
37 E elementAt(int index) => _base.elementAt(index); | |
38 | |
39 bool every(bool test(E element)) => _base.every(test); | |
40 | |
41 Iterable expand(Iterable f(E element)) => _base.expand(f); | |
42 | |
43 E get first => _base.first; | |
44 | |
45 E firstWhere(bool test(E element), {E orElse()}) => | |
46 _base.firstWhere(test, orElse: orElse); | |
47 | |
48 fold(initialValue, combine(previousValue, E element)) => | |
49 _base.fold(initialValue, combine); | |
50 | |
51 void forEach(void f(E element)) => _base.forEach(f); | |
52 | |
53 bool get isEmpty => _base.isEmpty; | |
54 | |
55 bool get isNotEmpty => _base.isNotEmpty; | |
56 | |
57 Iterator<E> get iterator => _base.iterator; | |
58 | |
59 String join([String separator = ""]) => _base.join(separator); | |
60 | |
61 E get last => _base.last; | |
62 | |
63 E lastWhere(bool test(E element), {E orElse()}) => | |
64 _base.lastWhere(test, orElse: orElse); | |
65 | |
66 int get length => _base.length; | |
67 | |
68 Iterable map(f(E element)) => _base.map(f); | |
69 | |
70 E reduce(E combine(E value, E element)) => _base.reduce(combine); | |
71 | |
72 E get single => _base.single; | |
73 | |
74 E singleWhere(bool test(E element)) => _base.singleWhere(test); | |
75 | |
76 Iterable<E> skip(int n) => _base.skip(n); | |
77 | |
78 Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test); | |
79 | |
80 Iterable<E> take(int n) => _base.take(n); | |
81 | |
82 Iterable<E> takeWhile(bool test(E value)) => _base.takeWhile(test); | |
83 | |
84 List<E> toList({bool growable: true}) => _base.toList(growable: growable); | |
85 | |
86 Set<E> toSet() => _base.toSet(); | |
87 | |
88 Iterable<E> where(bool test(E element)) => _base.where(test); | |
89 | |
90 String toString() => _base.toString(); | |
91 } | |
92 | |
93 /** | |
94 * Creates an [Iterable] that delegates all operations to a base iterable. | |
95 * | |
96 * This class can be used hide non-`Iterable` methods of an iterable object, | |
97 * or it can be extended to add extra functionality on top of an existing | |
98 * iterable object. | |
99 */ | |
100 class DelegatingIterable<E> extends _DelegatingIterableBase<E> { | |
101 final Iterable<E> _base; | |
102 | |
103 /** | |
104 * Create a wrapper that forwards operations to [base]. | |
105 */ | |
106 const DelegatingIterable(Iterable<E> base) : _base = base; | |
107 } | |
108 | |
109 | |
110 /** | |
111 * Creates a [List] that delegates all operations to a base list. | |
112 * | |
113 * This class can be used hide non-`List` methods of a list object, | |
114 * or it can be extended to add extra functionality on top of an existing | |
115 * list object. | |
116 */ | |
117 class DelegatingList<E> extends DelegatingIterable<E> implements List<E> { | |
118 const DelegatingList(List<E> base) : super(base); | |
119 | |
120 List<E> get _listBase => _base; | |
121 | |
122 E operator [](int index) => _listBase[index]; | |
123 | |
124 void operator []=(int index, E value) { | |
125 _listBase[index] = value; | |
126 } | |
127 | |
128 void add(E value) { | |
129 _listBase.add(value); | |
130 } | |
131 | |
132 void addAll(Iterable<E> iterable) { | |
133 _listBase.addAll(iterable); | |
134 } | |
135 | |
136 Map<int, E> asMap() => _listBase.asMap(); | |
137 | |
138 void clear() { | |
139 _listBase.clear(); | |
140 } | |
141 | |
142 void fillRange(int start, int end, [E fillValue]) { | |
143 _listBase.fillRange(start, end, fillValue); | |
144 } | |
145 | |
146 Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end); | |
147 | |
148 int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start); | |
149 | |
150 void insert(int index, E element) { | |
151 _listBase.insert(index, element); | |
152 } | |
153 | |
154 void insertAll(int index, Iterable<E> iterable) { | |
155 _listBase.insertAll(index, iterable); | |
156 } | |
157 | |
158 int lastIndexOf(E element, [int start]) => | |
159 _listBase.lastIndexOf(element, start); | |
160 | |
161 void set length(int newLength) { | |
162 _listBase.length = newLength; | |
163 } | |
164 | |
165 bool remove(Object value) => _listBase.remove(value); | |
166 | |
167 E removeAt(int index) => _listBase.removeAt(index); | |
168 | |
169 E removeLast() => _listBase.removeLast(); | |
170 | |
171 void removeRange(int start, int end) { | |
172 _listBase.removeRange(start, end); | |
173 } | |
174 | |
175 void removeWhere(bool test(E element)) { | |
176 _listBase.removeWhere(test); | |
177 } | |
178 | |
179 void replaceRange(int start, int end, Iterable<E> iterable) { | |
180 _listBase.replaceRange(start, end, iterable); | |
181 } | |
182 | |
183 void retainWhere(bool test(E element)) { | |
184 _listBase.retainWhere(test); | |
185 } | |
186 | |
187 Iterable<E> get reversed => _listBase.reversed; | |
188 | |
189 void setAll(int index, Iterable<E> iterable) { | |
190 _listBase.setAll(index, iterable); | |
191 } | |
192 | |
193 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | |
194 _listBase.setRange(start, end, iterable, skipCount); | |
195 } | |
196 | |
197 void shuffle([Random random]) { | |
198 _listBase.shuffle(random); | |
199 } | |
200 | |
201 void sort([int compare(E a, E b)]) { | |
202 _listBase.sort(compare); | |
203 } | |
204 | |
205 List<E> sublist(int start, [int end]) => _listBase.sublist(start, end); | |
206 } | |
207 | |
208 | |
209 /** | |
210 * Creates a [Set] that delegates all operations to a base set. | |
211 * | |
212 * This class can be used hide non-`Set` methods of a set object, | |
213 * or it can be extended to add extra functionality on top of an existing | |
214 * set object. | |
215 */ | |
216 class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> { | |
217 const DelegatingSet(Set<E> base) : super(base); | |
218 | |
219 Set<E> get _setBase => _base; | |
220 | |
221 bool add(E value) => _setBase.add(value); | |
222 | |
223 void addAll(Iterable<E> elements) { | |
224 _setBase.addAll(elements); | |
225 } | |
226 | |
227 void clear() { | |
228 _setBase.clear(); | |
229 } | |
230 | |
231 bool containsAll(Iterable<Object> other) => _setBase.containsAll(other); | |
232 | |
233 Set<E> difference(Set<E> other) => _setBase.difference(other); | |
234 | |
235 Set<E> intersection(Set<Object> other) => _setBase.intersection(other); | |
236 | |
237 E lookup(Object element) => _setBase.lookup(element); | |
238 | |
239 bool remove(Object value) => _setBase.remove(value); | |
240 | |
241 void removeAll(Iterable<Object> elements) { | |
242 _setBase.removeAll(elements); | |
243 } | |
244 | |
245 void removeWhere(bool test(E element)) { | |
246 _setBase.removeWhere(test); | |
247 } | |
248 | |
249 void retainAll(Iterable<Object> elements) { | |
250 _setBase.retainAll(elements); | |
251 } | |
252 | |
253 void retainWhere(bool test(E element)) { | |
254 _setBase.retainWhere(test); | |
255 } | |
256 | |
257 Set<E> union(Set<E> other) => _setBase.union(other); | |
258 | |
259 Set<E> toSet() => new DelegatingSet<E>(_setBase.toSet()); | |
260 } | |
261 | |
262 /** | |
263 * Creates a [Queue] that delegates all operations to a base queue. | |
264 * | |
265 * This class can be used hide non-`Queue` methods of a queue object, | |
266 * or it can be extended to add extra functionality on top of an existing | |
267 * queue object. | |
268 */ | |
269 class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> { | |
270 const DelegatingQueue(Queue<E> queue) : super(queue); | |
271 | |
272 Queue<E> get _baseQueue => _base; | |
273 | |
274 void add(E value) { | |
275 _baseQueue.add(value); | |
276 } | |
277 | |
278 void addAll(Iterable<E> iterable) { | |
279 _baseQueue.addAll(iterable); | |
280 } | |
281 | |
282 void addFirst(E value) { | |
283 _baseQueue.addFirst(value); | |
284 } | |
285 | |
286 void addLast(E value) { | |
287 _baseQueue.addLast(value); | |
288 } | |
289 | |
290 void clear() { | |
291 _baseQueue.clear(); | |
292 } | |
293 | |
294 bool remove(Object object) => _baseQueue.remove(object); | |
295 | |
296 void removeWhere(bool test(E element)) { _baseQueue.removeWhere(test); } | |
297 | |
298 void retainWhere(bool test(E element)) { _baseQueue.retainWhere(test); } | |
299 | |
300 E removeFirst() => _baseQueue.removeFirst(); | |
301 | |
302 E removeLast() => _baseQueue.removeLast(); | |
303 } | |
304 | |
305 /** | |
306 * Creates a [Map] that delegates all operations to a base map. | |
307 * | |
308 * This class can be used hide non-`Map` methods of an object that extends | |
309 * `Map`, or it can be extended to add extra functionality on top of an existing | |
310 * map object. | |
311 */ | |
312 class DelegatingMap<K, V> implements Map<K, V> { | |
313 final Map<K, V> _base; | |
314 | |
315 const DelegatingMap(Map<K, V> base) : _base = base; | |
316 | |
317 V operator [](Object key) => _base[key]; | |
318 | |
319 void operator []=(K key, V value) { | |
320 _base[key] = value; | |
321 } | |
322 | |
323 void addAll(Map<K, V> other) { | |
324 _base.addAll(other); | |
325 } | |
326 | |
327 void clear() { | |
328 _base.clear(); | |
329 } | |
330 | |
331 bool containsKey(Object key) => _base.containsKey(key); | |
332 | |
333 bool containsValue(Object value) => _base.containsValue(value); | |
334 | |
335 void forEach(void f(K key, V value)) { | |
336 _base.forEach(f); | |
337 } | |
338 | |
339 bool get isEmpty => _base.isEmpty; | |
340 | |
341 bool get isNotEmpty => _base.isNotEmpty; | |
342 | |
343 Iterable<K> get keys => _base.keys; | |
344 | |
345 int get length => _base.length; | |
346 | |
347 V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent); | |
348 | |
349 V remove(Object key) => _base.remove(key); | |
350 | |
351 Iterable<V> get values => _base.values; | |
352 | |
353 String toString() => _base.toString(); | |
354 } | |
355 | |
356 /** | |
357 * An unmodifiable [Set] view of the keys of a [Map]. | |
358 * | |
359 * The set delegates all operations to the underlying map. | |
360 * | |
361 * A `Map` can only contain each key once, so its keys can always | |
362 * be viewed as a `Set` without any loss, even if the [Map.keys] | |
363 * getter only shows an [Iterable] view of the keys. | |
364 * | |
365 * Note that [lookup] is not supported for this set. | |
366 */ | |
367 class MapKeySet<E> extends _DelegatingIterableBase<E> | |
368 with UnmodifiableSetMixin<E> { | |
369 final Map<E, dynamic> _baseMap; | |
370 | |
371 MapKeySet(Map<E, dynamic> base) : _baseMap = base; | |
372 | |
373 Iterable<E> get _base => _baseMap.keys; | |
374 | |
375 bool contains(Object element) => _baseMap.containsKey(element); | |
376 | |
377 bool get isEmpty => _baseMap.isEmpty; | |
378 | |
379 bool get isNotEmpty => _baseMap.isNotEmpty; | |
380 | |
381 int get length => _baseMap.length; | |
382 | |
383 String toString() => "{${_base.join(', ')}}"; | |
384 | |
385 bool containsAll(Iterable<Object> other) => other.every(contains); | |
386 | |
387 /** | |
388 * Returns a new set with the the elements of [this] that are not in [other]. | |
389 * | |
390 * That is, the returned set contains all the elements of this [Set] that are | |
391 * not elements of [other] according to `other.contains`. | |
392 * | |
393 * Note that the returned set will use the default equality operation, which | |
394 * may be different than the equality operation [this] uses. | |
395 */ | |
396 Set<E> difference(Set<E> other) => | |
397 where((element) => !other.contains(element)).toSet(); | |
398 | |
399 /** | |
400 * Returns a new set which is the intersection between [this] and [other]. | |
401 * | |
402 * That is, the returned set contains all the elements of this [Set] that are | |
403 * also elements of [other] according to `other.contains`. | |
404 * | |
405 * Note that the returned set will use the default equality operation, which | |
406 * may be different than the equality operation [this] uses. | |
407 */ | |
408 Set<E> intersection(Set<Object> other) => where(other.contains).toSet(); | |
409 | |
410 /** | |
411 * Throws an [UnsupportedError] since there's no corresponding method for | |
412 * [Map]s. | |
413 */ | |
414 E lookup(E element) => throw new UnsupportedError( | |
415 "MapKeySet doesn't support lookup()."); | |
416 | |
417 /** | |
418 * Returns a new set which contains all the elements of [this] and [other]. | |
419 * | |
420 * That is, the returned set contains all the elements of this [Set] and all | |
421 * the elements of [other]. | |
422 * | |
423 * Note that the returned set will use the default equality operation, which | |
424 * may be different than the equality operation [this] uses. | |
425 */ | |
426 Set<E> union(Set<E> other) => toSet()..addAll(other); | |
427 } | |
428 | |
429 /** | |
430 * Creates a modifiable [Set] view of the values of a [Map]. | |
431 * | |
432 * The `Set` view assumes that the keys of the `Map` can be uniquely determined | |
433 * from the values. The `keyForValue` function passed to the constructor finds | |
434 * the key for a single value. The `keyForValue` function should be consistent | |
435 * with equality. If `value1 == value2` then `keyForValue(value1)` and | |
436 * `keyForValue(value2)` should be considered equal keys by the underlying map, | |
437 * and vice versa. | |
438 * | |
439 * Modifying the set will modify the underlying map based on the key returned by | |
440 * `keyForValue`. | |
441 * | |
442 * If the `Map` contents are not compatible with the `keyForValue` function, the | |
443 * set will not work consistently, and may give meaningless responses or do | |
444 * inconsistent updates. | |
445 * | |
446 * This set can, for example, be used on a map from database record IDs to the | |
447 * records. It exposes the records as a set, and allows for writing both | |
448 * `recordSet.add(databaseRecord)` and `recordMap[id]`. | |
449 * | |
450 * Effectively, the map will act as a kind of index for the set. | |
451 */ | |
452 class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { | |
453 final Map<K, V> _baseMap; | |
454 final Function _keyForValue; | |
455 | |
456 /** | |
457 * Creates a new [MapValueSet] based on [base]. | |
458 * | |
459 * [keyForValue] returns the key in the map that should be associated with the | |
460 * given value. The set's notion of equality is identical to the equality of | |
461 * the return values of [keyForValue]. | |
462 */ | |
463 MapValueSet(Map<K, V> base, K keyForValue(V value)) | |
464 : _baseMap = base, | |
465 _keyForValue = keyForValue; | |
466 | |
467 Iterable<V> get _base => _baseMap.values; | |
468 | |
469 bool contains(Object element) { | |
470 if (element != null && element is! V) return false; | |
471 return _baseMap.containsKey(_keyForValue(element)); | |
472 } | |
473 | |
474 bool get isEmpty => _baseMap.isEmpty; | |
475 | |
476 bool get isNotEmpty => _baseMap.isNotEmpty; | |
477 | |
478 int get length => _baseMap.length; | |
479 | |
480 String toString() => toSet().toString(); | |
481 | |
482 bool add(V value) { | |
483 K key = _keyForValue(value); | |
484 bool result = false; | |
485 _baseMap.putIfAbsent(key, () { | |
486 result = true; | |
487 return value; | |
488 }); | |
489 return result; | |
490 } | |
491 | |
492 void addAll(Iterable<V> elements) => elements.forEach(add); | |
493 | |
494 void clear() => _baseMap.clear(); | |
495 | |
496 bool containsAll(Iterable<Object> other) => other.every(contains); | |
497 | |
498 /** | |
499 * Returns a new set with the the elements of [this] that are not in [other]. | |
500 * | |
501 * That is, the returned set contains all the elements of this [Set] that are | |
502 * not elements of [other] according to `other.contains`. | |
503 * | |
504 * Note that the returned set will use the default equality operation, which | |
505 * may be different than the equality operation [this] uses. | |
506 */ | |
507 Set<V> difference(Set<V> other) => | |
508 where((element) => !other.contains(element)).toSet(); | |
509 | |
510 /** | |
511 * Returns a new set which is the intersection between [this] and [other]. | |
512 * | |
513 * That is, the returned set contains all the elements of this [Set] that are | |
514 * also elements of [other] according to `other.contains`. | |
515 * | |
516 * Note that the returned set will use the default equality operation, which | |
517 * may be different than the equality operation [this] uses. | |
518 */ | |
519 Set<V> intersection(Set<Object> other) => where(other.contains).toSet(); | |
520 | |
521 V lookup(Object element) => _baseMap[_keyForValue(element)]; | |
522 | |
523 bool remove(Object value) { | |
524 if (value != null && value is! V) return false; | |
525 var key = _keyForValue(value); | |
526 if (!_baseMap.containsKey(key)) return false; | |
527 _baseMap.remove(key); | |
528 return true; | |
529 } | |
530 | |
531 void removeAll(Iterable<Object> elements) => elements.forEach(remove); | |
532 | |
533 void removeWhere(bool test(V element)) { | |
534 var toRemove = []; | |
535 _baseMap.forEach((key, value) { | |
536 if (test(value)) toRemove.add(key); | |
537 }); | |
538 toRemove.forEach(_baseMap.remove); | |
539 } | |
540 | |
541 void retainAll(Iterable<Object> elements) { | |
542 var valuesToRetain = new Set<V>.identity(); | |
543 for (var element in elements) { | |
544 if (element != null && element is! V) continue; | |
545 var key = _keyForValue(element); | |
546 if (!_baseMap.containsKey(key)) continue; | |
547 valuesToRetain.add(_baseMap[key]); | |
548 } | |
549 | |
550 var keysToRemove = []; | |
551 _baseMap.forEach((k, v) { | |
552 if (!valuesToRetain.contains(v)) keysToRemove.add(k); | |
553 }); | |
554 keysToRemove.forEach(_baseMap.remove); | |
555 } | |
556 | |
557 void retainWhere(bool test(V element)) => | |
558 removeWhere((element) => !test(element)); | |
559 | |
560 /** | |
561 * Returns a new set which contains all the elements of [this] and [other]. | |
562 * | |
563 * That is, the returned set contains all the elements of this [Set] and all | |
564 * the elements of [other]. | |
565 * | |
566 * Note that the returned set will use the default equality operation, which | |
567 * may be different than the equality operation [this] uses. | |
568 */ | |
569 Set<V> union(Set<V> other) => toSet()..addAll(other); | |
570 } | |
OLD | NEW |