X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.IO%2FBufferedStream.cs;h=d70ad125374d8e875aa5279c474bf3ec635a0eb2;hb=05d6416e37cd1f875786ede96b5a9f09211ab86e;hp=ac7d17a5e23d247378564597b2a93837eff5df63;hpb=ced0e65179064e7258108263baac033b52f16dab;p=mono.git diff --git a/mcs/class/corlib/System.IO/BufferedStream.cs b/mcs/class/corlib/System.IO/BufferedStream.cs index ac7d17a5e23..d70ad125374 100644 --- a/mcs/class/corlib/System.IO/BufferedStream.cs +++ b/mcs/class/corlib/System.IO/BufferedStream.cs @@ -3,7 +3,13 @@ // // Author: // Matt Kimball (matt@kimball.net) +// Ville Palo // +// Copyright (C) 2004 Novell (http://www.novell.com) +// + +using System.Globalization; +using System.Runtime.InteropServices; namespace System.IO { public sealed class BufferedStream : Stream { @@ -12,13 +18,26 @@ namespace System.IO { int m_buffer_pos; int m_buffer_read_ahead; bool m_buffer_reading; + private bool disposed = false; - public BufferedStream(Stream stream) : this(stream, 4096) { + public BufferedStream (Stream stream) : this (stream, 4096) + { } - public BufferedStream(Stream stream, int buffer_size) { + public BufferedStream (Stream stream, int buffer_size) + { + if (stream == null) + throw new ArgumentNullException ("stream"); + // LAMESPEC: documented as < 0 + if (buffer_size <= 0) + throw new ArgumentOutOfRangeException ("buffer_size", "<= 0"); + if (!stream.CanRead && !stream.CanWrite) { + throw new ObjectDisposedException ( + Locale.GetText ("Cannot access a closed Stream.")); + } + m_stream = stream; - m_buffer = new byte[buffer_size]; + m_buffer = new byte [buffer_size]; } public override bool CanRead { @@ -40,34 +59,50 @@ namespace System.IO { } public override long Length { - get { + get { + Flush (); return m_stream.Length; } } public override long Position { get { + CheckObjectDisposedException (); return m_stream.Position - m_buffer_read_ahead + m_buffer_pos; } set { - Flush(); - m_stream.Position = value; + if (value < Position && (Position - value <= m_buffer_pos) && m_buffer_reading) { + m_buffer_pos -= (int) (Position - value); + } + else if (value > Position && (value - Position < m_buffer_read_ahead - m_buffer_pos) && m_buffer_reading) { + m_buffer_pos += (int) (value - Position); + } + else { + Flush(); + m_stream.Position = value; + } } } - public override void Close() { - Flush(); + public override void Close () + { + if (m_buffer != null) + Flush(); + m_stream.Close(); - m_stream = null; m_buffer = null; + disposed = true; } - public override void Flush() { + public override void Flush () + { + CheckObjectDisposedException (); + if (m_buffer_reading) { if (CanSeek) m_stream.Position = Position; - } else { + } else if (m_buffer_pos > 0) { m_stream.Write(m_buffer, 0, m_buffer_pos); } @@ -75,16 +110,29 @@ namespace System.IO { m_buffer_pos = 0; } - public override long Seek(long offset, SeekOrigin origin) { - Flush(); - return m_stream.Seek(offset, origin); + public override long Seek (long offset, SeekOrigin origin) + { + CheckObjectDisposedException (); + if (!CanSeek) { + throw new NotSupportedException ( + Locale.GetText ("Non seekable stream.")); + } + Flush (); + return m_stream.Seek (offset, origin); } - public override void SetLength(long value) { + public override void SetLength (long value) + { + CheckObjectDisposedException (); m_stream.SetLength(value); + if (Position > value) + Position = value; } - public override int ReadByte() { + public override int ReadByte () + { + CheckObjectDisposedException (); + byte[] b = new byte[1]; if (Read(b, 0, 1) == 1) { @@ -94,14 +142,32 @@ namespace System.IO { } } - public override void WriteByte(byte value) { + public override void WriteByte (byte value) + { + CheckObjectDisposedException (); byte[] b = new byte[1]; b[0] = value; Write(b, 0, 1); } - public override int Read(byte[] array, int offset, int count) { + public override int Read ([In,Out] byte[] array, int offset, int count) + { + if (array == null) + throw new ArgumentNullException ("array"); + CheckObjectDisposedException (); + if (!m_stream.CanRead) { + throw new NotSupportedException ( + Locale.GetText ("Cannot read from stream")); + } + if (offset < 0) + throw new ArgumentOutOfRangeException ("offset", "< 0"); + if (count < 0) + throw new ArgumentOutOfRangeException ("count", "< 0"); + // re-ordered to avoid possible integer overflow + if (array.Length - offset < count) + throw new ArgumentException ("array.Length - offset < count"); + if (!m_buffer_reading) { Flush(); m_buffer_reading = true; @@ -145,19 +211,45 @@ namespace System.IO { return ret; } - public override void Write(byte[] array, int offset, int count) { + public override void Write (byte[] array, int offset, int count) + { + if (array == null) + throw new ArgumentNullException ("array"); + CheckObjectDisposedException (); + if (!m_stream.CanWrite) { + throw new NotSupportedException ( + Locale.GetText ("Cannot write to stream")); + } + if (offset < 0) + throw new ArgumentOutOfRangeException ("offset", "< 0"); + if (count < 0) + throw new ArgumentOutOfRangeException ("count", "< 0"); + // avoid possible integer overflow + if (array.Length - offset < count) + throw new ArgumentException ("array.Length - offset < count"); + if (m_buffer_reading) { Flush(); m_buffer_reading = false; } - if (m_buffer_pos + count >= m_buffer.Length) { - Flush(); - m_stream.Write(array, offset, count); - } else { - Array.Copy(array, offset, m_buffer, m_buffer_pos, count); + // reordered to avoid possible integer overflow + if (m_buffer_pos >= m_buffer.Length - count) { + Flush (); + m_stream.Write (array, offset, count); + } + else { + Array.Copy (array, offset, m_buffer, m_buffer_pos, count); m_buffer_pos += count; } } + + private void CheckObjectDisposedException () + { + if (disposed) { + throw new ObjectDisposedException ("BufferedStream", + Locale.GetText ("Stream is closed")); + } + } } }