Mercurial > projects > ldc
comparison tango/tango/util/collection/ArraySeq.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 /* | |
2 File: ArraySeq.d | |
3 | |
4 Originally written by Doug Lea and released into the public domain. | |
5 Thanks for the assistance and support of Sun Microsystems Labs, Agorics | |
6 Inc, Loral, and everyone contributing, testing, and using this code. | |
7 | |
8 History: | |
9 Date Who What | |
10 2Oct95 dl@cs.oswego.edu refactored from DASeq.d | |
11 13Oct95 dl Changed protection statuses | |
12 | |
13 */ | |
14 | |
15 | |
16 module tango.util.collection.ArraySeq; | |
17 | |
18 private import tango.util.collection.model.Iterator, | |
19 tango.util.collection.model.Sortable, | |
20 tango.util.collection.model.Comparator, | |
21 tango.util.collection.model.GuardIterator; | |
22 | |
23 private import tango.util.collection.impl.SeqCollection, | |
24 tango.util.collection.impl.AbstractIterator; | |
25 | |
26 | |
27 /** | |
28 * | |
29 * Dynamically allocated and resized Arrays. | |
30 * | |
31 * Beyond implementing its interfaces, adds methods | |
32 * to adjust capacities. The default heuristics for resizing | |
33 * usually work fine, but you can adjust them manually when | |
34 * you need to. | |
35 * | |
36 * ArraySeqs are generally like java.util.Vectors. But unlike them, | |
37 * ArraySeqs do not actually allocate arrays when they are constructed. | |
38 * Among other consequences, you can adjust the capacity `for free' | |
39 * after construction but before adding elements. You can adjust | |
40 * it at other times as well, but this may lead to more expensive | |
41 * resizing. Also, unlike Vectors, they release their internal arrays | |
42 * whenever they are empty. | |
43 * | |
44 * | |
45 author: Doug Lea | |
46 * @version 0.93 | |
47 * | |
48 * <P> For an introduction to this package see <A HREF="index.html"> Overview </A>. | |
49 * | |
50 **/ | |
51 | |
52 public class ArraySeq(T) : SeqCollection!(T), Sortable!(T) | |
53 { | |
54 alias SeqCollection!(T).remove remove; | |
55 alias SeqCollection!(T).removeAll removeAll; | |
56 | |
57 /** | |
58 * The minimum capacity of any non-empty buffer | |
59 **/ | |
60 | |
61 public static int minCapacity = 16; | |
62 | |
63 | |
64 // instance variables | |
65 | |
66 /** | |
67 * The elements, or null if no buffer yet allocated. | |
68 **/ | |
69 | |
70 package T array[]; | |
71 | |
72 | |
73 // constructors | |
74 | |
75 /** | |
76 * Make a new empty ArraySeq. | |
77 **/ | |
78 | |
79 public this () | |
80 { | |
81 this (null, null, 0); | |
82 } | |
83 | |
84 /** | |
85 * Make an empty ArraySeq with given element screener | |
86 **/ | |
87 | |
88 public this (Predicate screener) | |
89 { | |
90 this (screener, null, 0); | |
91 } | |
92 | |
93 /** | |
94 * Special version of constructor needed by clone() | |
95 **/ | |
96 package this (Predicate s, T[] b, int c) | |
97 { | |
98 super(s); | |
99 array = b; | |
100 count = c; | |
101 } | |
102 | |
103 /** | |
104 * Make an independent copy. The elements themselves are not cloned | |
105 **/ | |
106 | |
107 public final ArraySeq duplicate() | |
108 { | |
109 int cap = count; | |
110 if (cap is 0) | |
111 return new ArraySeq (screener, null, 0); | |
112 else | |
113 { | |
114 if (cap < minCapacity) | |
115 cap = minCapacity; | |
116 | |
117 T newArray[] = new T[cap]; | |
118 //System.copy (array[0].sizeof, array, 0, newArray, 0, count); | |
119 | |
120 newArray[0..count] = array[0..count]; | |
121 return new ArraySeq!(T)(screener, newArray, count); | |
122 } | |
123 } | |
124 | |
125 // methods introduced _in ArraySeq | |
126 | |
127 /** | |
128 * return the current internal buffer capacity (zero if no buffer allocated). | |
129 * Returns: capacity (always greater than or equal to size()) | |
130 **/ | |
131 | |
132 public final int capacity() | |
133 { | |
134 return (array is null) ? 0 : array.length; | |
135 } | |
136 | |
137 /** | |
138 * Set the internal buffer capacity to max(size(), newCap). | |
139 * That is, if given an argument less than the current | |
140 * number of elements, the capacity is just set to the | |
141 * current number of elements. Thus, elements are never lost | |
142 * by setting the capacity. | |
143 * | |
144 * @param newCap the desired capacity. | |
145 * Returns: condition: | |
146 * <PRE> | |
147 * capacity() >= size() && | |
148 * version() != PREV(this).version() == (capacity() != PREV(this).capacity()) | |
149 * </PRE> | |
150 **/ | |
151 | |
152 public final void capacity(int newCap) | |
153 { | |
154 if (newCap < count) | |
155 newCap = count; | |
156 | |
157 if (newCap is 0) | |
158 { | |
159 clear(); | |
160 } | |
161 else | |
162 if (array is null) | |
163 { | |
164 array = new T[newCap]; | |
165 incVersion(); | |
166 } | |
167 else | |
168 if (newCap !is array.length) | |
169 { | |
170 //T newArray[] = new T[newCap]; | |
171 //newArray[0..count] = array[0..count]; | |
172 //array = newArray; | |
173 array ~= new T[newCap - array.length]; | |
174 incVersion(); | |
175 } | |
176 } | |
177 | |
178 | |
179 // Collection methods | |
180 | |
181 /** | |
182 * Implements tango.util.collection.impl.Collection.Collection.contains | |
183 * Time complexity: O(n). | |
184 * See_Also: tango.util.collection.impl.Collection.Collection.contains | |
185 **/ | |
186 public final bool contains(T element) | |
187 { | |
188 if (! isValidArg (element)) | |
189 return false; | |
190 | |
191 for (int i = 0; i < count; ++i) | |
192 if (array[i] == (element)) | |
193 return true; | |
194 return false; | |
195 } | |
196 | |
197 /** | |
198 * Implements tango.util.collection.impl.Collection.Collection.instances | |
199 * Time complexity: O(n). | |
200 * See_Also: tango.util.collection.impl.Collection.Collection.instances | |
201 **/ | |
202 public final uint instances(T element) | |
203 { | |
204 if (! isValidArg(element)) | |
205 return 0; | |
206 | |
207 uint c = 0; | |
208 for (uint i = 0; i < count; ++i) | |
209 if (array[i] == (element)) | |
210 ++c; | |
211 return c; | |
212 } | |
213 | |
214 /** | |
215 * Implements tango.util.collection.impl.Collection.Collection.elements | |
216 * Time complexity: O(1). | |
217 * See_Also: tango.util.collection.impl.Collection.Collection.elements | |
218 **/ | |
219 public final GuardIterator!(T) elements() | |
220 { | |
221 return new ArrayIterator!(T)(this); | |
222 } | |
223 | |
224 /** | |
225 * Implements tango.util.collection.model.View.View.opApply | |
226 * Time complexity: O(n). | |
227 * See_Also: tango.util.collection.model.View.View.opApply | |
228 **/ | |
229 int opApply (int delegate (inout T value) dg) | |
230 { | |
231 auto scope iterator = new ArrayIterator!(T)(this); | |
232 return iterator.opApply (dg); | |
233 } | |
234 | |
235 | |
236 // Seq methods: | |
237 | |
238 /** | |
239 * Implements tango.util.collection.model.Seq.Seq.head. | |
240 * Time complexity: O(1). | |
241 * See_Also: tango.util.collection.model.Seq.Seq.head | |
242 **/ | |
243 public final T head() | |
244 { | |
245 checkIndex(0); | |
246 return array[0]; | |
247 } | |
248 | |
249 /** | |
250 * Implements tango.util.collection.model.Seq.Seq.tail. | |
251 * Time complexity: O(1). | |
252 * See_Also: tango.util.collection.model.Seq.Seq.tail | |
253 **/ | |
254 public final T tail() | |
255 { | |
256 checkIndex(count -1); | |
257 return array[count -1]; | |
258 } | |
259 | |
260 /** | |
261 * Implements tango.util.collection.model.Seq.Seq.get. | |
262 * Time complexity: O(1). | |
263 * See_Also: tango.util.collection.model.Seq.Seq.get | |
264 **/ | |
265 public final T get(int index) | |
266 in { | |
267 checkIndex(index); | |
268 } | |
269 body | |
270 { | |
271 return array[index]; | |
272 } | |
273 | |
274 /** | |
275 * Implements tango.util.collection.model.Seq.Seq.first. | |
276 * Time complexity: O(n). | |
277 * See_Also: tango.util.collection.model.Seq.Seq.first | |
278 **/ | |
279 public final int first(T element, int startingIndex = 0) | |
280 { | |
281 if (startingIndex < 0) | |
282 startingIndex = 0; | |
283 | |
284 for (int i = startingIndex; i < count; ++i) | |
285 if (array[i] == (element)) | |
286 return i; | |
287 return -1; | |
288 } | |
289 | |
290 /** | |
291 * Implements tango.util.collection.model.Seq.Seq.last. | |
292 * Time complexity: O(n). | |
293 * See_Also: tango.util.collection.model.Seq.Seq.last | |
294 **/ | |
295 public final int last(T element, int startingIndex = 0) | |
296 { | |
297 if (startingIndex >= count) | |
298 startingIndex = count -1; | |
299 | |
300 for (int i = startingIndex; i >= 0; --i) | |
301 if (array[i] == (element)) | |
302 return i; | |
303 return -1; | |
304 } | |
305 | |
306 | |
307 /** | |
308 * Implements tango.util.collection.model.Seq.Seq.subseq. | |
309 * Time complexity: O(length). | |
310 * See_Also: tango.util.collection.model.Seq.Seq.subseq | |
311 **/ | |
312 public final ArraySeq subset (int from, int _length) | |
313 { | |
314 if (_length > 0) | |
315 { | |
316 checkIndex(from); | |
317 checkIndex(from + _length - 1); | |
318 | |
319 T newArray[] = new T[_length]; | |
320 //System.copy (array[0].sizeof, array, from, newArray, 0, _length); | |
321 | |
322 newArray[0.._length] = array[from..from+_length]; | |
323 return new ArraySeq!(T)(screener, newArray, _length); | |
324 } | |
325 else | |
326 return new ArraySeq!(T)(screener); | |
327 } | |
328 | |
329 | |
330 // MutableCollection methods | |
331 | |
332 /** | |
333 * Implements tango.util.collection.impl.Collection.Collection.clear. | |
334 * Time complexity: O(1). | |
335 * See_Also: tango.util.collection.impl.Collection.Collection.clear | |
336 **/ | |
337 public final void clear() | |
338 { | |
339 array = null; | |
340 setCount(0); | |
341 } | |
342 | |
343 /** | |
344 * Implements tango.util.collection.impl.Collection.Collection.removeOneOf. | |
345 * Time complexity: O(n). | |
346 * See_Also: tango.util.collection.impl.Collection.Collection.removeOneOf | |
347 **/ | |
348 public final void remove(T element) | |
349 { | |
350 remove_(element, false); | |
351 } | |
352 | |
353 | |
354 /** | |
355 * Implements tango.util.collection.impl.Collection.Collection.replaceOneOf | |
356 * Time complexity: O(n). | |
357 * See_Also: tango.util.collection.impl.Collection.Collection.replaceOneOf | |
358 **/ | |
359 public final void replace(T oldElement, T newElement) | |
360 { | |
361 replace_(oldElement, newElement, false); | |
362 } | |
363 | |
364 /** | |
365 * Implements tango.util.collection.impl.Collection.Collection.replaceAllOf. | |
366 * Time complexity: O(n * number of replacements). | |
367 * See_Also: tango.util.collection.impl.Collection.Collection.replaceAllOf | |
368 **/ | |
369 public final void replaceAll(T oldElement, T newElement) | |
370 { | |
371 replace_(oldElement, newElement, true); | |
372 } | |
373 | |
374 /** | |
375 * Implements tango.util.collection.impl.Collection.Collection.exclude. | |
376 * Time complexity: O(n * instances(element)). | |
377 * See_Also: tango.util.collection.impl.Collection.Collection.exclude | |
378 **/ | |
379 public final void removeAll(T element) | |
380 { | |
381 remove_(element, true); | |
382 } | |
383 | |
384 /** | |
385 * Implements tango.util.collection.impl.Collection.Collection.take. | |
386 * Time complexity: O(1). | |
387 * Takes the rightmost element of the array. | |
388 * See_Also: tango.util.collection.impl.Collection.Collection.take | |
389 **/ | |
390 public final T take() | |
391 { | |
392 T v = tail(); | |
393 removeTail(); | |
394 return v; | |
395 } | |
396 | |
397 | |
398 // SortableCollection methods: | |
399 | |
400 | |
401 /** | |
402 * Implements tango.util.collection.SortableCollection.sort. | |
403 * Time complexity: O(n log n). | |
404 * Uses a quicksort-based algorithm. | |
405 * See_Also: tango.util.collection.SortableCollection.sort | |
406 **/ | |
407 public void sort(Comparator!(T) cmp) | |
408 { | |
409 if (count > 0) | |
410 { | |
411 quickSort(array, 0, count - 1, cmp); | |
412 incVersion(); | |
413 } | |
414 } | |
415 | |
416 | |
417 // MutableSeq methods | |
418 | |
419 /** | |
420 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.prepend. | |
421 * Time complexity: O(n) | |
422 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.prepend | |
423 **/ | |
424 public final void prepend(T element) | |
425 { | |
426 checkElement(element); | |
427 growBy_(1); | |
428 for (int i = count -1; i > 0; --i) | |
429 array[i] = array[i - 1]; | |
430 array[0] = element; | |
431 } | |
432 | |
433 /** | |
434 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.replaceHead. | |
435 * Time complexity: O(1). | |
436 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.replaceHead | |
437 **/ | |
438 public final void replaceHead(T element) | |
439 { | |
440 checkElement(element); | |
441 array[0] = element; | |
442 incVersion(); | |
443 } | |
444 | |
445 /** | |
446 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.removeHead. | |
447 * Time complexity: O(n). | |
448 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.removeHead | |
449 **/ | |
450 public final void removeHead() | |
451 { | |
452 removeAt(0); | |
453 } | |
454 | |
455 /** | |
456 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.append. | |
457 * Time complexity: normally O(1), but O(n) if size() == capacity(). | |
458 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.append | |
459 **/ | |
460 public final void append(T element) | |
461 in { | |
462 checkElement (element); | |
463 } | |
464 body | |
465 { | |
466 int last = count; | |
467 growBy_(1); | |
468 array[last] = element; | |
469 } | |
470 | |
471 /** | |
472 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.replaceTail. | |
473 * Time complexity: O(1). | |
474 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.replaceTail | |
475 **/ | |
476 public final void replaceTail(T element) | |
477 { | |
478 checkElement(element); | |
479 array[count -1] = element; | |
480 incVersion(); | |
481 } | |
482 | |
483 /** | |
484 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.removeTail. | |
485 * Time complexity: O(1). | |
486 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.removeTail | |
487 **/ | |
488 public final void removeTail() | |
489 { | |
490 checkIndex(0); | |
491 array[count -1] = T.init; | |
492 growBy_( -1); | |
493 } | |
494 | |
495 /** | |
496 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.addAt. | |
497 * Time complexity: O(n). | |
498 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.addAt | |
499 **/ | |
500 public final void addAt(int index, T element) | |
501 { | |
502 if (index !is count) | |
503 checkIndex(index); | |
504 | |
505 checkElement(element); | |
506 growBy_(1); | |
507 for (int i = count -1; i > index; --i) | |
508 array[i] = array[i - 1]; | |
509 array[index] = element; | |
510 } | |
511 | |
512 /** | |
513 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.remove. | |
514 * Time complexity: O(n). | |
515 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.removeAt | |
516 **/ | |
517 public final void removeAt(int index) | |
518 { | |
519 checkIndex(index); | |
520 for (int i = index + 1; i < count; ++i) | |
521 array[i - 1] = array[i]; | |
522 array[count -1] = T.init; | |
523 growBy_( -1); | |
524 } | |
525 | |
526 | |
527 /** | |
528 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.replaceAt. | |
529 * Time complexity: O(1). | |
530 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.replaceAt | |
531 **/ | |
532 public final void replaceAt(int index, T element) | |
533 { | |
534 checkIndex(index); | |
535 checkElement(element); | |
536 array[index] = element; | |
537 incVersion(); | |
538 } | |
539 | |
540 /** | |
541 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.prepend. | |
542 * Time complexity: O(n + number of elements in e) if (e | |
543 * instanceof CollectionIterator) else O(n * number of elements in e) | |
544 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.prepend | |
545 **/ | |
546 public final void prepend(Iterator!(T) e) | |
547 { | |
548 insert_(0, e); | |
549 } | |
550 | |
551 /** | |
552 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.append. | |
553 * Time complexity: O(number of elements in e) | |
554 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.append | |
555 **/ | |
556 public final void append(Iterator!(T) e) | |
557 { | |
558 insert_(count, e); | |
559 } | |
560 | |
561 /** | |
562 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.addAt. | |
563 * Time complexity: O(n + number of elements in e) if (e | |
564 * instanceof CollectionIterator) else O(n * number of elements in e) | |
565 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.addAt | |
566 **/ | |
567 public final void addAt(int index, Iterator!(T) e) | |
568 { | |
569 if (index !is count) | |
570 checkIndex(index); | |
571 insert_(index, e); | |
572 } | |
573 | |
574 | |
575 /** | |
576 * Implements tango.util.collection.impl.SeqCollection.SeqCollection.removeFromTo. | |
577 * Time complexity: O(n). | |
578 * See_Also: tango.util.collection.impl.SeqCollection.SeqCollection.removeFromTo | |
579 **/ | |
580 public final void removeRange (int fromIndex, int toIndex) | |
581 { | |
582 checkIndex(fromIndex); | |
583 checkIndex(toIndex); | |
584 if (fromIndex <= toIndex) | |
585 { | |
586 int gap = toIndex - fromIndex + 1; | |
587 int j = fromIndex; | |
588 for (int i = toIndex + 1; i < count; ++i) | |
589 array[j++] = array[i]; | |
590 | |
591 for (int i = 1; i <= gap; ++i) | |
592 array[count -i] = T.init; | |
593 addToCount( -gap); | |
594 } | |
595 } | |
596 | |
597 /** | |
598 * An implementation of Quicksort using medians of 3 for partitions. | |
599 * Used internally by sort. | |
600 * It is public and static so it can be used to sort plain | |
601 * arrays as well. | |
602 * @param s, the array to sort | |
603 * @param lo, the least index to sort from | |
604 * @param hi, the greatest index | |
605 * @param cmp, the comparator to use for comparing elements | |
606 **/ | |
607 | |
608 public final static void quickSort(T s[], int lo, int hi, Comparator!(T) cmp) | |
609 { | |
610 if (lo >= hi) | |
611 return; | |
612 | |
613 /* | |
614 Use median-of-three(lo, mid, hi) to pick a partition. | |
615 Also swap them into relative order while we are at it. | |
616 */ | |
617 | |
618 int mid = (lo + hi) / 2; | |
619 | |
620 if (cmp.compare(s[lo], s[mid]) > 0) | |
621 { | |
622 T tmp = s[lo]; | |
623 s[lo] = s[mid]; | |
624 s[mid] = tmp; // swap | |
625 } | |
626 | |
627 if (cmp.compare(s[mid], s[hi]) > 0) | |
628 { | |
629 T tmp = s[mid]; | |
630 s[mid] = s[hi]; | |
631 s[hi] = tmp; // swap | |
632 | |
633 if (cmp.compare(s[lo], s[mid]) > 0) | |
634 { | |
635 T tmp2 = s[lo]; | |
636 s[lo] = s[mid]; | |
637 s[mid] = tmp2; // swap | |
638 } | |
639 } | |
640 | |
641 int left = lo + 1; // start one past lo since already handled lo | |
642 int right = hi - 1; // similarly | |
643 if (left >= right) | |
644 return; // if three or fewer we are done | |
645 | |
646 T partition = s[mid]; | |
647 | |
648 for (;;) | |
649 { | |
650 while (cmp.compare(s[right], partition) > 0) | |
651 --right; | |
652 | |
653 while (left < right && cmp.compare(s[left], partition) <= 0) | |
654 ++left; | |
655 | |
656 if (left < right) | |
657 { | |
658 T tmp = s[left]; | |
659 s[left] = s[right]; | |
660 s[right] = tmp; // swap | |
661 --right; | |
662 } | |
663 else | |
664 break; | |
665 } | |
666 | |
667 quickSort(s, lo, left, cmp); | |
668 quickSort(s, left + 1, hi, cmp); | |
669 } | |
670 | |
671 /*********************************************************************** | |
672 | |
673 expose collection content as an array | |
674 | |
675 ************************************************************************/ | |
676 | |
677 override public T[] toArray () | |
678 { | |
679 return array[0..count].dup; | |
680 } | |
681 | |
682 // helper methods | |
683 | |
684 /** | |
685 * Main method to control buffer sizing. | |
686 * The heuristic used for growth is: | |
687 * <PRE> | |
688 * if out of space: | |
689 * if need less than minCapacity, grow to minCapacity | |
690 * else grow by average of requested size and minCapacity. | |
691 * </PRE> | |
692 * <P> | |
693 * For small buffers, this causes them to be about 1/2 full. | |
694 * while for large buffers, it causes them to be about 2/3 full. | |
695 * <P> | |
696 * For shrinkage, the only thing we do is unlink the buffer if it is empty. | |
697 * @param inc, the amount of space to grow by. Negative values mean shrink. | |
698 * Returns: condition: adjust record of count, and if any of | |
699 * the above conditions apply, allocate and copy into a new | |
700 * buffer of the appropriate size. | |
701 **/ | |
702 | |
703 private final void growBy_(int inc) | |
704 { | |
705 int needed = count + inc; | |
706 if (inc > 0) | |
707 { | |
708 /* heuristic: */ | |
709 int current = capacity(); | |
710 if (needed > current) | |
711 { | |
712 incVersion(); | |
713 int newCap = needed + (needed + minCapacity) / 2; | |
714 | |
715 if (newCap < minCapacity) | |
716 newCap = minCapacity; | |
717 | |
718 if (array is null) | |
719 { | |
720 array = new T[newCap]; | |
721 } | |
722 else | |
723 { | |
724 //T newArray[] = new T[newCap]; | |
725 //newArray[0..count] = array[0..count]; | |
726 //array = newArray; | |
727 array ~= new T[newCap - array.length]; | |
728 } | |
729 } | |
730 } | |
731 else | |
732 if (needed is 0) | |
733 array = null; | |
734 | |
735 setCount(needed); | |
736 } | |
737 | |
738 | |
739 /** | |
740 * Utility to splice in enumerations | |
741 **/ | |
742 | |
743 private final void insert_(int index, Iterator!(T) e) | |
744 { | |
745 if (cast(GuardIterator!(T)) e) | |
746 { | |
747 // we know size! | |
748 int inc = (cast(GuardIterator!(T)) (e)).remaining(); | |
749 int oldcount = count; | |
750 int oldversion = vershion; | |
751 growBy_(inc); | |
752 | |
753 for (int i = oldcount - 1; i >= index; --i) | |
754 array[i + inc] = array[i]; | |
755 | |
756 int j = index; | |
757 while (e.more()) | |
758 { | |
759 T element = e.get(); | |
760 if (!allows (element)) | |
761 { // Ugh. Can only do full rollback | |
762 for (int i = index; i < oldcount; ++i) | |
763 array[i] = array[i + inc]; | |
764 | |
765 vershion = oldversion; | |
766 count = oldcount; | |
767 checkElement(element); // force throw | |
768 } | |
769 array[j++] = element; | |
770 } | |
771 } | |
772 else | |
773 if (index is count) | |
774 { // next best; we can append | |
775 while (e.more()) | |
776 { | |
777 T element = e.get(); | |
778 checkElement(element); | |
779 growBy_(1); | |
780 array[count -1] = element; | |
781 } | |
782 } | |
783 else | |
784 { // do it the slow way | |
785 int j = index; | |
786 while (e.more()) | |
787 { | |
788 T element = e.get(); | |
789 checkElement(element); | |
790 growBy_(1); | |
791 | |
792 for (int i = count -1; i > j; --i) | |
793 array[i] = array[i - 1]; | |
794 array[j++] = element; | |
795 } | |
796 } | |
797 } | |
798 | |
799 private final void remove_(T element, bool allOccurrences) | |
800 { | |
801 if (! isValidArg(element)) | |
802 return; | |
803 | |
804 for (int i = 0; i < count; ++i) | |
805 { | |
806 while (i < count && array[i] == (element)) | |
807 { | |
808 for (int j = i + 1; j < count; ++j) | |
809 array[j - 1] = array[j]; | |
810 | |
811 array[count -1] = T.init; | |
812 growBy_( -1); | |
813 | |
814 if (!allOccurrences || count is 0) | |
815 return ; | |
816 } | |
817 } | |
818 } | |
819 | |
820 private final void replace_(T oldElement, T newElement, bool allOccurrences) | |
821 { | |
822 if (isValidArg(oldElement) is false || count is 0) | |
823 return; | |
824 | |
825 for (int i = 0; i < count; ++i) | |
826 { | |
827 if (array[i] == (oldElement)) | |
828 { | |
829 checkElement(newElement); | |
830 array[i] = newElement; | |
831 incVersion(); | |
832 | |
833 if (! allOccurrences) | |
834 return; | |
835 } | |
836 } | |
837 } | |
838 | |
839 /** | |
840 * Implements tango.util.collection.model.View.View.checkImplementation. | |
841 * See_Also: tango.util.collection.model.View.View.checkImplementation | |
842 **/ | |
843 public override void checkImplementation() | |
844 { | |
845 super.checkImplementation(); | |
846 assert(!(array is null && count !is 0)); | |
847 assert((array is null || count <= array.length)); | |
848 | |
849 for (int i = 0; i < count; ++i) | |
850 { | |
851 assert(allows(array[i])); | |
852 assert(instances(array[i]) > 0); | |
853 assert(contains(array[i])); | |
854 } | |
855 } | |
856 | |
857 /*********************************************************************** | |
858 | |
859 opApply() has migrated here to mitigate the virtual call | |
860 on method get() | |
861 | |
862 ************************************************************************/ | |
863 | |
864 static class ArrayIterator(T) : AbstractIterator!(T) | |
865 { | |
866 private int row; | |
867 private T[] array; | |
868 | |
869 public this (ArraySeq seq) | |
870 { | |
871 super (seq); | |
872 array = seq.array; | |
873 } | |
874 | |
875 public final T get() | |
876 { | |
877 decRemaining(); | |
878 return array[row++]; | |
879 } | |
880 | |
881 int opApply (int delegate (inout T value) dg) | |
882 { | |
883 int result; | |
884 | |
885 for (auto i=remaining(); i--;) | |
886 { | |
887 auto value = get(); | |
888 if ((result = dg(value)) != 0) | |
889 break; | |
890 } | |
891 return result; | |
892 } | |
893 } | |
894 } | |
895 | |
896 | |
897 | |
898 debug (Test) | |
899 { | |
900 import tango.io.Console; | |
901 | |
902 void main() | |
903 { | |
904 auto array = new ArraySeq!(char[]); | |
905 array.append ("foo"); | |
906 array.append ("bar"); | |
907 array.append ("wumpus"); | |
908 | |
909 foreach (value; array.elements) {} | |
910 | |
911 auto elements = array.elements(); | |
912 while (elements.more) | |
913 auto v = elements.get(); | |
914 | |
915 foreach (value; array) | |
916 Cout (value).newline; | |
917 | |
918 auto a = array.toArray; | |
919 foreach (value; a) | |
920 Cout (value).newline; | |
921 | |
922 array.checkImplementation(); | |
923 } | |
924 } |