2006-06-02 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / corlib / System.IO / BinaryReader.cs
index 0c666ee5ccb7e5683f24ada9b11039d291ba462e..510d9dd58ba74d12d212dc7c0221be839a7e4936 100644 (file)
@@ -41,6 +41,15 @@ namespace System.IO {
                int m_encoding_max_byte;
 
                byte[] m_buffer;
+
+               Decoder decoder;
+               char [] charBuffer;
+               
+               //
+               // 128 chars should cover most strings in one grab.
+               //
+               const int MaxBufferSize = 128;
+
                
                private bool m_disposed = false;
 
@@ -55,7 +64,7 @@ namespace System.IO {
 
                        m_stream = input;
                        m_encoding = encoding;
-                       m_encoding_max_byte = m_encoding.GetMaxByteCount(1);
+                       decoder = encoding.GetDecoder ();
                        m_buffer = new byte [32];
                }
 
@@ -79,6 +88,7 @@ namespace System.IO {
                        m_buffer = null;
                        m_encoding = null;
                        m_stream = null;
+                       charBuffer = null;
                }
 
                void IDisposable.Dispose() 
@@ -308,7 +318,7 @@ namespace System.IO {
                                
                        if (pos!=count) {
                                byte[] new_buffer=new byte[pos];
-                               Buffer.BlockCopy (buf, 0, new_buffer, 0, pos);
+                               Buffer.BlockCopyInternal (buf, 0, new_buffer, 0, pos);
                                return(new_buffer);
                        }
                        
@@ -330,6 +340,9 @@ namespace System.IO {
                                throw new ArgumentOutOfRangeException("count is less than 0");
                        }
 
+                       if (count == 0)
+                               return new char [0];
+                                       
                        char[] full = new char[count];
                        int chars = Read(full, 0, count);
                        
@@ -441,12 +454,44 @@ namespace System.IO {
                         * not chars
                         */
                        int len = Read7BitEncodedInt();
+                       
+                       if (len < 0)
+                               throw new IOException ("Invalid binary file (string len < 0)");
 
-                       FillBuffer(len);
+                       if (len == 0)
+                               return String.Empty;
+                       
                        
-                       char[] str = m_encoding.GetChars(m_buffer, 0, len);
+                       if (charBuffer == null)
+                               charBuffer = new char [MaxBufferSize];
+
+                       //
+                       // We read the string here in small chunks. Also, we
+                       // Attempt to optimize the common case of short strings.
+                       //
+                       StringBuilder sb = null;
+                       do {
+                               int readLen = (len > MaxBufferSize)
+                                               ? MaxBufferSize
+                                               : len;
+                               
+                               FillBuffer (readLen);
+                               
+                               int cch = decoder.GetChars (m_buffer, 0, readLen, charBuffer, 0);
+
+                               if (sb == null && readLen == len) // ok, we got out the easy way, dont bother with the sb
+                                       return new String (charBuffer, 0, cch);
+
+                               if (sb == null)
+                                       // Len is a fairly good estimate of the number of chars in a string
+                                       // Most of the time 1 byte == 1 char
+                                       sb = new StringBuilder (len);
+                               
+                               sb.Append (charBuffer, 0, cch);
+                               len -= readLen;
+                       } while (len > 0);
 
-                       return(new String(str));
+                       return sb.ToString();
                }
 
                public virtual float ReadSingle() {
@@ -497,7 +542,7 @@ namespace System.IO {
                {
                        if(m_buffer.Length <= length) {
                                byte[] new_buffer=new byte[length];
-                               Buffer.BlockCopy (m_buffer, 0, new_buffer, 0, m_buffer.Length);
+                               Buffer.BlockCopyInternal (m_buffer, 0, new_buffer, 0, m_buffer.Length);
                                m_buffer=new_buffer;
                        }
                }