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 | 5 |
6 // TODO(srdjan): Use shared array implementation. | 6 // TODO(srdjan): Use shared array implementation. |
7 class _List<E> implements List<E> { | 7 class _List<E> extends FixedLengthListBase<E> { |
8 | 8 |
9 factory _List(length) native "List_allocate"; | 9 factory _List(length) native "List_allocate"; |
10 | 10 |
11 E operator [](int index) native "List_getIndexed"; | 11 E operator [](int index) native "List_getIndexed"; |
12 | 12 |
13 void operator []=(int index, E value) native "List_setIndexed"; | 13 void operator []=(int index, E value) native "List_setIndexed"; |
14 | 14 |
15 String toString() { | |
16 return ListBase.listToString(this); | |
17 } | |
18 | |
19 int get length native "List_getLength"; | 15 int get length native "List_getLength"; |
20 | 16 |
21 List _slice(int start, int count, bool needsTypeArgument) { | 17 List _slice(int start, int count, bool needsTypeArgument) { |
22 if (count <= 64) { | 18 if (count <= 64) { |
23 final result = needsTypeArgument ? new _List<E>(count) | 19 final result = needsTypeArgument ? new _List<E>(count) |
24 : new _List(count); | 20 : new _List(count); |
25 for (int i = 0; i < result.length; i++) { | 21 for (int i = 0; i < result.length; i++) { |
26 result[i] = this[start + i]; | 22 result[i] = this[start + i]; |
27 } | 23 } |
28 return result; | 24 return result; |
29 } else { | 25 } else { |
30 return _sliceInternal(start, count, needsTypeArgument); | 26 return _sliceInternal(start, count, needsTypeArgument); |
31 } | 27 } |
32 } | 28 } |
33 | 29 |
34 List _sliceInternal(int start, int count, bool needsTypeArgument) | 30 List _sliceInternal(int start, int count, bool needsTypeArgument) |
35 native "List_slice"; | 31 native "List_slice"; |
36 | 32 |
37 void insert(int index, E element) { | |
38 throw NonGrowableListError.add(); | |
39 } | |
40 | |
41 void insertAll(int index, Iterable<E> iterable) { | |
42 throw NonGrowableListError.add(); | |
43 } | |
44 | |
45 void setAll(int index, Iterable<E> iterable) { | |
46 IterableMixinWorkaround.setAllList(this, index, iterable); | |
47 } | |
48 | |
49 E removeAt(int index) { | |
50 throw NonGrowableListError.remove(); | |
51 } | |
52 | |
53 bool remove(Object element) { | |
54 throw NonGrowableListError.remove(); | |
55 } | |
56 | |
57 void removeWhere(bool test(E element)) { | |
58 throw NonGrowableListError.remove(); | |
59 } | |
60 | |
61 void retainWhere(bool test(E element)) { | |
62 throw NonGrowableListError.remove(); | |
63 } | |
64 | |
65 Iterable<E> getRange(int start, [int end]) { | |
66 return new IterableMixinWorkaround<E>().getRangeList(this, start, end); | |
67 } | |
68 | |
69 // List interface. | 33 // List interface. |
70 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | 34 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
71 if (start < 0 || start > this.length) { | 35 if (start < 0 || start > this.length) { |
72 throw new RangeError.range(start, 0, this.length); | 36 throw new RangeError.range(start, 0, this.length); |
73 } | 37 } |
74 if (end < start || end > this.length) { | 38 if (end < start || end > this.length) { |
75 throw new RangeError.range(end, start, this.length); | 39 throw new RangeError.range(end, start, this.length); |
76 } | 40 } |
77 int length = end - start; | 41 int length = end - start; |
78 if (length == 0) return; | 42 if (length == 0) return; |
79 if (identical(this, iterable)) { | 43 if (identical(this, iterable)) { |
80 Lists.copy(iterable, skipCount, this, start, length); | 44 Lists.copy(iterable, skipCount, this, start, length); |
81 } else if (ClassID.getID(iterable) == ClassID.cidArray) { | 45 } else if (ClassID.getID(iterable) == ClassID.cidArray) { |
82 Lists.copy(iterable, skipCount, this, start, length); | 46 Lists.copy(iterable, skipCount, this, start, length); |
83 } else if (iterable is List) { | 47 } else if (iterable is List) { |
84 Lists.copy(iterable, skipCount, this, start, length); | 48 Lists.copy(iterable, skipCount, this, start, length); |
85 } else { | 49 } else { |
86 Iterator it = iterable.iterator; | 50 Iterator it = iterable.iterator; |
87 while (skipCount > 0) { | 51 while (skipCount > 0) { |
88 if (!it.moveNext()) return; | 52 if (!it.moveNext()) return; |
89 skipCount--; | 53 skipCount--; |
90 } | 54 } |
91 for (int i = start; i < end; i++) { | 55 for (int i = start; i < end; i++) { |
92 if (!it.moveNext()) return; | 56 if (!it.moveNext()) return; |
93 this[i] = it.current; | 57 this[i] = it.current; |
94 } | 58 } |
95 } | 59 } |
96 } | 60 } |
97 | 61 |
98 void removeRange(int start, int end) { | |
99 throw NonGrowableListError.remove(); | |
100 } | |
101 | |
102 void replaceRange(int start, int end, Iterable<E> iterable) { | |
103 throw NonGrowableListError.remove(); | |
104 } | |
105 | |
106 void fillRange(int start, int end, [E fillValue]) { | |
107 IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); | |
108 } | |
109 | |
110 List<E> sublist(int start, [int end]) { | 62 List<E> sublist(int start, [int end]) { |
111 Lists.indicesCheck(this, start, end); | 63 Lists.indicesCheck(this, start, end); |
112 if (end == null) end = this.length; | 64 if (end == null) end = this.length; |
113 int length = end - start; | 65 int length = end - start; |
114 if (start == end) return <E>[]; | 66 if (start == end) return <E>[]; |
115 var result = new _GrowableList<E>.withData(_slice(start, length, false)); | 67 var result = new _GrowableList<E>.withData(_slice(start, length, false)); |
116 result._setLength(length); | 68 result._setLength(length); |
117 return result; | 69 return result; |
118 } | 70 } |
119 | 71 |
120 // Iterable interface. | 72 // Iterable interface. |
121 | 73 |
122 bool contains(Object element) { | |
123 return IterableMixinWorkaround.contains(this, element); | |
124 } | |
125 | |
126 void forEach(f(E element)) { | 74 void forEach(f(E element)) { |
127 final length = this.length; | 75 final length = this.length; |
128 for (int i = 0; i < length; i++) { | 76 for (int i = 0; i < length; i++) { |
129 f(this[i]); | 77 f(this[i]); |
130 } | 78 } |
131 } | 79 } |
132 | 80 |
133 String join([String separator = ""]) { | |
134 return IterableMixinWorkaround.joinList(this, separator); | |
135 } | |
136 | |
137 Iterable map(f(E element)) { | |
138 return IterableMixinWorkaround.mapList(this, f); | |
139 } | |
140 | |
141 E reduce(E combine(E value, E element)) { | |
142 return IterableMixinWorkaround.reduce(this, combine); | |
143 } | |
144 | |
145 fold(initialValue, combine(previousValue, E element)) { | |
146 return IterableMixinWorkaround.fold(this, initialValue, combine); | |
147 } | |
148 | |
149 Iterable<E> where(bool f(E element)) { | |
150 return new IterableMixinWorkaround<E>().where(this, f); | |
151 } | |
152 | |
153 Iterable expand(Iterable f(E element)) { | |
154 return IterableMixinWorkaround.expand(this, f); | |
155 } | |
156 | |
157 Iterable<E> take(int n) { | |
158 return new IterableMixinWorkaround<E>().takeList(this, n); | |
159 } | |
160 | |
161 Iterable<E> takeWhile(bool test(E value)) { | |
162 return new IterableMixinWorkaround<E>().takeWhile(this, test); | |
163 } | |
164 | |
165 Iterable<E> skip(int n) { | |
166 return new IterableMixinWorkaround<E>().skipList(this, n); | |
167 } | |
168 | |
169 Iterable<E> skipWhile(bool test(E value)) { | |
170 return new IterableMixinWorkaround<E>().skipWhile(this, test); | |
171 } | |
172 | |
173 bool every(bool f(E element)) { | |
174 return IterableMixinWorkaround.every(this, f); | |
175 } | |
176 | |
177 bool any(bool f(E element)) { | |
178 return IterableMixinWorkaround.any(this, f); | |
179 } | |
180 | |
181 E firstWhere(bool test(E value), {E orElse()}) { | |
182 return IterableMixinWorkaround.firstWhere(this, test, orElse); | |
183 } | |
184 | |
185 E lastWhere(bool test(E value), {E orElse()}) { | |
186 return IterableMixinWorkaround.lastWhereList(this, test, orElse); | |
187 } | |
188 | |
189 E singleWhere(bool test(E value)) { | |
190 return IterableMixinWorkaround.singleWhere(this, test); | |
191 } | |
192 | |
193 E elementAt(int index) { | |
194 return this[index]; | |
195 } | |
196 | |
197 bool get isEmpty { | |
198 return this.length == 0; | |
199 } | |
200 | |
201 bool get isNotEmpty => !isEmpty; | |
202 | |
203 Iterable<E> get reversed => | |
204 new IterableMixinWorkaround<E>().reversedList(this); | |
205 | |
206 void sort([int compare(E a, E b)]) { | |
207 IterableMixinWorkaround.sortList(this, compare); | |
208 } | |
209 | |
210 void shuffle([Random random]) { | |
211 IterableMixinWorkaround.shuffleList(this, random); | |
212 } | |
213 | |
214 int indexOf(Object element, [int start = 0]) { | |
215 return Lists.indexOf(this, element, start, this.length); | |
216 } | |
217 | |
218 int lastIndexOf(Object element, [int start = null]) { | |
219 if (start == null) start = length - 1; | |
220 return Lists.lastIndexOf(this, element, start); | |
221 } | |
222 | |
223 Iterator<E> get iterator { | 81 Iterator<E> get iterator { |
224 return new _FixedSizeArrayIterator<E>(this); | 82 return new _FixedSizeArrayIterator<E>(this); |
225 } | 83 } |
226 | 84 |
227 void add(E element) { | |
228 throw NonGrowableListError.add(); | |
229 } | |
230 | |
231 void addAll(Iterable<E> iterable) { | |
232 throw NonGrowableListError.add(); | |
233 } | |
234 | |
235 void clear() { | |
236 throw NonGrowableListError.remove(); | |
237 } | |
238 | |
239 void set length(int length) { | |
240 throw NonGrowableListError.length(); | |
241 } | |
242 | |
243 E removeLast() { | |
244 throw NonGrowableListError.remove(); | |
245 } | |
246 | |
247 E get first { | 85 E get first { |
248 if (length > 0) return this[0]; | 86 if (length > 0) return this[0]; |
249 throw IterableElementError.noElement(); | 87 throw IterableElementError.noElement(); |
250 } | 88 } |
251 | 89 |
252 E get last { | 90 E get last { |
253 if (length > 0) return this[length - 1]; | 91 if (length > 0) return this[length - 1]; |
254 throw IterableElementError.noElement(); | 92 throw IterableElementError.noElement(); |
255 } | 93 } |
256 | 94 |
257 E get single { | 95 E get single { |
258 if (length == 1) return this[0]; | 96 if (length == 1) return this[0]; |
259 if (length == 0) throw IterableElementError.noElement(); | 97 if (length == 0) throw IterableElementError.noElement(); |
260 throw IterableElementError.tooMany(); | 98 throw IterableElementError.tooMany(); |
261 } | 99 } |
262 | 100 |
263 List<E> toList({ bool growable: true }) { | 101 List<E> toList({ bool growable: true }) { |
264 var length = this.length; | 102 var length = this.length; |
265 if (length > 0) { | 103 if (length > 0) { |
266 var result = _slice(0, length, !growable); | 104 var result = _slice(0, length, !growable); |
267 if (growable) { | 105 if (growable) { |
268 result = new _GrowableList<E>.withData(result); | 106 result = new _GrowableList<E>.withData(result); |
269 result._setLength(length); | 107 result._setLength(length); |
270 } | 108 } |
271 return result; | 109 return result; |
272 } | 110 } |
273 // _GrowableList.withData must not be called with empty list. | 111 // _GrowableList.withData must not be called with empty list. |
274 return growable ? <E>[] : new List<E>(0); | 112 return growable ? <E>[] : new List<E>(0); |
275 } | 113 } |
276 | |
277 Set<E> toSet() { | |
278 return new Set<E>.from(this); | |
279 } | |
280 | |
281 Map<int, E> asMap() { | |
282 return new IterableMixinWorkaround<E>().asMapList(this); | |
283 } | |
284 } | 114 } |
285 | 115 |
286 | 116 |
287 // This is essentially the same class as _List, but it does not | 117 // This is essentially the same class as _List, but it does not |
288 // permit any modification of array elements from Dart code. We use | 118 // permit any modification of array elements from Dart code. We use |
289 // this class for arrays constructed from Dart array literals. | 119 // this class for arrays constructed from Dart array literals. |
290 // TODO(hausner): We should consider the trade-offs between two | 120 // TODO(hausner): We should consider the trade-offs between two |
291 // classes (and inline cache misses) versus a field in the native | 121 // classes (and inline cache misses) versus a field in the native |
292 // implementation (checks when modifying). We should keep watching | 122 // implementation (checks when modifying). We should keep watching |
293 // the inline cache misses. | 123 // the inline cache misses. |
294 class _ImmutableList<E> implements List<E> { | 124 class _ImmutableList<E> extends UnmodifiableListBase<E> { |
295 | 125 |
296 factory _ImmutableList._uninstantiable() { | 126 factory _ImmutableList._uninstantiable() { |
297 throw new UnsupportedError( | 127 throw new UnsupportedError( |
298 "ImmutableArray can only be allocated by the VM"); | 128 "ImmutableArray can only be allocated by the VM"); |
299 } | 129 } |
300 | 130 |
301 factory _ImmutableList._from(List from, int offset, int length) | 131 factory _ImmutableList._from(List from, int offset, int length) |
302 native "ImmutableList_from"; | 132 native "ImmutableList_from"; |
303 | 133 |
304 E operator [](int index) native "List_getIndexed"; | 134 E operator [](int index) native "List_getIndexed"; |
305 | 135 |
306 void operator []=(int index, E value) { | |
307 throw UnmodifiableListError.change(); | |
308 } | |
309 | |
310 int get length native "List_getLength"; | 136 int get length native "List_getLength"; |
311 | 137 |
312 void insert(int index, E element) { | |
313 throw UnmodifiableListError.add(); | |
314 } | |
315 | |
316 void insertAll(int index, Iterable<E> iterable) { | |
317 throw UnmodifiableListError.add(); | |
318 } | |
319 | |
320 void setAll(int index, Iterable<E> iterable) { | |
321 throw UnmodifiableListError.change(); | |
322 } | |
323 | |
324 E removeAt(int index) { | |
325 throw UnmodifiableListError.remove(); | |
326 } | |
327 | |
328 bool remove(Object element) { | |
329 throw UnmodifiableListError.remove(); | |
330 } | |
331 | |
332 void removeWhere(bool test(E element)) { | |
333 throw UnmodifiableListError.remove(); | |
334 } | |
335 | |
336 void retainWhere(bool test(E element)) { | |
337 throw UnmodifiableListError.remove(); | |
338 } | |
339 | |
340 void copyFrom(List src, int srcStart, int dstStart, int count) { | |
341 throw UnmodifiableListError.change(); | |
342 } | |
343 | |
344 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | |
345 throw UnmodifiableListError.change(); | |
346 } | |
347 | |
348 void removeRange(int start, int end) { | |
349 throw UnmodifiableListError.remove(); | |
350 } | |
351 | |
352 void fillRange(int start, int end, [E fillValue]) { | |
353 throw UnmodifiableListError.change(); | |
354 } | |
355 | |
356 void replaceRange(int start, int end, Iterable<E> iterable) { | |
357 throw UnmodifiableListError.change(); | |
358 } | |
359 | |
360 List<E> sublist(int start, [int end]) { | 138 List<E> sublist(int start, [int end]) { |
361 Lists.indicesCheck(this, start, end); | 139 Lists.indicesCheck(this, start, end); |
362 if (end == null) end = this.length; | 140 if (end == null) end = this.length; |
363 int length = end - start; | 141 int length = end - start; |
364 if (length == 0) return <E>[]; | 142 if (length == 0) return <E>[]; |
365 List list = new _List(length); | 143 List list = new _List(length); |
366 for (int i = 0; i < length; i++) { | 144 for (int i = 0; i < length; i++) { |
367 list[i] = this[start + i]; | 145 list[i] = this[start + i]; |
368 } | 146 } |
369 var result = new _GrowableList<E>.withData(list); | 147 var result = new _GrowableList<E>.withData(list); |
370 result._setLength(length); | 148 result._setLength(length); |
371 return result; | 149 return result; |
372 } | 150 } |
373 | 151 |
374 Iterable<E> getRange(int start, int end) { | |
375 return new IterableMixinWorkaround<E>().getRangeList(this, start, end); | |
376 } | |
377 | |
378 // Collection interface. | 152 // Collection interface. |
379 | 153 |
380 bool contains(Object element) { | |
381 return IterableMixinWorkaround.contains(this, element); | |
382 } | |
383 | |
384 void forEach(f(E element)) { | 154 void forEach(f(E element)) { |
385 final length = this.length; | 155 final length = this.length; |
386 for (int i = 0; i < length; i++) { | 156 for (int i = 0; i < length; i++) { |
387 f(this[i]); | 157 f(this[i]); |
388 } | 158 } |
389 } | 159 } |
390 | 160 |
391 Iterable map(f(E element)) { | |
392 return IterableMixinWorkaround.mapList(this, f); | |
393 } | |
394 | |
395 String join([String separator = ""]) { | |
396 return IterableMixinWorkaround.joinList(this, separator); | |
397 } | |
398 | |
399 E reduce(E combine(E value, E element)) { | |
400 return IterableMixinWorkaround.reduce(this, combine); | |
401 } | |
402 | |
403 fold(initialValue, combine(previousValue, E element)) { | |
404 return IterableMixinWorkaround.fold(this, initialValue, combine); | |
405 } | |
406 | |
407 Iterable<E> where(bool f(E element)) { | |
408 return new IterableMixinWorkaround<E>().where(this, f); | |
409 } | |
410 | |
411 Iterable expand(Iterable f(E element)) { | |
412 return IterableMixinWorkaround.expand(this, f); | |
413 } | |
414 | |
415 Iterable<E> take(int n) { | |
416 return new IterableMixinWorkaround<E>().takeList(this, n); | |
417 } | |
418 | |
419 Iterable<E> takeWhile(bool test(E value)) { | |
420 return new IterableMixinWorkaround<E>().takeWhile(this, test); | |
421 } | |
422 | |
423 Iterable<E> skip(int n) { | |
424 return new IterableMixinWorkaround<E>().skipList(this, n); | |
425 } | |
426 | |
427 Iterable<E> skipWhile(bool test(E value)) { | |
428 return new IterableMixinWorkaround<E>().skipWhile(this, test); | |
429 } | |
430 | |
431 bool every(bool f(E element)) { | |
432 return IterableMixinWorkaround.every(this, f); | |
433 } | |
434 | |
435 bool any(bool f(E element)) { | |
436 return IterableMixinWorkaround.any(this, f); | |
437 } | |
438 | |
439 E firstWhere(bool test(E value), {E orElse()}) { | |
440 return IterableMixinWorkaround.firstWhere(this, test, orElse); | |
441 } | |
442 | |
443 E lastWhere(bool test(E value), {E orElse()}) { | |
444 return IterableMixinWorkaround.lastWhereList(this, test, orElse); | |
445 } | |
446 | |
447 E singleWhere(bool test(E value)) { | |
448 return IterableMixinWorkaround.singleWhere(this, test); | |
449 } | |
450 | |
451 E elementAt(int index) { | |
452 return this[index]; | |
453 } | |
454 | |
455 bool get isEmpty { | |
456 return this.length == 0; | |
457 } | |
458 | |
459 bool get isNotEmpty => !isEmpty; | |
460 | |
461 Iterable<E> get reversed => | |
462 new IterableMixinWorkaround<E>().reversedList(this); | |
463 | |
464 void sort([int compare(E a, E b)]) { | |
465 throw UnmodifiableListError.change(); | |
466 } | |
467 | |
468 void shuffle([Random random]) { | |
469 throw UnmodifiableListError.change(); | |
470 } | |
471 | |
472 String toString() { | |
473 return ListBase.listToString(this); | |
474 } | |
475 | |
476 int indexOf(Object element, [int start = 0]) { | |
477 return Lists.indexOf(this, element, start, this.length); | |
478 } | |
479 | |
480 int lastIndexOf(Object element, [int start = null]) { | |
481 if (start == null) start = length - 1; | |
482 return Lists.lastIndexOf(this, element, start); | |
483 } | |
484 | |
485 Iterator<E> get iterator { | 161 Iterator<E> get iterator { |
486 return new _FixedSizeArrayIterator<E>(this); | 162 return new _FixedSizeArrayIterator<E>(this); |
487 } | 163 } |
488 | 164 |
489 void add(E element) { | |
490 throw UnmodifiableListError.add(); | |
491 } | |
492 | |
493 void addAll(Iterable<E> elements) { | |
494 throw UnmodifiableListError.add(); | |
495 } | |
496 | |
497 void clear() { | |
498 throw UnmodifiableListError.remove(); | |
499 } | |
500 | |
501 void set length(int length) { | |
502 throw UnmodifiableListError.length(); | |
503 } | |
504 | |
505 E removeLast() { | |
506 throw UnmodifiableListError.remove(); | |
507 } | |
508 | |
509 E get first { | 165 E get first { |
510 if (length > 0) return this[0]; | 166 if (length > 0) return this[0]; |
511 throw IterableElementError.noElement(); | 167 throw IterableElementError.noElement(); |
512 } | 168 } |
513 | 169 |
514 E get last { | 170 E get last { |
515 if (length > 0) return this[length - 1]; | 171 if (length > 0) return this[length - 1]; |
516 throw IterableElementError.noElement(); | 172 throw IterableElementError.noElement(); |
517 } | 173 } |
518 | 174 |
(...skipping 10 matching lines...) Expand all Loading... |
529 for (int i = 0; i < length; i++) { | 185 for (int i = 0; i < length; i++) { |
530 list[i] = this[i]; | 186 list[i] = this[i]; |
531 } | 187 } |
532 if (!growable) return list; | 188 if (!growable) return list; |
533 var result = new _GrowableList<E>.withData(list); | 189 var result = new _GrowableList<E>.withData(list); |
534 result._setLength(length); | 190 result._setLength(length); |
535 return result; | 191 return result; |
536 } | 192 } |
537 return growable ? <E>[] : new _List<E>(0); | 193 return growable ? <E>[] : new _List<E>(0); |
538 } | 194 } |
539 | |
540 Set<E> toSet() { | |
541 return new Set<E>.from(this); | |
542 } | |
543 | |
544 Map<int, E> asMap() { | |
545 return new IterableMixinWorkaround<E>().asMapList(this); | |
546 } | |
547 } | 195 } |
548 | 196 |
549 | 197 |
550 // Iterator for arrays with fixed size. | 198 // Iterator for arrays with fixed size. |
551 class _FixedSizeArrayIterator<E> implements Iterator<E> { | 199 class _FixedSizeArrayIterator<E> implements Iterator<E> { |
552 final List<E> _array; | 200 final List<E> _array; |
553 final int _length; // Cache array length for faster access. | 201 final int _length; // Cache array length for faster access. |
554 int _index; | 202 int _index; |
555 E _current; | 203 E _current; |
556 | 204 |
557 _FixedSizeArrayIterator(List array) | 205 _FixedSizeArrayIterator(List array) |
558 : _array = array, _length = array.length, _index = 0 { | 206 : _array = array, _length = array.length, _index = 0 { |
559 assert(array is _List || array is _ImmutableList); | 207 assert(array is _List || array is _ImmutableList); |
560 } | 208 } |
561 | 209 |
562 E get current => _current; | 210 E get current => _current; |
563 | 211 |
564 bool moveNext() { | 212 bool moveNext() { |
565 if (_index >= _length) { | 213 if (_index >= _length) { |
566 _current = null; | 214 _current = null; |
567 return false; | 215 return false; |
568 } | 216 } |
569 _current = _array[_index]; | 217 _current = _array[_index]; |
570 _index++; | 218 _index++; |
571 return true; | 219 return true; |
572 } | 220 } |
573 } | 221 } |
OLD | NEW |