2004-12-03 Lluis Sanchez Gual <lluis@novell.com>
[mono.git] / mcs / class / corlib / System.IO / BinaryReader.cs
index 2449f23d3b5079df001b324b3796d3cedb309e9d..7958b70efb0a40521488a6e03209415214e26922 100644 (file)
@@ -6,6 +6,29 @@
 //   Dick Porter (dick@ximian.com)
 //
 
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.Text;
 using System.Globalization;
@@ -17,8 +40,10 @@ namespace System.IO {
                int m_encoding_max_byte;
 
                byte[] m_buffer;
+               
+               private bool m_disposed = false;
 
-               public BinaryReader(Stream input) : this(input, Encoding.UTF8) {
+               public BinaryReader(Stream input) : this(input, Encoding.UTF8Unmarked) {
                }
 
                public BinaryReader(Stream input, Encoding encoding) {
@@ -41,6 +66,7 @@ namespace System.IO {
 
                public virtual void Close() {
                        Dispose (true);
+                       m_disposed = true;
                }
                
                protected virtual void Dispose (bool disposing)
@@ -48,6 +74,7 @@ namespace System.IO {
                        if (disposing && m_stream != null)
                                m_stream.Close ();
 
+                       m_disposed = true;
                        m_buffer = null;
                        m_encoding = null;
                        m_stream = null;
@@ -58,15 +85,18 @@ namespace System.IO {
                        Dispose (true);
                }
 
-               protected virtual void FillBuffer(int bytes) {
-                       if(m_stream==null) {
+               protected virtual void FillBuffer (int bytes)
+               {
+                       if (m_disposed)
+                               throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader.");
+                       if (m_stream==null)
                                throw new IOException("Stream is invalid");
-                       }
                        
                        CheckBuffer(bytes);
 
                        /* Cope with partial reads */
                        int pos=0;
+
                        while(pos<bytes) {
                                int n=m_stream.Read(m_buffer, pos, bytes-pos);
                                if(n==0) {
@@ -79,18 +109,35 @@ namespace System.IO {
 
                public virtual int PeekChar() {
                        if(m_stream==null) {
+                               
+                               if (m_disposed)
+                                       throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader.");
+
                                throw new IOException("Stream is invalid");
                        }
 
-                       if(!m_stream.CanSeek) {
-                               return(-1);
+                       if ( !m_stream.CanSeek )
+                       {
+                               return -1;
                        }
 
-                       long pos=m_stream.Position;
-                       int ch=Read();
-                       m_stream.Position=pos;
+                       char[] result = new char[1];
+                       byte[] bytes;
+                       int bcount;
+
+                       int ccount = ReadCharBytes (result, 0, 1, out bytes, out bcount);
+
+                       // Reposition the stream
+                       m_stream.Position -= bcount;
 
-                       return(ch);
+                       // If we read 0 characters then return -1
+                       if (ccount == 0) 
+                       {
+                               return -1;
+                       }
+                       
+                       // Return the single character we read
+                       return result[0];
                }
 
                public virtual int Read() {
@@ -107,21 +154,25 @@ namespace System.IO {
 
                public virtual int Read(byte[] buffer, int index, int count) {
                        if(m_stream==null) {
+
+                               if (m_disposed)
+                                       throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader.");
+
                                throw new IOException("Stream is invalid");
                        }
                        
                        if (buffer == null) {
                                throw new ArgumentNullException("buffer is null");
                        }
-                       if (buffer.Length - index < count) {
-                               throw new ArgumentException("buffer is too small");
-                       }
                        if (index < 0) {
                                throw new ArgumentOutOfRangeException("index is less than 0");
                        }
                        if (count < 0) {
                                throw new ArgumentOutOfRangeException("count is less than 0");
                        }
+                       if (buffer.Length - index < count) {
+                               throw new ArgumentException("buffer is too small");
+                       }
 
                        int bytes_read=m_stream.Read(buffer, index, count);
 
@@ -129,44 +180,61 @@ namespace System.IO {
                }
 
                public virtual int Read(char[] buffer, int index, int count) {
+
                        if(m_stream==null) {
+
+                               if (m_disposed)
+                                       throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader.");
+
                                throw new IOException("Stream is invalid");
                        }
                        
                        if (buffer == null) {
                                throw new ArgumentNullException("buffer is null");
                        }
-                       if (buffer.Length - index < count) {
-                               throw new ArgumentException("buffer is too small");
-                       }
                        if (index < 0) {
                                throw new ArgumentOutOfRangeException("index is less than 0");
                        }
                        if (count < 0) {
                                throw new ArgumentOutOfRangeException("count is less than 0");
                        }
+                       if (buffer.Length - index < count) {
+                               throw new ArgumentException("buffer is too small");
+                       }
 
+                       int bytes_read;
+                       byte[] bytes;
+                       return ReadCharBytes (buffer, index, count, out bytes, out bytes_read);
+               }
+
+               private int ReadCharBytes(char[] buffer, int index, int count, out byte[] bytes, out int bytes_read) \r
+               {
                        int chars_read=0;
-                       int bytes_read=0;
+                       bytes_read=0;
                        
-                       while(chars_read < count) {
-                               CheckBuffer(bytes_read);
+                       while(chars_read < count) 
+                       {
+                               CheckBuffer(bytes_read + 1);
+
+                               int read_byte = m_stream.ReadByte();
 
-                               int read_byte=m_stream.ReadByte();
-                               if(read_byte==-1) {
+                               if(read_byte==-1) 
+                               {
                                        /* EOF */
+                                       bytes = m_buffer;
                                        return(chars_read);
                                }
 
                                m_buffer[bytes_read]=(byte)read_byte;
                                bytes_read++;
-                               
+
                                chars_read=m_encoding.GetChars(m_buffer, 0,
-                                                              bytes_read,
-                                                              buffer, index);
+                                                                                bytes_read,
+                                                                                buffer, index);
                                
                        }
 
+                       bytes = m_buffer;
                        return(chars_read);
                }
 
@@ -186,21 +254,25 @@ namespace System.IO {
                }
 
                public virtual bool ReadBoolean() {
-                       FillBuffer(1);
-
                        // Return value:
                        //  true if the byte is non-zero; otherwise false.
-                       return(m_buffer[0] != 0);
+                       return ReadByte() != 0;
                }
 
                public virtual byte ReadByte() {
-                       FillBuffer(1);
-
-                       return(m_buffer[0]);
+                       int val = m_stream.ReadByte ();
+                       if (val != -1)
+                               return (byte) val;
+                       
+                       throw new EndOfStreamException ();
                }
 
                public virtual byte[] ReadBytes(int count) {
                        if(m_stream==null) {
+
+                               if (m_disposed)
+                                       throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader.");
+
                                throw new IOException("Stream is invalid");
                        }
                        
@@ -215,7 +287,8 @@ namespace System.IO {
                        byte[] buf = new byte[count];
                        int pos=0;
                        
-                       while(pos < count) {
+                       while(pos < count) \r
+                       {
                                int n=m_stream.Read(buf, pos, count-pos);
                                if(n==0) {
                                        /* EOF */
@@ -269,7 +342,28 @@ namespace System.IO {
                        decimal ret;
                        byte* ret_ptr = (byte *)&ret;
                        for (int i = 0; i < 16; i++) {
-                               ret_ptr[i] = m_buffer[i];
+                         
+                               /*
+                                * internal representation of decimal is 
+                                * ss32, hi32, lo32, mi32, 
+                                * but in stream it is 
+                                * lo32, mi32, hi32, ss32
+                                * So we have to rerange this int32 values
+                                */                       
+                         
+                               if (i < 4) {
+                                       // lo 8 - 12                      
+                                       ret_ptr [i + 8] = m_buffer [i];
+                               } else if (i < 8) {
+                                       // mid 12 - 16
+                                       ret_ptr [i + 8] = m_buffer [i];
+                               } else if (i < 12) {
+                                       // hi 4 - 8
+                                       ret_ptr [i - 4] = m_buffer [i];
+                               } else if (i < 16) {
+                                       // ss 0 - 4
+                                       ret_ptr [i - 12] = m_buffer [i];
+                               }                               
                        }
 
                        return ret;
@@ -312,9 +406,7 @@ namespace System.IO {
 
                [CLSCompliant(false)]
                public virtual sbyte ReadSByte() {
-                       FillBuffer(1);
-
-                       return((sbyte)m_buffer[0]);
+                       return (sbyte) ReadByte ();
                }
 
                public virtual string ReadString() {