Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #553: LineIteratorEnhanced.d

File LineIteratorEnhanced.d, 5.9 kB (added by Nietsnie, 1 year ago)

Example LineIterator? with above features.

Line 
1 module tango.io.LineIteratorEnhanced;
2
3 public  import tango.io.Buffer;
4 private import Text = tango.text.Util;
5 private import tango.util.collection.CircularSeq;
6
7 class LineIteratorEnhanced(T)
8 {
9
10     protected T[]           slice,
11                             pushed;
12     protected IBuffer       buffer;
13     private long            _position = 0,
14                             _pushLength = 0;
15
16
17     this (InputStream stream = null)
18     {
19         if (stream)
20             set(stream);
21     }
22
23     final LineIteratorEnhanced set (InputStream stream)
24     {
25         auto b = cast(IBuffer) stream;
26         if (b)
27             buffer = b;
28         else
29             if (buffer)
30                 buffer.clear, buffer.setConduit (stream.conduit);
31             else
32                 buffer = new Buffer (stream.conduit);
33
34         this._position = 0;
35
36         return this;
37     }
38
39     /***********************************************************************
40
41       Resets the iterator using the passed stream
42
43      ***********************************************************************/
44
45     void reset(InputStream stream, long newPosition = -1)
46     {
47         this.buffer.clear;
48         this.buffer.setConduit(stream.conduit);
49         this.pushed = null;
50         this._pushLength = 0;
51         if (newPosition >= 0)
52             this._position = newPosition;
53     }
54
55
56     /***********************************************************************
57
58       Return the size of data read so far
59
60      ***********************************************************************/
61     final uint position()
62     {
63         return this._position;
64     }
65
66     /***********************************************************************
67
68       Return the current token as a slice of the content
69
70      ***********************************************************************/
71
72     final T[] get ()
73     {
74         return slice;
75     }
76
77     /***********************************************************************
78
79       Push one token back into the stream, to be returned by a
80       subsequent call to next()
81
82       Push null to cancel a prior assignment
83
84      ***********************************************************************/
85     final LineIteratorEnhanced push(T[] token, long previousPosition = -1)
86     {
87         pushed = token;
88         if (token is null)
89         {
90             if (pushed.ptr)
91                 this._position += this._pushLength;
92         }
93         else       
94         {
95             pushed = token;
96             if (previousPosition >= 0)
97             {
98                 this._pushLength = this._position - previousPosition;
99                 this._position = previousPosition;
100                 if (this._position < 0)
101                     this._position = 0;
102             }
103         }
104        
105         return this;
106     }
107
108     /**********************************************************************
109
110       Iterate over the set of tokens. This should really
111       provide read-only access to the tokens, but D does
112       not support that at this time
113
114      **********************************************************************/
115
116     int opApply (int delegate(inout T[]) dg)
117     {
118         T[]     token;
119         int     result;
120
121         while ((token = next).ptr)
122         {
123             result = dg (token);
124             if (result)
125                 break;
126         }
127         return result;
128     }
129
130     /***********************************************************************
131
132       Locate the next token. Returns the token if found, null
133       otherwise. Null indicates an end of stream condition. To
134       sweep a conduit for lines using method next():
135       ---
136       auto lines = new LineIterator!(char) (new FileConduit("myfile"));
137       while (lines.next)
138       Cout (lines.get).newline;
139       ---
140
141       Alternatively, we can extract one line from a conduit:
142       ---
143       auto line = (new LineIterator!(char) (new FileConduit("myfile"))).next;
144       ---
145
146       The difference between next() and foreach() is that the
147       latter processes all tokens in one go, whereas the former
148       processes in a piecemeal fashion. To wit:
149       ---
150       foreach (line; new LineIterator!(char) (new FileConduit("myfile"))
151       Cout(line).newline;
152       ---
153
154       Note that tokens returned via push() are returned immediately
155       when available, taking priority over the input stream itself
156
157      ***********************************************************************/
158
159     final T[] next ()
160     {
161         T[] rtn = pushed;
162
163         if (rtn.ptr)
164         {
165             this._position += this._pushLength;
166             pushed = null;
167         }
168         else
169             if (buffer.next (&scan) || slice.length > 0)
170                 rtn = get ();
171
172         return rtn;
173     }
174
175     /***********************************************************************
176
177       Set the content of the current slice
178
179      ***********************************************************************/
180
181     protected final uint set (T* content, uint start, uint end)
182     {
183         slice = content [start .. end];
184         return end;
185     }
186
187     /***********************************************************************
188
189       Convert void[] from buffer into an appropriate array
190
191      ***********************************************************************/
192
193     protected final T[] convert (void[] data)
194     {
195         return cast(T[]) data [0 .. data.length & ~(T.sizeof-1)];
196     }
197
198     /***********************************************************************
199
200       Called when a scanner fails to find a matching pattern.
201       This may cause more content to be loaded, and a rescan
202       initiated
203      ***********************************************************************/
204
205     protected final uint notFound (T[] content)
206     {
207         slice = content;
208         return IConduit.Eof;
209     }
210
211     /***********************************************************************
212
213       Invoked when a scanner matches a pattern. The provided
214       value should be the index of the last element of the
215       matching pattern, which is converted back to a void[]
216       index.
217
218      ***********************************************************************/
219
220     protected final uint found (uint i)
221     {
222         return (i + 1) * T.sizeof;
223     }
224
225     /***********************************************************************
226
227       See if set of characters holds a particular instance
228
229      ***********************************************************************/
230
231     protected final bool has (T[] set, T match)
232     {
233         foreach (T c; set)
234             if (match is c)
235                 return true;
236         return false;
237     }
238
239     protected uint scan(void[] data)
240     {
241         T[] content = convert (data);
242
243         foreach (int i, T c; content)
244             if (c is '\n')
245             {
246                 this._position += i+1;
247                 int slice = i;
248                 if (i && content[i-1] is '\r')
249                     --slice;
250                 set (content.ptr, 0, slice);
251                 return found (i);
252             }
253
254         return notFound (content);
255
256     }
257 }