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)
11 using System.Globalization;
12 using System.Runtime.InteropServices;
15 public sealed class BufferedStream : Stream {
19 int m_buffer_read_ahead;
20 bool m_buffer_reading;
21 private bool disposed = false;
23 public BufferedStream (Stream stream) : this (stream, 4096)
27 public BufferedStream (Stream stream, int buffer_size)
30 throw new ArgumentNullException ("stream");
31 // LAMESPEC: documented as < 0
33 throw new ArgumentOutOfRangeException ("buffer_size", "<= 0");
34 if (!stream.CanRead && !stream.CanWrite) {
35 throw new ObjectDisposedException (
36 Locale.GetText ("Cannot access a closed Stream."));
40 m_buffer = new byte [buffer_size];
43 public override bool CanRead {
45 return m_stream.CanRead;
49 public override bool CanWrite {
51 return m_stream.CanWrite;
55 public override bool CanSeek {
57 return m_stream.CanSeek;
61 public override long Length {
64 return m_stream.Length;
68 public override long Position {
70 CheckObjectDisposedException ();
71 return m_stream.Position - m_buffer_read_ahead + m_buffer_pos;
75 if (value < Position && (Position - value <= m_buffer_pos) && m_buffer_reading) {
76 m_buffer_pos -= (int) (Position - value);
78 else if (value > Position && (value - Position < m_buffer_read_ahead - m_buffer_pos) && m_buffer_reading) {
79 m_buffer_pos += (int) (value - Position);
83 m_stream.Position = value;
88 public override void Close ()
98 public override void Flush ()
100 CheckObjectDisposedException ();
102 if (m_buffer_reading) {
104 m_stream.Position = Position;
105 } else if (m_buffer_pos > 0) {
106 m_stream.Write(m_buffer, 0, m_buffer_pos);
109 m_buffer_read_ahead = 0;
113 public override long Seek (long offset, SeekOrigin origin)
115 CheckObjectDisposedException ();
117 throw new NotSupportedException (
118 Locale.GetText ("Non seekable stream."));
121 return m_stream.Seek (offset, origin);
124 public override void SetLength (long value)
126 CheckObjectDisposedException ();
129 throw new ArgumentOutOfRangeException ("value must be positive");
131 if (!m_stream.CanWrite && !m_stream.CanSeek)
132 throw new NotSupportedException ("the stream cannot seek nor write.");
134 if ((m_stream == null) || (!m_stream.CanRead && !m_stream.CanWrite))
135 throw new IOException ("the stream is not open");
137 m_stream.SetLength(value);
138 if (Position > value)
142 public override int ReadByte ()
144 CheckObjectDisposedException ();
146 byte[] b = new byte[1];
148 if (Read(b, 0, 1) == 1) {
155 public override void WriteByte (byte value)
157 CheckObjectDisposedException ();
158 byte[] b = new byte[1];
164 public override int Read ([In,Out] byte[] array, int offset, int count)
167 throw new ArgumentNullException ("array");
168 CheckObjectDisposedException ();
169 if (!m_stream.CanRead) {
170 throw new NotSupportedException (
171 Locale.GetText ("Cannot read from stream"));
174 throw new ArgumentOutOfRangeException ("offset", "< 0");
176 throw new ArgumentOutOfRangeException ("count", "< 0");
177 // re-ordered to avoid possible integer overflow
178 if (array.Length - offset < count)
179 throw new ArgumentException ("array.Length - offset < count");
181 if (!m_buffer_reading) {
183 m_buffer_reading = true;
186 if (count <= m_buffer_read_ahead - m_buffer_pos) {
187 Array.Copy(m_buffer, m_buffer_pos, array, offset, count);
189 m_buffer_pos += count;
190 if (m_buffer_pos == m_buffer_read_ahead) {
192 m_buffer_read_ahead = 0;
198 int ret = m_buffer_read_ahead - m_buffer_pos;
199 Array.Copy(m_buffer, m_buffer_pos, array, offset, ret);
201 m_buffer_read_ahead = 0;
205 if (count >= m_buffer.Length) {
206 ret += m_stream.Read(array, offset, count);
208 m_buffer_read_ahead = m_stream.Read(m_buffer, 0, m_buffer.Length);
210 if (count < m_buffer_read_ahead) {
211 Array.Copy(m_buffer, 0, array, offset, count);
212 m_buffer_pos = count;
215 Array.Copy(m_buffer, 0, array, offset, m_buffer_read_ahead);
216 ret += m_buffer_read_ahead;
217 m_buffer_read_ahead = 0;
224 public override void Write (byte[] array, int offset, int count)
227 throw new ArgumentNullException ("array");
228 CheckObjectDisposedException ();
229 if (!m_stream.CanWrite) {
230 throw new NotSupportedException (
231 Locale.GetText ("Cannot write to stream"));
234 throw new ArgumentOutOfRangeException ("offset", "< 0");
236 throw new ArgumentOutOfRangeException ("count", "< 0");
237 // avoid possible integer overflow
238 if (array.Length - offset < count)
239 throw new ArgumentException ("array.Length - offset < count");
241 if (m_buffer_reading) {
243 m_buffer_reading = false;
246 // reordered to avoid possible integer overflow
247 if (m_buffer_pos >= m_buffer.Length - count) {
249 m_stream.Write (array, offset, count);
252 Array.Copy (array, offset, m_buffer, m_buffer_pos, count);
253 m_buffer_pos += count;
257 private void CheckObjectDisposedException ()
260 throw new ObjectDisposedException ("BufferedStream",
261 Locale.GetText ("Stream is closed"));