132
|
1 /*
|
|
2 File: InterleavingIterator.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 22Oct95 dl@cs.oswego.edu Created.
|
|
11
|
|
12 */
|
|
13
|
|
14
|
|
15 module tango.util.collection.iterator.InterleavingIterator;
|
|
16
|
|
17 private import tango.core.Exception;
|
|
18
|
|
19 private import tango.util.collection.model.Iterator;
|
|
20
|
|
21 /**
|
|
22 *
|
|
23 * InterleavingIterators allow you to combine the elements
|
|
24 * of two different enumerations as if they were one enumeration
|
|
25 * before they are seen by their `consumers'.
|
|
26 * This sometimes allows you to avoid having to use a
|
|
27 * Collection object to temporarily combine two sets of Collection elements()
|
|
28 * that need to be collected together for common processing.
|
|
29 * <P>
|
|
30 * The elements are revealed (via get()) in a purely
|
|
31 * interleaved fashion, alternating between the first and second
|
|
32 * enumerations unless one of them has been exhausted, in which case
|
|
33 * all remaining elements of the other are revealed until it too is
|
|
34 * exhausted.
|
|
35 * <P>
|
|
36 * InterleavingIterators work as wrappers around other Iterators.
|
|
37 * To build one, you need two existing Iterators.
|
|
38 * For example, if you want to process together the elements of
|
|
39 * two Collections a and b, you could write something of the form:
|
|
40 * <PRE>
|
|
41 * Iterator items = InterleavingIterator(a.elements(), b.elements());
|
|
42 * while (items.more())
|
|
43 * doSomethingWith(items.get());
|
|
44 * </PRE>
|
|
45 *
|
|
46 author: Doug Lea
|
|
47 * @version 0.93
|
|
48 *
|
|
49 * <P> For an introduction to this package see <A HREF="index.html"> Overview </A>.
|
|
50 *
|
|
51 **/
|
|
52
|
|
53
|
|
54 public class InterleavingIterator(T) : Iterator!(T)
|
|
55 {
|
|
56
|
|
57 /**
|
|
58 * The first source; nulled out once it is exhausted
|
|
59 **/
|
|
60
|
|
61 private Iterator!(T) fst_;
|
|
62
|
|
63 /**
|
|
64 * The second source; nulled out once it is exhausted
|
|
65 **/
|
|
66
|
|
67 private Iterator!(T) snd_;
|
|
68
|
|
69 /**
|
|
70 * The source currently being used
|
|
71 **/
|
|
72
|
|
73 private Iterator!(T) current_;
|
|
74
|
|
75
|
|
76
|
|
77 /**
|
|
78 * Make an enumeration interleaving elements from fst and snd
|
|
79 **/
|
|
80
|
|
81 public this (Iterator!(T) fst, Iterator!(T) snd)
|
|
82 {
|
|
83 fst_ = fst;
|
|
84 snd_ = snd;
|
|
85 current_ = snd_; // flip will reset to fst (if it can)
|
|
86 flip();
|
|
87 }
|
|
88
|
|
89 /**
|
|
90 * Implements java.util.Iterator.more
|
|
91 **/
|
|
92 public final bool more()
|
|
93 {
|
|
94 return current_ !is null;
|
|
95 }
|
|
96
|
|
97 /**
|
|
98 * Implements java.util.Iterator.get.
|
|
99 **/
|
|
100 public final T get()
|
|
101 {
|
|
102 if (current_ is null)
|
|
103 throw new NoSuchElementException("exhausted iterator");
|
|
104 else
|
|
105 {
|
|
106 // following line may also throw ex, but there's nothing
|
|
107 // reasonable to do except propagate
|
|
108 auto result = current_.get();
|
|
109 flip();
|
|
110 return result;
|
|
111 }
|
|
112 }
|
|
113
|
|
114
|
|
115 int opApply (int delegate (inout T value) dg)
|
|
116 {
|
|
117 int result;
|
|
118
|
|
119 while (current_)
|
|
120 {
|
|
121 auto value = get();
|
|
122 if ((result = dg(value)) != 0)
|
|
123 break;
|
|
124 }
|
|
125 return result;
|
|
126 }
|
|
127
|
|
128 /**
|
|
129 * Alternate sources
|
|
130 **/
|
|
131
|
|
132 private final void flip()
|
|
133 {
|
|
134 if (current_ is fst_)
|
|
135 {
|
|
136 if (snd_ !is null && !snd_.more())
|
|
137 snd_ = null;
|
|
138 if (snd_ !is null)
|
|
139 current_ = snd_;
|
|
140 else
|
|
141 {
|
|
142 if (fst_ !is null && !fst_.more())
|
|
143 fst_ = null;
|
|
144 current_ = fst_;
|
|
145 }
|
|
146 }
|
|
147 else
|
|
148 {
|
|
149 if (fst_ !is null && !fst_.more())
|
|
150 fst_ = null;
|
|
151 if (fst_ !is null)
|
|
152 current_ = fst_;
|
|
153 else
|
|
154 {
|
|
155 if (snd_ !is null && !snd_.more())
|
|
156 snd_ = null;
|
|
157 current_ = snd_;
|
|
158 }
|
|
159 }
|
|
160 }
|
|
161
|
|
162
|
|
163 }
|
|
164
|