132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: Initial release: March 2004
|
|
8
|
|
9 author: Kris
|
|
10
|
|
11 *******************************************************************************/
|
|
12
|
|
13 module tango.io.Conduit;
|
|
14
|
|
15 private import tango.core.Exception;
|
|
16
|
|
17 public import tango.io.model.IConduit;
|
|
18
|
|
19 /*******************************************************************************
|
|
20
|
|
21 Conduit abstract base-class, implementing interface IConduit.
|
|
22 Only the conduit-specific read(), write(), fileHandle() and
|
|
23 bufferSize() need to be implemented for a concrete conduit
|
|
24 implementation. See FileConduit for an example.
|
|
25
|
|
26 Conduits provide virtualized access to external content, and
|
|
27 represent things like files or Internet connections. Conduits
|
|
28 expose a pair of streams, are modelled by tango.io.model.IConduit,
|
|
29 and are implemented via classes such as FileConduit & SocketConduit.
|
|
30
|
|
31 Additional kinds of conduit are easy to construct: one either
|
|
32 subclasses tango.io.Conduit, or implements tango.io.model.IConduit.
|
|
33 A conduit typically reads and writes from/to an IBuffer in large
|
|
34 chunks, typically the entire buffer. Alternatively, one can invoke
|
|
35 input.read(dst[]) and/or output.write(src[]) directly.
|
|
36
|
|
37 *******************************************************************************/
|
|
38
|
|
39 class Conduit : IConduit, ISelectable
|
|
40 {
|
|
41 /***********************************************************************
|
|
42
|
|
43 Return the name of this conduit
|
|
44
|
|
45 ***********************************************************************/
|
|
46
|
|
47 abstract char[] toString ();
|
|
48
|
|
49 /***********************************************************************
|
|
50
|
|
51 Return a preferred size for buffering conduit I/O
|
|
52
|
|
53 ***********************************************************************/
|
|
54
|
|
55 abstract uint bufferSize ();
|
|
56
|
|
57 /***********************************************************************
|
|
58
|
|
59 Models a handle-oriented device. We need to revisit this
|
|
60
|
|
61 TODO: figure out how to avoid exposing this in the general
|
|
62 case
|
|
63
|
|
64 ***********************************************************************/
|
|
65
|
|
66 abstract Handle fileHandle ();
|
|
67
|
|
68 /***********************************************************************
|
|
69
|
|
70 Read from conduit into a target array. The provided dst
|
|
71 will be populated with content from the conduit.
|
|
72
|
|
73 Returns the number of bytes read, which may be less than
|
|
74 requested in dst. Eof is returned whenever an end-of-flow
|
|
75 condition arises.
|
|
76
|
|
77 ***********************************************************************/
|
|
78
|
|
79 abstract uint read (void[] dst);
|
|
80
|
|
81 /***********************************************************************
|
|
82
|
|
83 Write to conduit from a source array. The provided src
|
|
84 content will be written to the conduit.
|
|
85
|
|
86 Returns the number of bytes written from src, which may
|
|
87 be less than the quantity provided. Eof is returned when
|
|
88 an end-of-flow condition arises.
|
|
89
|
|
90 ***********************************************************************/
|
|
91
|
|
92 abstract uint write (void [] src);
|
|
93
|
|
94 /***********************************************************************
|
|
95
|
|
96 Disconnect this conduit
|
|
97
|
|
98 ***********************************************************************/
|
|
99
|
|
100 abstract void detach ();
|
|
101
|
|
102 /***********************************************************************
|
|
103
|
|
104 Is the conduit alive? Default behaviour returns true
|
|
105
|
|
106 ***********************************************************************/
|
|
107
|
|
108 bool isAlive ()
|
|
109 {
|
|
110 return true;
|
|
111 }
|
|
112
|
|
113 /***********************************************************************
|
|
114
|
|
115 Return the host. This is part of the Stream interface
|
|
116
|
|
117 ***********************************************************************/
|
|
118
|
|
119 final IConduit conduit()
|
|
120 {
|
|
121 return this;
|
|
122 }
|
|
123
|
|
124 /***********************************************************************
|
|
125
|
|
126 clear any buffered input
|
|
127
|
|
128 ***********************************************************************/
|
|
129
|
|
130 InputStream clear () {return this;}
|
|
131
|
|
132 /***********************************************************************
|
|
133
|
|
134 Write buffered output
|
|
135
|
|
136 ***********************************************************************/
|
|
137
|
|
138 OutputStream flush () {return this;}
|
|
139
|
|
140 /***********************************************************************
|
|
141
|
|
142 Close this conduit
|
|
143
|
|
144 Remarks:
|
|
145 Both input and output are detached, and are no longer usable
|
|
146
|
|
147 ***********************************************************************/
|
|
148
|
|
149 final void close ()
|
|
150 {
|
|
151 this.detach;
|
|
152 }
|
|
153
|
|
154 /***********************************************************************
|
|
155
|
|
156 Return the current input stream
|
|
157
|
|
158 ***********************************************************************/
|
|
159
|
|
160 final InputStream input ()
|
|
161 {
|
|
162 return this;
|
|
163 }
|
|
164
|
|
165 /***********************************************************************
|
|
166
|
|
167 Return the current output stream
|
|
168
|
|
169 ***********************************************************************/
|
|
170
|
|
171 final OutputStream output ()
|
|
172 {
|
|
173 return this;
|
|
174 }
|
|
175
|
|
176 /***********************************************************************
|
|
177
|
|
178 Throw an IOException, with the provided message
|
|
179
|
|
180 ***********************************************************************/
|
|
181
|
|
182 final void error (char[] msg)
|
|
183 {
|
|
184 throw new IOException (msg);
|
|
185 }
|
|
186
|
|
187 /***********************************************************************
|
|
188
|
|
189 Transfer the content of another conduit to this one. Returns
|
|
190 the dst OutputStream, or throws IOException on failure.
|
|
191
|
|
192 ***********************************************************************/
|
|
193
|
|
194 final OutputStream copy (InputStream src)
|
|
195 {
|
|
196 return transfer (src, this);
|
|
197 }
|
|
198
|
|
199 /***********************************************************************
|
|
200
|
|
201 Transfer the content of one stream to another. Returns
|
|
202 the dst OutputStream, and throws IOException on failure.
|
|
203 Queries dst to identify what size of buffer to utilize.
|
|
204
|
|
205 ***********************************************************************/
|
|
206
|
|
207 static OutputStream transfer (InputStream src, OutputStream dst)
|
|
208 {
|
|
209 uint len = 0;
|
|
210 auto con = dst.conduit;
|
|
211 auto tmp = new byte [con.bufferSize];
|
|
212 while ((len = src.read(tmp)) != IConduit.Eof)
|
|
213 {
|
|
214 auto p = tmp.ptr;
|
|
215 for (uint j; len > 0; len -= j, p += j)
|
|
216 if ((j = dst.write (p[0..len])) is IConduit.Eof)
|
|
217 con.error ("Conduit.copy :: Eof while writing to: "~con.toString);
|
|
218 }
|
|
219 delete tmp;
|
|
220 return dst;
|
|
221 }
|
|
222 }
|
|
223
|
|
224
|
|
225 /*******************************************************************************
|
|
226
|
|
227 Base class for input stream filtering
|
|
228
|
|
229 *******************************************************************************/
|
|
230
|
|
231 class InputFilter : InputStream
|
|
232 {
|
|
233 protected InputStream host;
|
|
234
|
|
235 /***********************************************************************
|
|
236
|
|
237 Attach to the provided stream
|
|
238
|
|
239 ***********************************************************************/
|
|
240
|
|
241 this (InputStream host)
|
|
242 {
|
|
243 assert (host, "input stream host cannot be null");
|
|
244 this.host = host;
|
|
245 }
|
|
246
|
|
247 /***********************************************************************
|
|
248
|
|
249 Return the hosting conduit
|
|
250
|
|
251 ***********************************************************************/
|
|
252
|
|
253 IConduit conduit ()
|
|
254 {
|
|
255 return host.conduit;
|
|
256 }
|
|
257
|
|
258 /***********************************************************************
|
|
259
|
|
260 Read from conduit into a target array. The provided dst
|
|
261 will be populated with content from the conduit.
|
|
262
|
|
263 Returns the number of bytes read, which may be less than
|
|
264 requested in dst. Eof is returned whenever an end-of-flow
|
|
265 condition arises.
|
|
266
|
|
267 ***********************************************************************/
|
|
268
|
|
269 uint read (void[] dst)
|
|
270 {
|
|
271 return host.read (dst);
|
|
272 }
|
|
273
|
|
274 /***********************************************************************
|
|
275
|
|
276 Clear any buffered content
|
|
277
|
|
278 ***********************************************************************/
|
|
279
|
|
280 InputStream clear ()
|
|
281 {
|
|
282 host.clear;
|
|
283 return this;
|
|
284 }
|
|
285
|
|
286 /***********************************************************************
|
|
287
|
|
288 Close the input
|
|
289
|
|
290 ***********************************************************************/
|
|
291
|
|
292 void close ()
|
|
293 {
|
|
294 host.close;
|
|
295 }
|
|
296 }
|
|
297
|
|
298
|
|
299 /*******************************************************************************
|
|
300
|
|
301 Base class for output stream filtering
|
|
302
|
|
303 *******************************************************************************/
|
|
304
|
|
305 class OutputFilter : OutputStream
|
|
306 {
|
|
307 protected OutputStream host;
|
|
308
|
|
309 /***********************************************************************
|
|
310
|
|
311 Attach to the provided stream
|
|
312
|
|
313 ***********************************************************************/
|
|
314
|
|
315 this (OutputStream host)
|
|
316 {
|
|
317 assert (host, "output stream host cannot be null");
|
|
318 this.host = host;
|
|
319 }
|
|
320
|
|
321 /***********************************************************************
|
|
322
|
|
323 Return the hosting conduit
|
|
324
|
|
325 ***********************************************************************/
|
|
326
|
|
327 IConduit conduit ()
|
|
328 {
|
|
329 return host.conduit;
|
|
330 }
|
|
331
|
|
332 /***********************************************************************
|
|
333
|
|
334 Write to conduit from a source array. The provided src
|
|
335 content will be written to the conduit.
|
|
336
|
|
337 Returns the number of bytes written from src, which may
|
|
338 be less than the quantity provided. Eof is returned when
|
|
339 an end-of-flow condition arises.
|
|
340
|
|
341 ***********************************************************************/
|
|
342
|
|
343 uint write (void[] src)
|
|
344 {
|
|
345 return host.write (src);
|
|
346 }
|
|
347
|
|
348 /***********************************************************************
|
|
349
|
|
350 Emit/purge buffered content
|
|
351
|
|
352 ***********************************************************************/
|
|
353
|
|
354 OutputStream flush ()
|
|
355 {
|
|
356 host.flush;
|
|
357 return this;
|
|
358 }
|
|
359
|
|
360 /***********************************************************************
|
|
361
|
|
362 Close the output
|
|
363
|
|
364 ***********************************************************************/
|
|
365
|
|
366 void close ()
|
|
367 {
|
|
368 host.close;
|
|
369 }
|
|
370
|
|
371 /***********************************************************************
|
|
372
|
|
373 Transfer the content of another conduit to this one. Returns
|
|
374 a reference to this class, or throws IOException on failure.
|
|
375
|
|
376 ***********************************************************************/
|
|
377
|
|
378 OutputStream copy (InputStream src)
|
|
379 {
|
|
380 return Conduit.transfer (src, this);
|
|
381 }
|
|
382 }
|
|
383
|
|
384
|