132
|
1 /*
|
|
2 File: FilteringIterator.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.FilteringIterator;
|
|
16
|
|
17 private import tango.core.Exception;
|
|
18
|
|
19 private import tango.util.collection.model.Iterator;
|
|
20
|
|
21 /**
|
|
22 *
|
|
23 * FilteringIterators allow you to filter out elements from
|
|
24 * other enumerations before they are seen by their `consumers'
|
|
25 * (i.e., the callers of `get').
|
|
26 *
|
|
27 * FilteringIterators work as wrappers around other Iterators.
|
|
28 * To build one, you need an existing Iterator (perhaps one
|
|
29 * from coll.elements(), for some Collection coll), and a Predicate
|
|
30 * object (i.e., implementing interface Predicate).
|
|
31 * For example, if you want to screen out everything but Panel
|
|
32 * objects from a collection coll that might hold things other than Panels,
|
|
33 * write something of the form:
|
|
34 * ---
|
|
35 * Iterator e = coll.elements();
|
|
36 * Iterator panels = FilteringIterator(e, IsPanel);
|
|
37 * while (panels.more())
|
|
38 * doSomethingWith(cast(Panel)(panels.get()));
|
|
39 * ---
|
|
40 * To use this, you will also need to write a little class of the form:
|
|
41 * ---
|
|
42 * class IsPanel : Predicate {
|
|
43 * bool predicate(Object v) { return ( 0 !is cast(Panel)v; }
|
|
44 * }
|
|
45 * ---
|
|
46 * See_Also: tango.util.collection.Predicate.predicate
|
|
47 * author: Doug Lea
|
|
48 *
|
|
49 **/
|
|
50
|
|
51 public class FilteringIterator(T) : Iterator!(T)
|
|
52 {
|
|
53 alias bool delegate(T) Predicate;
|
|
54
|
|
55 // instance variables
|
|
56
|
|
57 /**
|
|
58 * The enumeration we are wrapping
|
|
59 **/
|
|
60
|
|
61 private Iterator!(T) src_;
|
|
62
|
|
63 /**
|
|
64 * The screening predicate
|
|
65 **/
|
|
66
|
|
67 private Predicate pred_;
|
|
68
|
|
69 /**
|
|
70 * The sense of the predicate. False means to invert
|
|
71 **/
|
|
72
|
|
73 private bool sign_;
|
|
74
|
|
75 /**
|
|
76 * The next element to hand out
|
|
77 **/
|
|
78
|
|
79 private T get_;
|
|
80
|
|
81 /**
|
|
82 * True if we have a next element
|
|
83 **/
|
|
84
|
|
85 private bool haveNext_;
|
|
86
|
|
87 /**
|
|
88 * Make a Filter using src for the elements, and p as the screener,
|
|
89 * selecting only those elements of src for which p is true
|
|
90 **/
|
|
91
|
|
92 public this (Iterator!(T) src, Predicate p)
|
|
93 {
|
|
94 this(src, p, true);
|
|
95 }
|
|
96
|
|
97 /**
|
|
98 * Make a Filter using src for the elements, and p as the screener,
|
|
99 * selecting only those elements of src for which p.predicate(v) == sense.
|
|
100 * A value of true for sense selects only values for which p.predicate
|
|
101 * is true. A value of false selects only those for which it is false.
|
|
102 **/
|
|
103 public this (Iterator!(T) src, Predicate p, bool sense)
|
|
104 {
|
|
105 src_ = src;
|
|
106 pred_ = p;
|
|
107 sign_ = sense;
|
|
108 findNext();
|
|
109 }
|
|
110
|
|
111 /**
|
|
112 * Implements java.util.Iterator.more
|
|
113 **/
|
|
114
|
|
115 public final bool more()
|
|
116 {
|
|
117 return haveNext_;
|
|
118 }
|
|
119
|
|
120 /**
|
|
121 * Implements java.util.Iterator.get.
|
|
122 **/
|
|
123 public final T get()
|
|
124 {
|
|
125 if (! haveNext_)
|
|
126 throw new NoSuchElementException("exhausted enumeration");
|
|
127 else
|
|
128 {
|
|
129 auto result = get_;
|
|
130 findNext();
|
|
131 return result;
|
|
132 }
|
|
133 }
|
|
134
|
|
135
|
|
136 int opApply (int delegate (inout T value) dg)
|
|
137 {
|
|
138 int result;
|
|
139
|
|
140 while (haveNext_)
|
|
141 {
|
|
142 auto value = get();
|
|
143 if ((result = dg(value)) != 0)
|
|
144 break;
|
|
145 }
|
|
146 return result;
|
|
147 }
|
|
148
|
|
149
|
|
150 /**
|
|
151 * Traverse through src_ elements finding one passing predicate
|
|
152 **/
|
|
153 private final void findNext()
|
|
154 {
|
|
155 haveNext_ = false;
|
|
156
|
|
157 for (;;)
|
|
158 {
|
|
159 if (! src_.more())
|
|
160 return ;
|
|
161 else
|
|
162 {
|
|
163 try {
|
|
164 auto v = src_.get();
|
|
165 if (pred_(v) is sign_)
|
|
166 {
|
|
167 haveNext_ = true;
|
|
168 get_ = v;
|
|
169 return;
|
|
170 }
|
|
171 } catch (NoSuchElementException ex)
|
|
172 {
|
|
173 return;
|
|
174 }
|
|
175 }
|
|
176 }
|
|
177 }
|
|
178 }
|
|
179
|