2003-03-05 Gonzalo Paniagua Javier <gonzalo@ximian.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Wed, 5 Mar 2003 11:12:52 +0000 (11:12 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Wed, 5 Mar 2003 11:12:52 +0000 (11:12 -0000)
* MemoryStream.cs: general fixes and reformatted. Passes all tests in
the new MemoryStreamTest.

svn path=/trunk/mcs/; revision=12213

mcs/class/corlib/System.IO/ChangeLog
mcs/class/corlib/System.IO/MemoryStream.cs

index a86996153a878b6db13a40bbd96b5a4aedcb2d1e..c59dfbdf3289448db6602f83a47d85973a6a9982 100644 (file)
@@ -1,3 +1,8 @@
+2003-03-05  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * MemoryStream.cs: general fixes and reformatted. Passes all tests in
+       the new MemoryStreamTest.
+
 2003-03-05  Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * MemoryStream.cs: undo my bogus fix in ToArray. Allow GetBuffer and
index e9b4ac3dfb4f62cddcd30a09e1bced86096c8fe4..d7aa2bf48adb338655f7953517ee1a3343f1e852 100644 (file)
-//\r
-// System.IO.MemoryStream \r
-//\r
-// Author:     Marcin Szczepanski (marcins@zipworld.com.au)\r
-//             Patrik Torstensson\r
-//\r
-// TODO: Clarify some of the lamespec issues\r
-//\r
-\r
-namespace System.IO {\r
-       [Serializable]\r
-        public class MemoryStream : Stream {\r
-                private bool canRead;\r
-                private bool canSeek;\r
-                private bool canWrite;\r
-                \r
-                private bool allowGetBuffer;\r
-\r
-                private int capacity;\r
-\r
-                private byte[] internalBuffer;\r
-\r
-                private int initialLength;\r
-                private bool expandable;\r
-\r
-                private bool streamClosed = false;\r
-\r
-                private long position = 0;\r
-                \r
-                public MemoryStream() {\r
-                        canRead = true;\r
-                        canSeek = true;\r
-                        canWrite = true;\r
-\r
-                        capacity = 0;\r
-\r
-                        internalBuffer = new byte[0];   \r
-\r
-                        allowGetBuffer = true;\r
-                        expandable = true;\r
-                }\r
-\r
-                public MemoryStream( byte[] buffer ) {\r
-                        InternalConstructor( buffer, 0, buffer.Length, true, false );                        \r
-                }\r
-\r
-                public MemoryStream( int capacity ) {\r
-                        \r
-                        canRead = true;\r
-                        canSeek = true;\r
-                        canWrite = true;\r
-                        \r
-                        this.capacity = capacity;\r
-                        initialLength = 0;\r
-                        internalBuffer = new byte [capacity];\r
-\r
-                        expandable = true;\r
-                        allowGetBuffer = true;\r
-                }\r
-\r
-                public MemoryStream( byte[] buffer, bool writeable ) {\r
-                        if( buffer == null ) {\r
-                                throw new ArgumentNullException();\r
-                        }\r
-\r
-                        InternalConstructor( buffer, 0, buffer.Length, writeable, true );\r
-\r
-                }\r
\r
-                public MemoryStream( byte[] buffer, int index, int count ) { \r
-                        if( buffer == null ) {\r
-                                throw new ArgumentNullException();\r
-                        }\r
-                        \r
-                        InternalConstructor( buffer, index, count, true, false );                                        \r
-                }\r
-                \r
-                public MemoryStream( byte[] buffer, int index, int count, bool writeable ) { \r
-                        \r
-                        if( buffer == null ) {\r
-                                throw new ArgumentNullException();\r
-                        }\r
-                        \r
-                        InternalConstructor( buffer, index, count, writeable, true );        \r
-                }\r
-\r
-                public MemoryStream( byte[] buffer, int index, int count, bool writeable, bool publicallyVisible ) {\r
-                        InternalConstructor( buffer, index, count, writeable, publicallyVisible );\r
-                }\r
-\r
-                private void InternalConstructor( byte[] buffer, int index, int count, bool writeable, bool publicallyVisible ) {\r
-                \r
-                        if( buffer == null ) {\r
-                                throw new ArgumentNullException();\r
-                        } else if ( index < 0 || count < 0 ) {\r
-                                throw new ArgumentOutOfRangeException();\r
-                        } else if ( buffer.Length - index < count ) {\r
-                                throw new ArgumentException();\r
-                        }\r
-\r
-                        // LAMESPEC: The spec says to throw an UnauthorisedAccessException if\r
-                        // publicallyVisibile is fale?!  Doesn't that defy the point of having\r
-                        // it there in the first place.  I'll leave it out for now.\r
-                        \r
-                        canRead = true;\r
-                        canSeek = true;\r
-                        canWrite = writeable;\r
-\r
-                        initialLength = count;\r
-\r
-                        internalBuffer = new byte[ count ];\r
-                        capacity = count;\r
-\r
-                       Buffer.BlockCopyInternal (buffer, index, internalBuffer, 0, count);\r
-\r
-                        allowGetBuffer = publicallyVisible;\r
-                        expandable = false;                \r
-                 }\r
-\r
-                 public override bool CanRead {\r
-                        get {\r
-                                return this.canRead;\r
-                        }\r
-                }\r
-\r
-                public override bool CanSeek {\r
-                        get {\r
-                                return this.canSeek;\r
-                        }\r
-                }\r
-\r
-                public override bool CanWrite {\r
-                        get {\r
-                                return this.canWrite;\r
-                        }\r
-                }\r
-\r
-                public virtual int Capacity {\r
-                        get {\r
-                                return this.capacity;\r
-                        }\r
-\r
-                        set {\r
-                                if( value < 0 || value < capacity ) {\r
-                                        throw new ArgumentOutOfRangeException("value",\r
-                                               "New capacity cannot be negative or less than the current capacity" );\r
-                                } else if( !expandable ) {\r
-                                        throw new NotSupportedException( "Cannot expand this MemoryStream" );\r
-                                }\r
-\r
-                                byte[] newBuffer = new byte[ value ];\r
-                               Buffer.BlockCopyInternal (internalBuffer, 0, newBuffer, 0, capacity);\r
-                                capacity = value;\r
-                        }\r
-                }\r
-\r
-                public override long Length {\r
-                        get {\r
-                                // LAMESPEC: The spec says to throw an IOException if the\r
-                                // stream is closed and an ObjectDisposedException if\r
-                                // "methods were called after the stream was closed".  What\r
-                                // is the difference?\r
-\r
-                                if( streamClosed ) {\r
-                                        throw new IOException( "MemoryStream is closed" );\r
-                                }\r
-                                \r
-                                return internalBuffer.Length;\r
-                        }\r
-                }\r
-\r
-                public override long Position {\r
-                        get {\r
-                                if( streamClosed ) {\r
-                                        throw new IOException( "MemoryStream is closed" );\r
-                                }\r
-\r
-                                return position;\r
-                        }\r
-\r
-                        set {\r
-\r
-                                if( position < 0 ) {\r
-                                        throw new ArgumentOutOfRangeException ("value", "Position cannot be negative" );\r
-                               } else if (position > Int32.MaxValue) {\r
-                                        throw new ArgumentOutOfRangeException ("value",\r
-                                                       "Length must be non-negative and less than 2^31 - 1 - origin");\r
-                                } else if( streamClosed ) {\r
-                                        throw new IOException( "MemoryStream is closed" );\r
-                                }\r
-                                \r
-                                position = value;\r
-                        }\r
-                }\r
-                \r
-                public override void Close ()\r
-               {\r
-                       streamClosed = true;\r
-                       expandable = false;\r
-                }\r
-\r
-                public override void Flush() { }\r
-\r
-                public virtual byte[] GetBuffer() {\r
-                        if( !allowGetBuffer ) {\r
-                                throw new UnauthorizedAccessException();\r
-                        }  \r
-\r
-                        return internalBuffer;\r
-                }\r
-\r
-                public override int Read( byte[] buffer, int offset, int count ) {\r
-                        if( buffer == null ) {\r
-                                throw new ArgumentNullException();\r
-                        } else if( offset < 0 || count < 0 ) {\r
-                                throw new ArgumentOutOfRangeException();\r
-                        } else if( buffer.Length - offset < count ) {\r
-                                throw new ArgumentException();\r
-                        } else if ( streamClosed ) {\r
-                                throw new ObjectDisposedException( "MemoryStream" );\r
-                        }\r
-\r
-                        long ReadTo;\r
-\r
-                        if( position + count > internalBuffer.Length ) {\r
-                                ReadTo = internalBuffer.Length;\r
-                        } else {\r
-                                ReadTo = position + (long)count;\r
-                        }\r
-\r
-                       Buffer.BlockCopyInternal (internalBuffer, (int)position, buffer, offset, (int)(ReadTo - position) );\r
-\r
-                        int bytesRead = (int)(ReadTo - position);\r
-\r
-                        position = ReadTo;\r
-\r
-                        return bytesRead;\r
-                }\r
-\r
-                public override int ReadByte( ) {\r
-                        if( streamClosed ) {\r
-                                throw new ObjectDisposedException( "MemoryStream" );\r
-                        }\r
-\r
-\r
-                        // LAMESPEC: What happens if we're at the end of the stream?  It's unspecified in the\r
-                        // docs but tests against the MS impl. show it returns -1\r
-                        //\r
-\r
-                        if( position >= internalBuffer.Length ) {\r
-                                return -1;\r
-                        } else {\r
-                                return internalBuffer[ position++ ];\r
-                        }\r
-                }\r
-                 \r
-                public override long Seek( long offset, SeekOrigin loc ) { \r
-                        long refPoint;\r
-\r
-                        if( streamClosed ) {\r
-                                throw new ObjectDisposedException( "MemoryStream" );\r
-                        }\r
-\r
-                        switch( loc ) {\r
-                                case SeekOrigin.Begin:\r
-                                        refPoint = 0;\r
-                                        break;\r
-                                case SeekOrigin.Current:\r
-                                        refPoint = position;\r
-                                        break;\r
-                                case SeekOrigin.End:\r
-                                        refPoint = internalBuffer.Length;\r
-                                        break;\r
-                                default:\r
-                                        throw new ArgumentException( "Invalid SeekOrigin" );\r
-                        }\r
-\r
-                        // LAMESPEC: My goodness, how may LAMESPECs are there in this\r
-                        // class! :)  In the spec for the Position property it's stated\r
-                        // "The position must not be more than one byte beyond the end of the stream."\r
-                        // In the spec for seek it says "Seeking to any location beyond the length of the \r
-                        // stream is supported."  That's a contradiction i'd say.\r
-                        // I guess seek can go anywhere but if you use position it may get moved back.\r
-\r
-                        if( refPoint + offset < 0 ) {\r
-                                throw new IOException( "Attempted to seek before start of MemoryStream" );\r
-                        } else if( offset > internalBuffer.Length ) {\r
-                                throw new ArgumentOutOfRangeException("offset",\r
-                                               "Offset cannot be greater than length of MemoryStream" );\r
-                        }\r
-\r
-                        position = refPoint + offset;\r
-\r
-                        return position;\r
-                }\r
-                \r
-                \r
-                public override void SetLength( long value ) { \r
-                        if( streamClosed ) {\r
-                                throw new ObjectDisposedException( "MemoryStream" );                        \r
-                        } else if( !expandable && value > capacity ) {\r
-                                throw new NotSupportedException( "Expanding this MemoryStream is not supported" );\r
-                        } else if( !canWrite ) {\r
-                                throw new IOException( "Cannot write to this MemoryStream" );\r
-                        } else if( value < 0 ) {\r
-\r
-                                // LAMESPEC: AGAIN! It says to throw this exception if value is\r
-                                // greater than "the maximum length of the MemoryStream".  I haven't\r
-                                // seen anywhere mention what the maximum length of a MemoryStream is and\r
-                                // since we're this far this memory stream is expandable.\r
-\r
-                                throw new ArgumentOutOfRangeException();\r
-                        } \r
-\r
-                        byte[] newBuffer;\r
-                       newBuffer = new byte[ value ];\r
-                        \r
-                        if (value < internalBuffer.Length) {\r
-                                // truncate\r
-                               Buffer.BlockCopyInternal (internalBuffer, 0, newBuffer, 0, (int)value );\r
-                        } else {\r
-                                // expand\r
-                               Buffer.BlockCopyInternal (internalBuffer, 0, newBuffer, 0, internalBuffer.Length );\r
-                        }\r
-                        internalBuffer = newBuffer;\r
-                        capacity = (int)value;\r
-\r
-                }\r
-                \r
-                \r
-                public virtual byte[] ToArray() { \r
-                        byte[] outBuffer = new byte[capacity];\r
-                       \r
-                       Buffer.BlockCopyInternal (internalBuffer, 0, outBuffer, 0, capacity);\r
-                        return outBuffer; \r
-                }\r
-\r
-                public override void Write( byte[] buffer, int offset, int count ) { \r
-                        if( buffer == null ) {\r
-                                throw new ArgumentNullException();\r
-                        } else if( !canWrite ) {\r
-                                throw new NotSupportedException();\r
-                        } else if( buffer.Length - offset < count ) {\r
-                                throw new ArgumentException();\r
-                        } else if( offset < 0 || count < 0 ) {\r
-                                throw new ArgumentOutOfRangeException();\r
-                        } else if( streamClosed ) {\r
-                                throw new ObjectDisposedException( "MemoryStream" );\r
-                        }\r
-\r
-                       if( position + count > capacity ) {\r
-                               if( expandable ) {\r
-                                       // expand the buffer\r
-                                       SetLength( (position + count) * 2 );\r
-                               } else {\r
-                                       // only write as many bytes as will fit\r
-                                       count = (int)((long)capacity - position);\r
-                               }\r
-                       }\r
-\r
-                       // internal buffer may not be allocated all the way up to capacity\r
-                       // count will already be limited to capacity above if non-expandable\r
-                       if( position + count >= internalBuffer.Length )\r
-                               SetLength ((position + count) * 2);\r
-\r
-                       Buffer.BlockCopyInternal (buffer, offset, internalBuffer, (int)position, count);\r
-                        position += count;\r
-                }\r
-\r
-\r
-                public override void WriteByte( byte value ) { \r
-                        if ( streamClosed )\r
-                                throw new ObjectDisposedException( "MemoryStream" );\r
-                       else if( !canWrite || (position >= capacity && !expandable))\r
-                                throw new NotSupportedException();\r
-\r
-                       if( position >= internalBuffer.Length )\r
-                               SetLength ((position + 1) * 2);\r
-\r
-                       internalBuffer[ position++ ] = value;\r
-                }\r
-                \r
-\r
-                public virtual void WriteTo( Stream stream ) { \r
-                       if (streamClosed)\r
-                               throw new ObjectDisposedException ("MemoryStream");\r
-\r
-                        if( stream == null ) {\r
-                                throw new ArgumentNullException();\r
-                        }\r
-\r
-                        stream.Write( internalBuffer, 0, internalBuffer.Length );\r
-                \r
-                }\r
-                               \r
-                       \r
-        }               \r
-\r
-\r
-}                      \r
+//
+// System.IO.MemoryStream 
+//
+// Authors:    Marcin Szczepanski (marcins@zipworld.com.au)
+//             Patrik Torstensson
+//             Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (c) 2001,2002 Marcin Szczepanski, Patrik Torstensson
+// (c) 2003 Ximian, Inc. (http://www.ximian.com)
+//
+
+namespace System.IO
+{
+       [Serializable]
+       public class MemoryStream : Stream
+       {
+               bool canWrite;
+               bool allowGetBuffer;
+               int capacity;
+               int length;
+               byte [] internalBuffer;
+               int initialIndex;
+               bool expandable;
+               bool streamClosed;
+               int position;
+
+               public MemoryStream () : this (0)
+               {
+               }
+
+               public MemoryStream (int capacity)
+               {
+                       if (capacity < 0)
+                               throw new ArgumentOutOfRangeException ("capacity");
+
+                       canWrite = true;
+
+                       this.capacity = capacity;
+                       internalBuffer = new byte [capacity];
+
+                       expandable = true;
+                       allowGetBuffer = true;
+               }
+
+               public MemoryStream (byte [] buffer)
+               {
+                       InternalConstructor (buffer, 0, buffer.Length, true, false);                        
+               }
+
+               public MemoryStream (byte [] buffer, bool writeable)
+               {
+                       InternalConstructor (buffer, 0, buffer.Length, writeable, false);
+               }
+
+               public MemoryStream (byte [] buffer, int index, int count)
+               {
+                       InternalConstructor (buffer, index, count, true, false);
+               }
+
+               public MemoryStream (byte [] buffer, int index, int count, bool writeable)
+               {
+                       InternalConstructor (buffer, index, count, writeable, false);
+               }
+
+               public MemoryStream (byte [] buffer, int index, int count, bool writeable, bool publicallyVisible)
+               {
+                       InternalConstructor (buffer, index, count, writeable, publicallyVisible);
+               }
+
+               void InternalConstructor (byte [] buffer, int index, int count, bool writeable, bool publicallyVisible)
+               {
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (index < 0 || count < 0)
+                               throw new ArgumentOutOfRangeException ("index or count is less than 0.");
+
+                       if (buffer.Length - index < count)
+                               throw new ArgumentException ("index+count", 
+                                                            "The size of the buffer is less than index + count.");
+
+                       canWrite = writeable;
+
+                       internalBuffer = buffer;
+                       capacity = count + index;
+                       length = capacity;
+                       position = index;
+                       initialIndex = index;
+
+                       allowGetBuffer = publicallyVisible;
+                       expandable = false;                
+               }
+
+               void CheckIfClosedThrowDisposed ()
+               {
+                       if (streamClosed)
+                               throw new ObjectDisposedException ("MemoryStream");
+               }
+               
+               void CheckIfClosedThrowIO ()
+               {
+                       if (streamClosed)
+                               throw new IOException ("MemoryStream is closed");
+               }
+               
+               public override bool CanRead {
+                       get { return !streamClosed; }
+               }
+
+               public override bool CanSeek {
+                       get { return !streamClosed; }
+               }
+
+               public override bool CanWrite {
+                       get { return (!streamClosed && canWrite); }
+               }
+
+               public virtual int Capacity {
+                       get {
+                               CheckIfClosedThrowDisposed ();
+                               return capacity - initialIndex;
+                       }
+
+                       set {
+                               CheckIfClosedThrowDisposed ();
+                               if (value == capacity)
+                                       return; // LAMENESS: see MemoryStreamTest.ConstructorFive
+
+                               if (!expandable)
+                                       throw new NotSupportedException ("Cannot expand this MemoryStream");
+
+                               if (value < 0 || value < length)
+                                       throw new ArgumentOutOfRangeException ("value",
+                                       "New capacity cannot be negative or less than the current capacity " + value + " " + capacity);
+
+                               byte [] newBuffer = null;
+                               if (value != 0) {
+                                       newBuffer = new byte [value];
+                                       Buffer.BlockCopyInternal (internalBuffer, 0, newBuffer, 0, length);
+                               }
+
+                               internalBuffer = newBuffer; // It's null when capacity is set to 0
+                               capacity = value;
+                       }
+               }
+
+               public override long Length {
+                       get {
+                               // LAMESPEC: The spec says to throw an IOException if the
+                               // stream is closed and an ObjectDisposedException if
+                               // "methods were called after the stream was closed".  What
+                               // is the difference?
+
+                               CheckIfClosedThrowIO ();
+
+                               // This is ok for MemoryStreamTest.ConstructorFive
+                               return length - initialIndex;
+                       }
+               }
+
+               public override long Position {
+                       get {
+                               CheckIfClosedThrowIO ();
+                               return position - initialIndex;
+                       }
+
+                       set {
+                               CheckIfClosedThrowIO ();
+                               if (value < 0)
+                                       throw new ArgumentOutOfRangeException ("value",
+                                                               "Position cannot be negative" );
+
+                               if (value > Int32.MaxValue)
+                                       throw new ArgumentOutOfRangeException ("value",
+                                       "Position must be non-negative and less than 2^31 - 1 - origin");
+
+                               position = initialIndex + (int) value;
+                       }
+               }
+
+               public override void Close ()
+               {
+                       streamClosed = true;
+                       expandable = false;
+               }
+
+               public override void Flush ()
+               {
+                       // Do nothing
+               }
+
+               public virtual byte [] GetBuffer ()
+               {
+                       if (!allowGetBuffer)
+                               throw new UnauthorizedAccessException ();
+
+                       return internalBuffer;
+               }
+
+               public override int Read (byte [] buffer, int offset, int count)
+               {
+                       CheckIfClosedThrowDisposed ();
+
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (offset < 0 || count < 0)
+                               throw new ArgumentOutOfRangeException ("offset or count less than zero.");
+
+                       if (buffer.Length - offset < count )
+                               throw new ArgumentException ("offset+count",
+                                                             "The size of the buffer is less than offset + count.");
+
+                       if (position >= length || count == 0)
+                               return 0;
+
+                       if (position > length - count)
+                               count = length - position;
+
+                       Buffer.BlockCopyInternal (internalBuffer, position, buffer, offset, count);
+                       position += count;
+                       return count;
+               }
+
+               public override int ReadByte ()
+               {
+                       CheckIfClosedThrowDisposed ();
+                       if (position >= length)
+                               return -1;
+
+                       return internalBuffer [position++];
+               }
+
+               public override long Seek (long offset, SeekOrigin loc)
+               {
+                       CheckIfClosedThrowDisposed ();
+
+                       // It's funny that they don't throw this exception for < Int32.MinValue
+                       if (offset > (long) Int32.MaxValue)
+                               throw new ArgumentOutOfRangeException ("Offset out of range. " + offset);
+
+                       int refPoint;
+                       switch (loc) {
+                       case SeekOrigin.Begin:
+                               if (offset < 0)
+                                       throw new IOException ("Attempted to seek before start of MemoryStream.");
+                               refPoint = initialIndex;
+                               break;
+                       case SeekOrigin.Current:
+                               refPoint = position;
+                               break;
+                       case SeekOrigin.End:
+                               refPoint = length;
+                               break;
+                       default:
+                               throw new ArgumentException ("loc", "Invalid SeekOrigin");
+                       }
+
+                       // LAMESPEC: My goodness, how may LAMESPECs are there in this
+                       // class! :)  In the spec for the Position property it's stated
+                       // "The position must not be more than one byte beyond the end of the stream."
+                       // In the spec for seek it says "Seeking to any location beyond the length of the 
+                       // stream is supported."  That's a contradiction i'd say.
+                       // I guess seek can go anywhere but if you use position it may get moved back.
+
+                       refPoint += (int) offset;
+                       if (refPoint < initialIndex)
+                               throw new IOException ("Attempted to seek before start of MemoryStream.");
+
+                       position = refPoint;
+                       return position;
+               }
+
+               int CalculateNewCapacity (int minimum)
+               {
+                       if (minimum < 256)
+                               minimum = 256; // See GetBufferTwo test
+
+                       if (minimum < capacity * 2)
+                               minimum = capacity * 2;
+
+                       return minimum;
+               }
+
+               public override void SetLength (long value)
+               {
+                       CheckIfClosedThrowDisposed ();
+                       if (!expandable && value > capacity)
+                               throw new NotSupportedException ("Expanding this MemoryStream is not supported");
+
+                       if (!canWrite)
+                               throw new IOException ("Cannot write to this MemoryStream");
+
+                       // LAMESPEC: AGAIN! It says to throw this exception if value is
+                       // greater than "the maximum length of the MemoryStream".  I haven't
+                       // seen anywhere mention what the maximum length of a MemoryStream is and
+                       // since we're this far this memory stream is expandable.
+                       if (value < 0 || (value + initialIndex) > (long) Int32.MaxValue)
+                               throw new ArgumentOutOfRangeException ();
+
+                       int newSize = (int) value + initialIndex;
+                       if (newSize > capacity) {
+                               Capacity = CalculateNewCapacity (newSize);
+                       } else if (newSize > length) {
+                               for (int i = newSize; i < length; i++)
+                                       Buffer.SetByte (internalBuffer, i, 0);
+                       }
+
+                       length = newSize;
+                       if (position > length)
+                               position = length;
+               }
+
+               public virtual byte [] ToArray ()
+               {
+                       int l = length - initialIndex;
+                       byte[] outBuffer = new byte [l];
+
+                       Buffer.BlockCopyInternal (internalBuffer, initialIndex, outBuffer, 0, l);
+                       return outBuffer; 
+               }
+
+               public override void Write (byte [] buffer, int offset, int count)
+               {
+                       CheckIfClosedThrowDisposed ();
+
+                       if (!canWrite)
+                               throw new NotSupportedException ("Cannot write to this stream.");
+
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+                       
+                       if (offset < 0 || count < 0)
+                               throw new ArgumentOutOfRangeException ();
+
+                       if (buffer.Length - offset < count)
+                               throw new ArgumentException ("offset+count",
+                                                            "The size of the buffer is less than offset + count.");
+
+                       if (position + count > capacity)
+                               Capacity = CalculateNewCapacity (position + count);
+
+                       Buffer.BlockCopyInternal (buffer, offset, internalBuffer, position, count);
+                       position += count;
+                       if (position >= length)
+                               length = position;
+               }
+
+               public override void WriteByte (byte value)
+               {
+                       CheckIfClosedThrowDisposed ();
+                       if (!canWrite)
+                               throw new NotSupportedException ("Cannot write to this stream.");
+
+                       if (position + 1 >= capacity)
+                               Capacity = CalculateNewCapacity (position + 1);
+
+                       if (position >= length)
+                               length = position + 1;
+
+                       internalBuffer [position++] = value;
+               }
+
+               public virtual void WriteTo (Stream stream)
+               {
+                       CheckIfClosedThrowDisposed ();
+
+                       if (stream == null)
+                               throw new ArgumentNullException ("stream");
+
+                       stream.Write (internalBuffer, initialIndex, length - initialIndex);
+               }
+       }               
+}                      
+