132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: Mar 2004: Initial release
|
|
8 Dec 2006: Outback release
|
|
9
|
|
10 author: Kris
|
|
11
|
|
12 *******************************************************************************/
|
|
13
|
|
14 module tango.io.model.IBuffer;
|
|
15
|
|
16 private import tango.io.model.IConduit;
|
|
17
|
|
18 /*******************************************************************************
|
|
19
|
|
20 Buffer is central concept in Tango I/O. Each buffer acts
|
|
21 as a queue (line) where items are removed from the front
|
|
22 and new items are added to the back. Buffers are modeled
|
|
23 by this interface and implemented in various ways.
|
|
24
|
|
25 Buffer can be read from and written to directly, though
|
|
26 various data-converters and filters are often leveraged
|
|
27 to apply structure to what might otherwise be simple raw
|
|
28 data.
|
|
29
|
|
30 Buffers may also be tokenized by applying an Iterator.
|
|
31 This can be handy when one is dealing with text input,
|
|
32 and/or the content suits a more fluid format than most
|
|
33 typical converters support. Iterator tokens are mapped
|
|
34 directly onto buffer content (sliced), making them quite
|
|
35 efficient in practice. Like other types of buffer client,
|
|
36 multiple iterators can be mapped onto one common buffer
|
|
37 and access will be serialized.
|
|
38
|
|
39 Buffers are sometimes memory-only, in which case there
|
|
40 is nothing left to do when a client has consumed all the
|
|
41 content. Other buffers are themselves bound to an external
|
|
42 device called a conduit. When this is the case, a consumer
|
|
43 will eventually cause a buffer to reload via its associated
|
|
44 conduit and previous buffer content will be lost.
|
|
45
|
|
46 A similar approach is applied to clients which populate a
|
|
47 buffer, whereby the content of a full buffer will be flushed
|
|
48 to a bound conduit before continuing. Another variation is
|
|
49 that of a memory-mapped buffer, whereby the buffer content
|
|
50 is mapped directly to virtual memory exposed via the OS. This
|
|
51 can be used to address large files as an array of content.
|
|
52
|
|
53 See tango.io.Buffer for more info.
|
|
54
|
|
55 *******************************************************************************/
|
|
56
|
|
57 abstract class IBuffer : IConduit, Buffered
|
|
58 {
|
|
59 alias append opCall;
|
|
60 alias flush opCall;
|
|
61
|
|
62 /***********************************************************************
|
|
63
|
|
64 implements Buffered interface
|
|
65
|
|
66 ***********************************************************************/
|
|
67
|
|
68 abstract IBuffer buffer ();
|
|
69
|
|
70 /***********************************************************************
|
|
71
|
|
72 Return the backing array
|
|
73
|
|
74 ***********************************************************************/
|
|
75
|
|
76 abstract void[] getContent ();
|
|
77
|
|
78 /***********************************************************************
|
|
79
|
|
80 Return a void[] slice of the buffer up to the limit of
|
|
81 valid content.
|
|
82
|
|
83 ***********************************************************************/
|
|
84
|
|
85 abstract void[] slice ();
|
|
86
|
|
87 /***********************************************************************
|
|
88
|
|
89 Set the backing array with all content readable. Writing
|
|
90 to this will either flush it to an associated conduit, or
|
|
91 raise an Eof condition. Use IBuffer.clear() to reset the
|
|
92 content (make it all writable).
|
|
93
|
|
94 ***********************************************************************/
|
|
95
|
|
96 abstract IBuffer setContent (void[] data);
|
|
97
|
|
98 /***********************************************************************
|
|
99
|
|
100 Set the backing array with some content readable. Writing
|
|
101 to this will either flush it to an associated conduit, or
|
|
102 raise an Eof condition. Use IBuffer.clear() to reset the
|
|
103 content (make it all writable).
|
|
104
|
|
105 ***********************************************************************/
|
|
106
|
|
107 abstract IBuffer setContent (void[] data, uint readable);
|
|
108
|
|
109 /***********************************************************************
|
|
110
|
|
111 Append an array of data into this buffer, and flush to the
|
|
112 conduit as necessary. Returns a chaining reference if all
|
|
113 data was written; throws an IOException indicating eof or
|
|
114 eob if not.
|
|
115
|
|
116 This is often used in lieu of a Writer.
|
|
117
|
|
118 ***********************************************************************/
|
|
119
|
|
120 abstract IBuffer append (void* content, uint length);
|
|
121
|
|
122 /***********************************************************************
|
|
123
|
|
124 Append an array of data into this buffer, and flush to the
|
|
125 conduit as necessary. Returns a chaining reference if all
|
|
126 data was written; throws an IOException indicating eof or
|
|
127 eob if not.
|
|
128
|
|
129 This is often used in lieu of a Writer.
|
|
130
|
|
131 ***********************************************************************/
|
|
132
|
|
133 abstract IBuffer append (void[] content);
|
|
134
|
|
135 /***********************************************************************
|
|
136
|
|
137 Append another buffer to this one, and flush to the
|
|
138 conduit as necessary. Returns a chaining reference if all
|
|
139 data was written; throws an IOException indicating eof or
|
|
140 eob if not.
|
|
141
|
|
142 This is often used in lieu of a Writer.
|
|
143
|
|
144 ***********************************************************************/
|
|
145
|
|
146 abstract IBuffer append (IBuffer other);
|
|
147
|
|
148 /***********************************************************************
|
|
149
|
|
150 Consume content from a producer
|
|
151
|
|
152 Params:
|
|
153 The content to consume. This is consumed verbatim, and in
|
|
154 raw binary format ~ no implicit conversions are performed.
|
|
155
|
|
156 Remarks:
|
|
157 This is often used in lieu of a Writer, and enables simple
|
|
158 classes, such as FilePath and Uri, to emit content directly
|
|
159 into a buffer (thus avoiding potential heap activity)
|
|
160
|
|
161 Examples:
|
|
162 ---
|
|
163 auto path = new FilePath (somepath);
|
|
164
|
|
165 path.produce (&buffer.consume);
|
|
166 ---
|
|
167
|
|
168 ***********************************************************************/
|
|
169
|
|
170 abstract void consume (void[] src);
|
|
171
|
|
172 /***********************************************************************
|
|
173
|
|
174 Read a chunk of data from the buffer, loading from the
|
|
175 conduit as necessary. The requested number of bytes are
|
|
176 loaded into the buffer, and marked as having been read
|
|
177 when the 'eat' parameter is set true. When 'eat' is set
|
|
178 false, the read position is not adjusted.
|
|
179
|
|
180 Returns the corresponding buffer slice when successful,
|
|
181 or null if there's not enough data available (Eof; Eob).
|
|
182
|
|
183 ***********************************************************************/
|
|
184
|
|
185 abstract void[] slice (uint size, bool eat = true);
|
|
186
|
|
187 /***********************************************************************
|
|
188
|
|
189 Access buffer content
|
|
190
|
|
191 Params:
|
|
192 dst = destination of the content
|
|
193 bytes = size of dst
|
|
194
|
|
195 Returns:
|
|
196 A reference to the populated content
|
|
197
|
|
198 Remarks:
|
|
199 Fill the provided array with content. We try to satisfy
|
|
200 the request from the buffer content, and read directly
|
|
201 from an attached conduit where more is required.
|
|
202
|
|
203 ***********************************************************************/
|
|
204
|
|
205 abstract void[] readExact (void* dst, uint bytes);
|
|
206
|
|
207 /**********************************************************************
|
|
208
|
|
209 Fill the provided buffer. Returns the number of bytes
|
|
210 actually read, which will be less than dst.length when
|
|
211 Eof has been reached and IConduit.Eof thereafter.
|
|
212
|
|
213 **********************************************************************/
|
|
214
|
|
215 abstract uint fill (void[] dst);
|
|
216
|
|
217 /***********************************************************************
|
|
218
|
|
219 Exposes the raw data buffer at the current write position,
|
|
220 The delegate is provided with a void[] representing space
|
|
221 available within the buffer at the current write position.
|
|
222
|
|
223 The delegate should return the approriate number of bytes
|
|
224 if it writes valid content, or IConduit.Eof on error.
|
|
225
|
|
226 Returns whatever the delegate returns.
|
|
227
|
|
228 ***********************************************************************/
|
|
229
|
|
230 abstract uint write (uint delegate (void[]) writer);
|
|
231
|
|
232 /***********************************************************************
|
|
233
|
|
234 Exposes the raw data buffer at the current read position. The
|
|
235 delegate is provided with a void[] representing the available
|
|
236 data, and should return zero to leave the current read position
|
|
237 intact.
|
|
238
|
|
239 If the delegate consumes data, it should return the number of
|
|
240 bytes consumed; or IConduit.Eof to indicate an error.
|
|
241
|
|
242 Returns whatever the delegate returns.
|
|
243
|
|
244 ***********************************************************************/
|
|
245
|
|
246 abstract uint read (uint delegate (void[]) reader);
|
|
247
|
|
248 /***********************************************************************
|
|
249
|
|
250 If we have some data left after an export, move it to
|
|
251 front-of-buffer and set position to be just after the
|
|
252 remains. This is for supporting certain conduits which
|
|
253 choose to write just the initial portion of a request.
|
|
254
|
|
255 Limit is set to the amount of data remaining. Position
|
|
256 is always reset to zero.
|
|
257
|
|
258 ***********************************************************************/
|
|
259
|
|
260 abstract IBuffer compress ();
|
|
261
|
|
262 /***********************************************************************
|
|
263
|
|
264 Skip ahead by the specified number of bytes, streaming from
|
|
265 the associated conduit as necessary.
|
|
266
|
|
267 Can also reverse the read position by 'size' bytes. This may
|
|
268 be used to support lookahead-type operations.
|
|
269
|
|
270 Returns true if successful, false otherwise.
|
|
271
|
|
272 ***********************************************************************/
|
|
273
|
|
274 abstract bool skip (int size);
|
|
275
|
|
276 /***********************************************************************
|
|
277
|
|
278 Support for tokenizing iterators.
|
|
279
|
|
280 Upon success, the delegate should return the byte-based
|
|
281 index of the consumed pattern (tail end of it). Failure
|
|
282 to match a pattern should be indicated by returning an
|
|
283 IConduit.Eof.
|
|
284
|
|
285 Each pattern is expected to be stripped of the delimiter.
|
|
286 An end-of-file condition causes trailing content to be
|
|
287 placed into the token. Requests made beyond Eof result
|
|
288 in empty matches (length == zero).
|
|
289
|
|
290 Note that additional iterator and/or reader instances
|
|
291 will stay in lockstep when bound to a common buffer.
|
|
292
|
|
293 Returns true if a token was isolated, false otherwise.
|
|
294
|
|
295 ***********************************************************************/
|
|
296
|
|
297 abstract bool next (uint delegate (void[]));
|
|
298
|
|
299 /***********************************************************************
|
|
300
|
|
301 Try to _fill the available buffer with content from the
|
|
302 specified conduit. We try to read as much as possible
|
|
303 by clearing the buffer when all current content has been
|
|
304 eaten. If there is no space available, nothing will be
|
|
305 read.
|
|
306
|
|
307 Returns the number of bytes read, or Conduit.Eof.
|
|
308
|
|
309 ***********************************************************************/
|
|
310
|
|
311 abstract uint fill (InputStream src);
|
|
312
|
|
313 /***********************************************************************
|
|
314
|
|
315 Write as much of the buffer that the associated conduit
|
|
316 can consume.
|
|
317
|
|
318 Returns the number of bytes written, or Conduit.Eof.
|
|
319
|
|
320 ***********************************************************************/
|
|
321
|
|
322 abstract uint drain (OutputStream dst);
|
|
323
|
|
324 /***********************************************************************
|
|
325
|
|
326 Truncate the buffer within its extent. Returns true if
|
|
327 the new 'extent' is valid, false otherwise.
|
|
328
|
|
329 ***********************************************************************/
|
|
330
|
|
331 abstract bool truncate (uint extent);
|
|
332
|
|
333 /***********************************************************************
|
|
334
|
|
335 Return count of readable bytes remaining in buffer. This is
|
|
336 calculated simply as limit() - position().
|
|
337
|
|
338 ***********************************************************************/
|
|
339
|
|
340 abstract uint readable ();
|
|
341
|
|
342 /***********************************************************************
|
|
343
|
|
344 Return count of writable bytes available in buffer. This is
|
|
345 calculated simply as capacity() - limit().
|
|
346
|
|
347 ***********************************************************************/
|
|
348
|
|
349 abstract uint writable ();
|
|
350
|
|
351 /***********************************************************************
|
|
352
|
|
353 Returns the limit of readable content within this buffer.
|
|
354
|
|
355 ***********************************************************************/
|
|
356
|
|
357 abstract uint limit ();
|
|
358
|
|
359 /***********************************************************************
|
|
360
|
|
361 Returns the total capacity of this buffer.
|
|
362
|
|
363 ***********************************************************************/
|
|
364
|
|
365 abstract uint capacity ();
|
|
366
|
|
367 /***********************************************************************
|
|
368
|
|
369 Returns the current position within this buffer.
|
|
370
|
|
371 ***********************************************************************/
|
|
372
|
|
373 abstract uint position ();
|
|
374
|
|
375 /***********************************************************************
|
|
376
|
|
377 Sets the external conduit associated with this buffer.
|
|
378
|
|
379 Buffers do not require an external conduit to operate, but
|
|
380 it can be convenient to associate one. For example, methods
|
|
381 read and write use it to import/export content as necessary.
|
|
382
|
|
383 ***********************************************************************/
|
|
384
|
|
385 abstract IBuffer setConduit (IConduit conduit);
|
|
386
|
|
387 /***********************************************************************
|
|
388
|
|
389 Set output stream
|
|
390
|
|
391 Params:
|
|
392 sink = the stream to attach to
|
|
393
|
|
394 Remarks:
|
|
395 Sets the external output stream associated with this buffer.
|
|
396
|
|
397 Buffers do not require an external stream to operate, but
|
|
398 it can be convenient to associate one. For example, methods
|
|
399 fill & drain use them to import/export content as necessary.
|
|
400
|
|
401 ***********************************************************************/
|
|
402
|
|
403 abstract IBuffer output (OutputStream sink);
|
|
404
|
|
405 /***********************************************************************
|
|
406
|
|
407 Set input stream
|
|
408
|
|
409 Params:
|
|
410 source = the stream to attach to
|
|
411
|
|
412 Remarks:
|
|
413 Sets the external input stream associated with this buffer.
|
|
414
|
|
415 Buffers do not require an external stream to operate, but
|
|
416 it can be convenient to associate one. For example, methods
|
|
417 fill & drain use them to import/export content as necessary.
|
|
418
|
|
419 ***********************************************************************/
|
|
420
|
|
421 abstract IBuffer input (InputStream source);
|
|
422
|
|
423 /***********************************************************************
|
|
424
|
|
425 Transfer content into the provided dst.
|
|
426
|
|
427 Params:
|
|
428 dst = destination of the content
|
|
429
|
|
430 Returns:
|
|
431 Return the number of bytes read, which may be less than
|
|
432 dst.length. Eof is returned when no further content is
|
|
433 available.
|
|
434
|
|
435 Remarks:
|
|
436 Populates the provided array with content. We try to
|
|
437 satisfy the request from the buffer content, and read
|
|
438 directly from an attached conduit when the buffer is
|
|
439 empty.
|
|
440
|
|
441 ***********************************************************************/
|
|
442
|
|
443 abstract uint read (void[] dst);
|
|
444
|
|
445 /***********************************************************************
|
|
446
|
|
447 Emulate OutputStream.write()
|
|
448
|
|
449 Params:
|
|
450 src = the content to write
|
|
451
|
|
452 Returns:
|
|
453 Return the number of bytes written, which will be Eof when
|
|
454 the content cannot be written.
|
|
455
|
|
456 Remarks:
|
|
457 Appends all of dst to the buffer, flushing to an attached
|
|
458 conduit as necessary.
|
|
459
|
|
460 ***********************************************************************/
|
|
461
|
|
462 abstract uint write (void[] src);
|
|
463
|
|
464 /***********************************************************************
|
|
465
|
|
466 Exposes configured output stream
|
|
467
|
|
468 Returns:
|
|
469 Returns the OutputStream associated with this buffer. Returns
|
|
470 null if the buffer is not attached to an output; that is, it's
|
|
471 not backed by some external medium.
|
|
472
|
|
473 Remarks:
|
|
474 Buffers do not require an external stream to operate, but
|
|
475 it can be convenient to associate them. For example, methods
|
|
476 fill & drain use them to import/export content as necessary.
|
|
477
|
|
478 ***********************************************************************/
|
|
479
|
|
480 abstract OutputStream output ();
|
|
481
|
|
482 /***********************************************************************
|
|
483
|
|
484 Exposes configured input stream
|
|
485
|
|
486 Returns:
|
|
487 Returns the InputStream associated with this buffer. Returns
|
|
488 null if the buffer is not attached to an input; that is, it's
|
|
489 not backed by some external medium.
|
|
490
|
|
491 Remarks:
|
|
492 Buffers do not require an external stream to operate, but
|
|
493 it can be convenient to associate them. For example, methods
|
|
494 fill & drain use them to import/export content as necessary.
|
|
495
|
|
496 ***********************************************************************/
|
|
497
|
|
498 abstract InputStream input ();
|
|
499
|
|
500 /***********************************************************************
|
|
501
|
|
502 Throw an exception with the provided message
|
|
503
|
|
504 ***********************************************************************/
|
|
505
|
|
506 abstract void error (char[] msg);
|
|
507
|
|
508 /***********************************************************************
|
|
509
|
|
510 Access configured conduit
|
|
511
|
|
512 Returns:
|
|
513 Returns the conduit associated with this buffer. Returns
|
|
514 null if the buffer is purely memory based; that is, it's
|
|
515 not backed by some external medium.
|
|
516
|
|
517 Remarks:
|
|
518 Buffers do not require an external conduit to operate, but
|
|
519 it can be convenient to associate one. For example, methods
|
|
520 fill() & drain() use it to import/export content as necessary.
|
|
521
|
|
522 ***********************************************************************/
|
|
523
|
|
524 abstract IConduit conduit ();
|
|
525
|
|
526 /***********************************************************************
|
|
527
|
|
528 Return a preferred size for buffering conduit I/O.
|
|
529
|
|
530 ***********************************************************************/
|
|
531
|
|
532 abstract uint bufferSize ();
|
|
533
|
|
534 /***********************************************************************
|
|
535
|
|
536 Return the name of this conduit.
|
|
537
|
|
538 ***********************************************************************/
|
|
539
|
|
540 abstract char[] toString ();
|
|
541
|
|
542 /***********************************************************************
|
|
543
|
|
544 Is the conduit alive?
|
|
545
|
|
546 ***********************************************************************/
|
|
547
|
|
548 abstract bool isAlive ();
|
|
549
|
|
550 /***********************************************************************
|
|
551
|
|
552 Flush the contents of this buffer to the related conduit.
|
|
553 Throws an IOException on premature eof.
|
|
554
|
|
555 ***********************************************************************/
|
|
556
|
|
557 abstract OutputStream flush ();
|
|
558
|
|
559 /***********************************************************************
|
|
560
|
|
561 Reset position and limit to zero.
|
|
562
|
|
563 ***********************************************************************/
|
|
564
|
|
565 abstract InputStream clear ();
|
|
566
|
|
567 /***********************************************************************
|
|
568
|
|
569 Copy content via this buffer from the provided src
|
|
570 conduit.
|
|
571
|
|
572 Remarks:
|
|
573 The src conduit has its content transferred through
|
|
574 this buffer via a series of fill & drain operations,
|
|
575 until there is no more content available. The buffer
|
|
576 content should be explicitly flushed by the caller.
|
|
577
|
|
578 Throws an IOException on premature Eof.
|
|
579
|
|
580 ***********************************************************************/
|
|
581
|
|
582 abstract OutputStream copy (InputStream src);
|
|
583
|
|
584 /***********************************************************************
|
|
585
|
|
586 Release external resources
|
|
587
|
|
588 ***********************************************************************/
|
|
589
|
|
590 abstract void detach ();
|
|
591
|
|
592 /***********************************************************************
|
|
593
|
|
594 Close the stream
|
|
595
|
|
596 Remarks:
|
|
597 Propagate request to an attached OutputStream (this is a
|
|
598 requirement for the OutputStream interface)
|
|
599
|
|
600 ***********************************************************************/
|
|
601
|
|
602 abstract void close ();
|
|
603 }
|
|
604
|
|
605
|
|
606 /*******************************************************************************
|
|
607
|
|
608 Supported by streams which are prepared to share an internal buffer
|
|
609 instance. This is intended to avoid a situation whereby content is
|
|
610 shunted unnecessarily from one buffer to another when "decorator"
|
|
611 streams are connected together in arbitrary ways.
|
|
612
|
|
613 Do not implement this if the internal buffer should not be accessed
|
|
614 directly by another stream e.g. if wrapper methods manipulate content
|
|
615 on the way in or out of the buffer.
|
|
616
|
|
617 *******************************************************************************/
|
|
618
|
|
619 interface Buffered
|
|
620 {
|
|
621 IBuffer buffer();
|
|
622 }
|