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 part of dart._internal; | |
6 | |
7 /** | |
8 * Mixin that throws on the length changing operations of [List]. | |
9 * | |
10 * Intended to mix-in on top of [ListMixin] for fixed-length lists. | |
11 */ | |
12 abstract class FixedLengthListMixin<E> { | |
13 /** This operation is not supported by a fixed length list. */ | |
14 void set length(int newLength) { | |
15 throw new UnsupportedError( | |
16 "Cannot change the length of a fixed-length list"); | |
17 } | |
18 | |
19 /** This operation is not supported by a fixed length list. */ | |
20 void add(E value) { | |
21 throw new UnsupportedError( | |
22 "Cannot add to a fixed-length list"); | |
23 } | |
24 | |
25 /** This operation is not supported by a fixed length list. */ | |
26 void insert(int index, E value) { | |
27 throw new UnsupportedError( | |
28 "Cannot add to a fixed-length list"); | |
29 } | |
30 | |
31 /** This operation is not supported by a fixed length list. */ | |
32 void insertAll(int at, Iterable<E> iterable) { | |
33 throw new UnsupportedError( | |
34 "Cannot add to a fixed-length list"); | |
35 } | |
36 | |
37 /** This operation is not supported by a fixed length list. */ | |
38 void addAll(Iterable<E> iterable) { | |
39 throw new UnsupportedError( | |
40 "Cannot add to a fixed-length list"); | |
41 } | |
42 | |
43 /** This operation is not supported by a fixed length list. */ | |
44 bool remove(Object element) { | |
45 throw new UnsupportedError( | |
46 "Cannot remove from a fixed-length list"); | |
47 } | |
48 | |
49 /** This operation is not supported by a fixed length list. */ | |
50 void removeWhere(bool test(E element)) { | |
51 throw new UnsupportedError( | |
52 "Cannot remove from a fixed-length list"); | |
53 } | |
54 | |
55 /** This operation is not supported by a fixed length list. */ | |
56 void retainWhere(bool test(E element)) { | |
57 throw new UnsupportedError( | |
58 "Cannot remove from a fixed-length list"); | |
59 } | |
60 | |
61 /** This operation is not supported by a fixed length list. */ | |
62 void clear() { | |
63 throw new UnsupportedError( | |
64 "Cannot clear a fixed-length list"); | |
65 } | |
66 | |
67 /** This operation is not supported by a fixed length list. */ | |
68 E removeAt(int index) { | |
69 throw new UnsupportedError( | |
70 "Cannot remove from a fixed-length list"); | |
71 } | |
72 | |
73 /** This operation is not supported by a fixed length list. */ | |
74 E removeLast() { | |
75 throw new UnsupportedError( | |
76 "Cannot remove from a fixed-length list"); | |
77 } | |
78 | |
79 /** This operation is not supported by a fixed length list. */ | |
80 void removeRange(int start, int end) { | |
81 throw new UnsupportedError( | |
82 "Cannot remove from a fixed-length list"); | |
83 } | |
84 | |
85 /** This operation is not supported by a fixed length list. */ | |
86 void replaceRange(int start, int end, Iterable<E> iterable) { | |
87 throw new UnsupportedError( | |
88 "Cannot remove from a fixed-length list"); | |
89 } | |
90 } | |
91 | |
92 /** | |
93 * Mixin for an unmodifiable [List] class. | |
94 * | |
95 * This overrides all mutating methods with methods that throw. | |
96 * This mixin is intended to be mixed in on top of [ListMixin] on | |
97 * unmodifiable lists. | |
98 */ | |
99 abstract class UnmodifiableListMixin<E> implements List<E> { | |
100 | |
101 /** This operation is not supported by an unmodifiable list. */ | |
102 void operator []=(int index, E value) { | |
103 throw new UnsupportedError( | |
104 "Cannot modify an unmodifiable list"); | |
105 } | |
106 | |
107 /** This operation is not supported by an unmodifiable list. */ | |
108 void set length(int newLength) { | |
109 throw new UnsupportedError( | |
110 "Cannot change the length of an unmodifiable list"); | |
111 } | |
112 | |
113 /** This operation is not supported by an unmodifiable list. */ | |
114 void setAll(int at, Iterable<E> iterable) { | |
115 throw new UnsupportedError( | |
116 "Cannot modify an unmodifiable list"); | |
117 } | |
118 | |
119 /** This operation is not supported by an unmodifiable list. */ | |
120 void add(E value) { | |
121 throw new UnsupportedError( | |
122 "Cannot add to an unmodifiable list"); | |
123 } | |
124 | |
125 /** This operation is not supported by an unmodifiable list. */ | |
126 void insert(int index, E element) { | |
127 throw new UnsupportedError( | |
128 "Cannot add to an unmodifiable list"); | |
129 } | |
130 | |
131 /** This operation is not supported by an unmodifiable list. */ | |
132 void insertAll(int at, Iterable<E> iterable) { | |
133 throw new UnsupportedError( | |
134 "Cannot add to an unmodifiable list"); | |
135 } | |
136 | |
137 /** This operation is not supported by an unmodifiable list. */ | |
138 void addAll(Iterable<E> iterable) { | |
139 throw new UnsupportedError( | |
140 "Cannot add to an unmodifiable list"); | |
141 } | |
142 | |
143 /** This operation is not supported by an unmodifiable list. */ | |
144 bool remove(Object element) { | |
145 throw new UnsupportedError( | |
146 "Cannot remove from an unmodifiable list"); | |
147 } | |
148 | |
149 /** This operation is not supported by an unmodifiable list. */ | |
150 void removeWhere(bool test(E element)) { | |
151 throw new UnsupportedError( | |
152 "Cannot remove from an unmodifiable list"); | |
153 } | |
154 | |
155 /** This operation is not supported by an unmodifiable list. */ | |
156 void retainWhere(bool test(E element)) { | |
157 throw new UnsupportedError( | |
158 "Cannot remove from an unmodifiable list"); | |
159 } | |
160 | |
161 /** This operation is not supported by an unmodifiable list. */ | |
162 void sort([Comparator<E> compare]) { | |
163 throw new UnsupportedError( | |
164 "Cannot modify an unmodifiable list"); | |
165 } | |
166 | |
167 /** This operation is not supported by an unmodifiable list. */ | |
168 void shuffle([Random random]) { | |
169 throw new UnsupportedError( | |
170 "Cannot modify an unmodifiable list"); | |
171 } | |
172 | |
173 /** This operation is not supported by an unmodifiable list. */ | |
174 void clear() { | |
175 throw new UnsupportedError( | |
176 "Cannot clear an unmodifiable list"); | |
177 } | |
178 | |
179 /** This operation is not supported by an unmodifiable list. */ | |
180 E removeAt(int index) { | |
181 throw new UnsupportedError( | |
182 "Cannot remove from an unmodifiable list"); | |
183 } | |
184 | |
185 /** This operation is not supported by an unmodifiable list. */ | |
186 E removeLast() { | |
187 throw new UnsupportedError( | |
188 "Cannot remove from an unmodifiable list"); | |
189 } | |
190 | |
191 /** This operation is not supported by an unmodifiable list. */ | |
192 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | |
193 throw new UnsupportedError( | |
194 "Cannot modify an unmodifiable list"); | |
195 } | |
196 | |
197 /** This operation is not supported by an unmodifiable list. */ | |
198 void removeRange(int start, int end) { | |
199 throw new UnsupportedError( | |
200 "Cannot remove from an unmodifiable list"); | |
201 } | |
202 | |
203 /** This operation is not supported by an unmodifiable list. */ | |
204 void replaceRange(int start, int end, Iterable<E> iterable) { | |
205 throw new UnsupportedError( | |
206 "Cannot remove from an unmodifiable list"); | |
207 } | |
208 | |
209 /** This operation is not supported by an unmodifiable list. */ | |
210 void fillRange(int start, int end, [E fillValue]) { | |
211 throw new UnsupportedError( | |
212 "Cannot modify an unmodifiable list"); | |
213 } | |
214 } | |
215 | |
216 /** | |
217 * Abstract implementation of a fixed-length list. | |
218 * | |
219 * All operations are defined in terms of `length`, `operator[]` and | |
220 * `operator[]=`, which need to be implemented. | |
221 */ | |
222 abstract class FixedLengthListBase<E> = | |
223 ListBase<E> with FixedLengthListMixin<E>; | |
224 | |
225 /** | |
226 * Abstract implementation of an unmodifiable list. | |
227 * | |
228 * All operations are defined in terms of `length` and `operator[]`, | |
229 * which need to be implemented. | |
230 */ | |
231 abstract class UnmodifiableListBase<E> = | |
232 ListBase<E> with UnmodifiableListMixin<E>; | |
233 | |
234 class _ListIndicesIterable extends ListIterable<int> { | |
235 List _backedList; | |
236 | |
237 _ListIndicesIterable(this._backedList); | |
238 | |
239 int get length => _backedList.length; | |
240 int elementAt(int index) { | |
241 RangeError.checkValidIndex(index, this); | |
242 return index; | |
243 } | |
244 } | |
245 | |
246 class ListMapView<E> implements Map<int, E> { | |
247 List<E> _values; | |
248 | |
249 ListMapView(this._values); | |
250 | |
251 E operator[] (Object key) => containsKey(key) ? _values[key] : null; | |
252 int get length => _values.length; | |
253 | |
254 Iterable<E> get values => new SubListIterable<E>(_values, 0, null); | |
255 Iterable<int> get keys => new _ListIndicesIterable(_values); | |
256 | |
257 bool get isEmpty => _values.isEmpty; | |
258 bool get isNotEmpty => _values.isNotEmpty; | |
259 bool containsValue(Object value) => _values.contains(value); | |
260 bool containsKey(Object key) => key is int && key >= 0 && key < length; | |
261 | |
262 void forEach(void f(int key, E value)) { | |
263 int length = _values.length; | |
264 for (int i = 0; i < length; i++) { | |
265 f(i, _values[i]); | |
266 if (length != _values.length) { | |
267 throw new ConcurrentModificationError(_values); | |
268 } | |
269 } | |
270 } | |
271 | |
272 /** This operation is not supported by an unmodifiable map. */ | |
273 void operator[]= (int key, E value) { | |
274 throw new UnsupportedError("Cannot modify an unmodifiable map"); | |
275 } | |
276 | |
277 /** This operation is not supported by an unmodifiable map. */ | |
278 E putIfAbsent(int key, E ifAbsent()) { | |
279 throw new UnsupportedError("Cannot modify an unmodifiable map"); | |
280 } | |
281 | |
282 /** This operation is not supported by an unmodifiable map. */ | |
283 E remove(Object key) { | |
284 throw new UnsupportedError("Cannot modify an unmodifiable map"); | |
285 } | |
286 | |
287 /** This operation is not supported by an unmodifiable map. */ | |
288 void clear() { | |
289 throw new UnsupportedError("Cannot modify an unmodifiable map"); | |
290 } | |
291 | |
292 /** This operation is not supported by an unmodifiable map. */ | |
293 void addAll(Map<int, E> other) { | |
294 throw new UnsupportedError("Cannot modify an unmodifiable map"); | |
295 } | |
296 | |
297 String toString() => Maps.mapToString(this); | |
298 } | |
299 | |
300 class ReversedListIterable<E> extends ListIterable<E> { | |
301 Iterable<E> _source; | |
302 ReversedListIterable(this._source); | |
303 | |
304 int get length => _source.length; | |
305 | |
306 E elementAt(int index) => _source.elementAt(_source.length - 1 - index); | |
307 } | |
308 | |
309 /** | |
310 * Creates errors thrown by unmodifiable lists when they are attempted modified. | |
311 * | |
312 * This class creates [UnsupportedError]s with specialized messages. | |
313 */ | |
314 abstract class UnmodifiableListError { | |
315 /** Error thrown when trying to add elements to an unmodifiable list. */ | |
316 static UnsupportedError add() | |
317 => new UnsupportedError("Cannot add to unmodifiable List"); | |
318 | |
319 /** Error thrown when trying to add elements to an unmodifiable list. */ | |
320 static UnsupportedError change() | |
321 => new UnsupportedError( | |
322 "Cannot change the content of an unmodifiable List"); | |
323 | |
324 /** Error thrown when trying to change the length of an unmodifiable list. */ | |
325 static UnsupportedError length() | |
326 => new UnsupportedError("Cannot change length of unmodifiable List"); | |
327 | |
328 /** Error thrown when trying to remove elements from an unmodifiable list. */ | |
329 static UnsupportedError remove() | |
330 => new UnsupportedError("Cannot remove from unmodifiable List"); | |
331 } | |
332 | |
333 /** | |
334 * Creates errors thrown by non-growable lists when they are attempted modified. | |
335 * | |
336 * This class creates [UnsupportedError]s with specialized messages. | |
337 */ | |
338 abstract class NonGrowableListError { | |
339 /** Error thrown when trying to add elements to an non-growable list. */ | |
340 static UnsupportedError add() | |
341 => new UnsupportedError("Cannot add to non-growable List"); | |
342 | |
343 /** Error thrown when trying to change the length of an non-growable list. */ | |
344 static UnsupportedError length() | |
345 => new UnsupportedError("Cannot change length of non-growable List"); | |
346 | |
347 /** Error thrown when trying to remove elements from an non-growable list. */ | |
348 static UnsupportedError remove() | |
349 => new UnsupportedError("Cannot remove from non-growable List"); | |
350 } | |
351 | |
352 /** | |
353 * Converts a growable list to a fixed length list with the same elements. | |
354 * | |
355 * For internal use only. | |
356 * Only works on growable lists as created by `[]` or `new List()`. | |
357 * May throw on any other list. | |
358 * | |
359 * The operation is efficient. It doesn't copy the elements, but converts | |
360 * the existing list directly to a fixed length list. | |
361 * That means that it is a destructive conversion. | |
362 * The original list should not be used afterwards. | |
363 * | |
364 * The returned list may be the same list as the original, | |
365 * or it may be a different list (according to [identical]). | |
366 * The original list may have changed type to be a fixed list, | |
367 * or become empty or been otherwise modified. | |
368 * It will still be a valid object, so references to it will not, e.g., crash | |
369 * the runtime if accessed, but no promises are made wrt. its contents. | |
370 * | |
371 * This unspecified behavior is the reason the function is not exposed to | |
372 * users. We allow the underlying implementation to make the most efficient | |
373 * conversion, at the cost of leaving the original list in an unspecified | |
374 * state. | |
375 */ | |
376 external List/*<E>*/ makeListFixedLength/*<E>*/(List/*<E>*/ growableList); | |
377 | |
378 /** | |
379 * Converts a fixed-length list to an unmodifiable list. | |
380 * | |
381 * For internal use only. | |
382 * Only works for core fixed-length lists as created by `new List(length)`, | |
383 * or as returned by [makeListFixedLength]. | |
384 * | |
385 * The operation is efficient. It doesn't copy the elements, but converts | |
386 * the existing list directly to a fixed length list. | |
387 * That means that it is a destructive conversion. | |
388 * The original list should not be used afterwards. | |
389 * | |
390 * The unmodifiable list type is similar to the one used by const lists. | |
391 */ | |
392 external List/*<E>*/ makeFixedListUnmodifiable/*<E>*/( | |
393 List/*<E>*/ fixedLengthList); | |
OLD | NEW |