OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, 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 // Collection<T> supports most of the ES 5 Array methods, but it's missing | |
6 // map and reduce. | |
7 | |
8 // TODO(jmesserly): we might want a version of this that return an iterable, | |
9 // however JS, Python and Ruby versions are all eager. | |
10 List map(Iterable source, mapper(source)) { | |
11 List result = new List(); | |
12 if (source is List) { | |
13 List list = source; // TODO: shouldn't need this | |
14 result.length = list.length; | |
15 for (int i = 0; i < list.length; i++) { | |
16 result[i] = mapper(list[i]); | |
17 } | |
18 } else { | |
19 for (final item in source) { | |
20 result.add(mapper(item)); | |
21 } | |
22 } | |
23 return result; | |
24 } | |
25 | |
26 reduce(Iterable source, callback, [initialValue]) { | |
27 final i = source.iterator(); | |
28 | |
29 var current = initialValue; | |
30 if (current == null && i.hasNext()) { | |
31 current = i.next(); | |
32 } | |
33 while (i.hasNext()) { | |
34 current = callback(current, i.next()); | |
35 } | |
36 return current; | |
37 } | |
38 | |
39 List zip(Iterable left, Iterable right, mapper(left, right)) { | |
40 List result = new List(); | |
41 var x = left.iterator(); | |
42 var y = right.iterator(); | |
43 while (x.hasNext() && y.hasNext()) { | |
44 result.add(mapper(x.next(), y.next())); | |
45 } | |
46 if (x.hasNext() || y.hasNext()) { | |
47 throw new IllegalArgumentException(); | |
48 } | |
49 return result; | |
50 } | |
51 | |
52 /** Sorts the map by the key. */ | |
53 List orderValuesByKeys(Map map) { | |
54 // TODO(jmesserly): it'd be nice to have SortedMap in corelib. | |
55 List keys = map.getKeys(); | |
56 keys.sort((x, y) => x.compareTo(y)); | |
57 final values = []; | |
58 for (var k in keys) { | |
59 values.add(map[k]); | |
60 } | |
61 return values; | |
62 } | |
63 | |
64 /** | |
65 * A [FixedCollection] is a collection of [length] items all of which have the | |
66 * identical [value] | |
67 */ | |
68 class FixedCollection<E> implements Collection<E> { | |
69 final E value; | |
70 final int length; | |
71 const FixedCollection(this.value, this.length); | |
72 | |
73 Iterator<E> iterator() => new FixedIterator<E>(value, length); | |
74 void forEach(void f(E element)) { Collections.forEach(this, f); } | |
75 Collection map(f(E element)) => Collections.map(this, new List(), f); | |
76 Collection<E> filter(bool f(E element)) { | |
77 return Collections.filter(this, new List<E>(), f); | |
78 } | |
79 bool every(bool f(E element)) => Collections.every(this, f); | |
80 bool some(bool f(E element)) => Collections.some(this, f); | |
81 bool isEmpty() => length == 0; | |
82 } | |
83 | |
84 class FixedIterator<E> implements Iterator<E> { | |
85 final E value; | |
86 final int length; | |
87 int _index = 0; | |
88 FixedIterator(this.value, this.length); | |
89 | |
90 bool hasNext() => _index < length; | |
91 E next() { | |
92 _index++; | |
93 return value; | |
94 } | |
95 } | |
96 | |
97 // Color constants used for generating messages. | |
98 String _GREEN_COLOR = '\u001b[32m'; | |
99 String _RED_COLOR = '\u001b[31m'; | |
100 String _MAGENTA_COLOR = '\u001b[35m'; | |
101 String _NO_COLOR = '\u001b[0m'; | |
102 | |
103 | |
104 /** | |
105 * An implementation detail of [CopyOnWriteMap]. Essentially just | |
106 * [HashMapImplementation] plus an additional [shared] field. | |
107 */ | |
108 class _SharedBackingMap<K, V> extends HashMapImplementation<K, V> { | |
109 /** | |
110 * The number of [CopyOnWriteMap] instances sharing this excluding the | |
111 * original, i.e. it is safe to write iff `shared == 0`; | |
112 */ | |
113 int shared = 0; | |
114 _SharedBackingMap(); | |
115 factory _SharedBackingMap.from(Map<K, V> other) { | |
116 final result = new _SharedBackingMap<K, V>(); | |
117 other.forEach((K k, V v) { result[k] = v; }); | |
118 return result; | |
119 } | |
120 } | |
121 | |
122 /** A copy-on-write [Map] implementation. */ | |
123 // TODO(jmesserly): A persistent tree-based implementation of Map would be much | |
124 // nicer. This is just a quick hack to get things working. | |
125 class CopyOnWriteMap<K extends Hashable, V> implements HashMap<K, V> { | |
126 _SharedBackingMap<K, V> _map; | |
127 | |
128 CopyOnWriteMap(): _map = new _SharedBackingMap<K, V>(); | |
129 CopyOnWriteMap._wrap(this._map); | |
130 factory CopyOnWriteMap.from(Map<K, V> other) { | |
131 if (other is CopyOnWriteMap<K, V>) { | |
132 return other.dynamic.clone(); | |
133 } | |
134 return new CopyOnWriteMap<K, V>._wrap( | |
135 new _SharedBackingMap<K, V>.from(other)); | |
136 } | |
137 | |
138 CopyOnWriteMap<K, V> clone() { | |
139 _map.shared++; | |
140 return new CopyOnWriteMap<K, V>._wrap(_map); | |
141 } | |
142 | |
143 void _ensureWritable() { | |
144 if (_map.shared > 0) { | |
145 _map.shared--; | |
146 _map = new _SharedBackingMap<K, V>.from(_map); | |
147 } | |
148 } | |
149 | |
150 void operator []=(K key, V value) { | |
151 _ensureWritable(); | |
152 _map[key] = value; | |
153 } | |
154 | |
155 V putIfAbsent(K key, V ifAbsent()) { | |
156 _ensureWritable(); | |
157 return _map.putIfAbsent(key, ifAbsent); | |
158 } | |
159 | |
160 void clear() { | |
161 _ensureWritable(); | |
162 _map.clear(); | |
163 } | |
164 | |
165 V remove(K key) { | |
166 _ensureWritable(); | |
167 return _map.remove(key); | |
168 } | |
169 | |
170 // Forwarding methods: | |
171 V operator [](K key) => _map[key]; | |
172 bool isEmpty() => _map.isEmpty(); | |
173 int get length() => _map.length; | |
174 void forEach(void f(K key, V value)) => _map.forEach(f); | |
175 Collection<K> getKeys() => _map.getKeys(); | |
176 Collection<V> getValues() => _map.getValues(); | |
177 bool containsKey(K key) => _map.containsKey(key); | |
178 bool containsValue(V value) => _map.containsValue(value); | |
179 } | |
OLD | NEW |