2 // System.IO.BufferedStream
5 // Matt Kimball (matt@kimball.net)
6 // Ville Palo <vi64pa@kolumbus.fi>
8 // Copyright (C) 2004 Novell (http://www.novell.com)
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Globalization
;
35 using System
.Runtime
.InteropServices
;
38 public sealed class BufferedStream
: Stream
{
42 int m_buffer_read_ahead
;
43 bool m_buffer_reading
;
44 private bool disposed
= false;
46 public BufferedStream (Stream stream
) : this (stream
, 4096)
50 public BufferedStream (Stream stream
, int buffer_size
)
53 throw new ArgumentNullException ("stream");
54 // LAMESPEC: documented as < 0
56 throw new ArgumentOutOfRangeException ("buffer_size", "<= 0");
57 if (!stream
.CanRead
&& !stream
.CanWrite
) {
58 throw new ObjectDisposedException (
59 Locale
.GetText ("Cannot access a closed Stream."));
63 m_buffer
= new byte [buffer_size
];
66 public override bool CanRead
{
68 return m_stream
.CanRead
;
72 public override bool CanWrite
{
74 return m_stream
.CanWrite
;
78 public override bool CanSeek
{
80 return m_stream
.CanSeek
;
84 public override long Length
{
87 return m_stream
.Length
;
91 public override long Position
{
93 CheckObjectDisposedException ();
94 return m_stream
.Position
- m_buffer_read_ahead
+ m_buffer_pos
;
98 if (value < Position
&& (Position
- value <= m_buffer_pos
) && m_buffer_reading
) {
99 m_buffer_pos
-= (int) (Position
- value);
101 else if (value > Position
&& (value - Position
< m_buffer_read_ahead
- m_buffer_pos
) && m_buffer_reading
) {
102 m_buffer_pos
+= (int) (value - Position
);
106 m_stream
.Position
= value;
111 public override void Close ()
113 if (m_buffer
!= null)
121 public override void Flush ()
123 CheckObjectDisposedException ();
125 if (m_buffer_reading
) {
127 m_stream
.Position
= Position
;
128 } else if (m_buffer_pos
> 0) {
129 m_stream
.Write(m_buffer
, 0, m_buffer_pos
);
132 m_buffer_read_ahead
= 0;
136 public override long Seek (long offset
, SeekOrigin origin
)
138 CheckObjectDisposedException ();
140 throw new NotSupportedException (
141 Locale
.GetText ("Non seekable stream."));
144 return m_stream
.Seek (offset
, origin
);
147 public override void SetLength (long value)
149 CheckObjectDisposedException ();
152 throw new ArgumentOutOfRangeException ("value must be positive");
154 if (!m_stream
.CanWrite
&& !m_stream
.CanSeek
)
155 throw new NotSupportedException ("the stream cannot seek nor write.");
157 if ((m_stream
== null) || (!m_stream
.CanRead
&& !m_stream
.CanWrite
))
158 throw new IOException ("the stream is not open");
160 m_stream
.SetLength(value);
161 if (Position
> value)
165 public override int ReadByte ()
167 CheckObjectDisposedException ();
169 byte[] b
= new byte[1];
171 if (Read(b
, 0, 1) == 1) {
178 public override void WriteByte (byte value)
180 CheckObjectDisposedException ();
181 byte[] b
= new byte[1];
187 public override int Read ([In
,Out
] byte[] array
, int offset
, int count
)
190 throw new ArgumentNullException ("array");
191 CheckObjectDisposedException ();
192 if (!m_stream
.CanRead
) {
193 throw new NotSupportedException (
194 Locale
.GetText ("Cannot read from stream"));
197 throw new ArgumentOutOfRangeException ("offset", "< 0");
199 throw new ArgumentOutOfRangeException ("count", "< 0");
200 // re-ordered to avoid possible integer overflow
201 if (array
.Length
- offset
< count
)
202 throw new ArgumentException ("array.Length - offset < count");
204 if (!m_buffer_reading
) {
206 m_buffer_reading
= true;
209 if (count
<= m_buffer_read_ahead
- m_buffer_pos
) {
210 Array
.Copy(m_buffer
, m_buffer_pos
, array
, offset
, count
);
212 m_buffer_pos
+= count
;
213 if (m_buffer_pos
== m_buffer_read_ahead
) {
215 m_buffer_read_ahead
= 0;
221 int ret
= m_buffer_read_ahead
- m_buffer_pos
;
222 Array
.Copy(m_buffer
, m_buffer_pos
, array
, offset
, ret
);
224 m_buffer_read_ahead
= 0;
228 if (count
>= m_buffer
.Length
) {
229 ret
+= m_stream
.Read(array
, offset
, count
);
231 m_buffer_read_ahead
= m_stream
.Read(m_buffer
, 0, m_buffer
.Length
);
233 if (count
< m_buffer_read_ahead
) {
234 Array
.Copy(m_buffer
, 0, array
, offset
, count
);
235 m_buffer_pos
= count
;
238 Array
.Copy(m_buffer
, 0, array
, offset
, m_buffer_read_ahead
);
239 ret
+= m_buffer_read_ahead
;
240 m_buffer_read_ahead
= 0;
247 public override void Write (byte[] array
, int offset
, int count
)
250 throw new ArgumentNullException ("array");
251 CheckObjectDisposedException ();
252 if (!m_stream
.CanWrite
) {
253 throw new NotSupportedException (
254 Locale
.GetText ("Cannot write to stream"));
257 throw new ArgumentOutOfRangeException ("offset", "< 0");
259 throw new ArgumentOutOfRangeException ("count", "< 0");
260 // avoid possible integer overflow
261 if (array
.Length
- offset
< count
)
262 throw new ArgumentException ("array.Length - offset < count");
264 if (m_buffer_reading
) {
266 m_buffer_reading
= false;
269 // reordered to avoid possible integer overflow
270 if (m_buffer_pos
>= m_buffer
.Length
- count
) {
272 m_stream
.Write (array
, offset
, count
);
275 Array
.Copy (array
, offset
, m_buffer
, m_buffer_pos
, count
);
276 m_buffer_pos
+= count
;
280 private void CheckObjectDisposedException ()
283 throw new ObjectDisposedException ("BufferedStream",
284 Locale
.GetText ("Stream is closed"));