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.GrowBuffer;
|
|
14
|
|
15 private import tango.io.Buffer;
|
|
16
|
|
17 public import tango.io.model.IBuffer;
|
|
18
|
|
19 /*******************************************************************************
|
|
20
|
|
21 Subclass to provide support for content growth. This is handy when
|
|
22 you want to keep a buffer around as a scratchpad.
|
|
23
|
|
24 *******************************************************************************/
|
|
25
|
|
26 class GrowBuffer : Buffer
|
|
27 {
|
|
28 private uint increment;
|
|
29
|
|
30 alias Buffer.slice slice;
|
|
31 alias Buffer.append append;
|
|
32
|
|
33 /***********************************************************************
|
|
34
|
|
35 Create a GrowBuffer with the specified initial size.
|
|
36
|
|
37 ***********************************************************************/
|
|
38
|
|
39 this (uint size = 1024, uint increment = 1024)
|
|
40 {
|
|
41 super (size);
|
|
42
|
|
43 assert (increment >= 32);
|
|
44 this.increment = increment;
|
|
45 }
|
|
46
|
|
47 /***********************************************************************
|
|
48
|
|
49 Create a GrowBuffer with the specified initial size.
|
|
50
|
|
51 ***********************************************************************/
|
|
52
|
|
53 this (IConduit conduit, uint size = 1024)
|
|
54 {
|
|
55 this (size, size);
|
|
56 setConduit (conduit);
|
|
57 }
|
|
58
|
|
59 /***********************************************************************
|
|
60
|
|
61 Read a chunk of data from the buffer, loading from the
|
|
62 conduit as necessary. The specified number of bytes is
|
|
63 loaded into the buffer, and marked as having been read
|
|
64 when the 'eat' parameter is set true. When 'eat' is set
|
|
65 false, the read position is not adjusted.
|
|
66
|
|
67 Returns the corresponding buffer slice when successful.
|
|
68
|
|
69 ***********************************************************************/
|
|
70
|
|
71 override void[] slice (uint size, bool eat = true)
|
|
72 {
|
|
73 if (size > readable)
|
|
74 {
|
|
75 if (source is null)
|
|
76 error (underflow);
|
|
77
|
|
78 if (size + index > dimension)
|
|
79 makeRoom (size);
|
|
80
|
|
81 // populate tail of buffer with new content
|
|
82 do {
|
|
83 if (fill(source) is IConduit.Eof)
|
|
84 error (eofRead);
|
|
85 } while (size > readable);
|
|
86 }
|
|
87
|
|
88 uint i = index;
|
|
89 if (eat)
|
|
90 index += size;
|
|
91 return data [i .. i + size];
|
|
92 }
|
|
93
|
|
94 /***********************************************************************
|
|
95
|
|
96 Append an array of data to this buffer. This is often used
|
|
97 in lieu of a Writer.
|
|
98
|
|
99 ***********************************************************************/
|
|
100
|
|
101 override IBuffer append (void *src, uint length)
|
|
102 {
|
|
103 if (length > writable)
|
|
104 makeRoom (length);
|
|
105
|
|
106 copy (src, length);
|
|
107 return this;
|
|
108 }
|
|
109
|
|
110 /***********************************************************************
|
|
111
|
|
112 Try to fill the available buffer with content from the
|
|
113 specified conduit.
|
|
114
|
|
115 Returns the number of bytes read, or IConduit.Eof
|
|
116
|
|
117 ***********************************************************************/
|
|
118
|
|
119 override uint fill (InputStream src)
|
|
120 {
|
|
121 if (writable <= increment/8)
|
|
122 makeRoom (increment);
|
|
123
|
|
124 return write (&src.read);
|
|
125 }
|
|
126
|
|
127 /***********************************************************************
|
|
128
|
|
129 Expand and consume the conduit content, up to the maximum
|
|
130 size indicated by the argument or until conduit.Eof
|
|
131
|
|
132 Returns the number of bytes in the buffer
|
|
133
|
|
134 ***********************************************************************/
|
|
135
|
|
136 uint fill (uint size = uint.max)
|
|
137 {
|
|
138 while (readable < size)
|
|
139 if (fill(source) is IConduit.Eof)
|
|
140 break;
|
|
141 return readable;
|
|
142 }
|
|
143
|
|
144 /***********************************************************************
|
|
145
|
|
146 make some room in the buffer
|
|
147
|
|
148 ***********************************************************************/
|
|
149
|
|
150 private uint makeRoom (uint size)
|
|
151 {
|
|
152 if (size < increment)
|
|
153 size = increment;
|
|
154
|
|
155 dimension += size;
|
|
156 data.length = dimension;
|
|
157 return writable();
|
|
158 }
|
|
159 }
|