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

Ticket #970: LineIterator.d

File LineIterator.d, 4.9 kB (added by Daniel919, 6 months ago)
Line 
1 /*******************************************************************************
2
3         copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
4
5         license:        BSD style: $(LICENSE)
6
7         version:        Initial release: January 2006     
8         
9         author:         Kris
10
11 *******************************************************************************/
12
13 module tango.text.stream.LineIterator;
14
15 private import  tango.text.stream.StreamIterator;
16
17 /*******************************************************************************
18
19         Iterate across a set of text patterns.
20
21         Each pattern is exposed to the client as a slice of the original
22         content, where the slice is transient. If you need to retain the
23         exposed content, then you should .dup it appropriately.
24
25         These iterators are based upon the IBuffer construct, and can
26         thus be used in conjunction with other Iterators and/or Reader
27         instances upon a common buffer ~ each will stay in lockstep via
28         state maintained within the IBuffer.
29
30         The content exposed via an iterator is supposed to be entirely
31         read-only. All current iterators abide by this rule, but it is
32         possible a user could mutate the content through a get() slice.
33         To enforce the desired read-only aspect, the code would have to
34         introduce redundant copying or the compiler would have to support
35         read-only arrays.
36
37         See LineIterator, SimpleIterator, RegexIterator, QuotedIterator.
38
39
40 *******************************************************************************/
41
42 class LineIterator(T) : StreamIterator!(T)
43 {
44         private T[] delim;
45
46         /***********************************************************************
47         
48                 Construct an uninitialized iterator. For example:
49                 ---
50                 auto lines = new LineIterator!(char);
51
52                 void somefunc (IBuffer buffer)
53                 {
54                         foreach (line; lines.set(buffer))
55                                  Cout (line).newline;
56                 }
57                 ---
58
59                 Construct a streaming iterator upon a buffer:
60                 ---
61                 void somefunc (IBuffer buffer)
62                 {
63                         foreach (line; new LineIterator!(char) (buffer))
64                                  Cout (line).newline;
65                 }
66                 ---
67                 
68                 Construct a streaming iterator upon a conduit:
69                 ---
70                 foreach (line; new LineIterator!(char) (new FileConduit ("myfile")))
71                          Cout (line).newline;
72                 ---
73
74         ***********************************************************************/
75
76         this (InputStream stream = null)
77         {
78                 super (stream);
79         }
80
81         /***********************************************************************
82
83                 Read a line of text, and return false when there's no
84                 further content available.
85
86         ***********************************************************************/
87
88         final bool readln (inout T[] content)
89         {
90                 content = super.next;
91                 return content.ptr !is null;
92         }
93
94         /**********************************************************************
95
96                 Iterate over a set of tokens, exposing the next delimiter
97
98         **********************************************************************/
99
100         int opApply (int delegate(inout T[], inout T[]) dg)
101         {
102                 bool more;
103                 int  result;
104
105                 do {
106                    delim.length = 0;
107                    more = consume; //delim is set as a sideeffect
108                    result = dg (slice, delim);
109                    } while (more && !result);
110                 return result;
111         }
112
113         /***********************************************************************
114         
115                 Scanner implementation for this iterator. Find a '\n',
116                 and eat any immediately preceeding '\r'
117                 
118         ***********************************************************************/
119
120         protected uint scan (void[] data)
121         {
122                 auto content = (cast(T*) data.ptr) [0 .. data.length / T.sizeof];
123
124                 foreach (int i, T c; content)
125                          if (c is '\n')
126                             {
127                             int slice = i;
128                             if (i && content[i-1] is '\r') {
129                                 delim = "\r\n";
130                                 --slice;
131                             } else {
132                             delim = "\n";
133                         }
134                             set (content.ptr, 0, slice);
135                             return found (i);
136                             }
137
138                 return notFound;
139         }
140 }