X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.IO%2FBinaryReader.cs;h=d7b92b38541e42a0d7888c6f06acf15fb94c85f1;hb=a0173a7e76ad48889ade46116e516731b170e7c5;hp=600b2ca2ed0e4e55e91405758ed6cbe5f3f762b8;hpb=b87c7e29df7d04e3199e224c8b8e9a41292cec1b;p=mono.git diff --git a/mcs/class/corlib/System.IO/BinaryReader.cs b/mcs/class/corlib/System.IO/BinaryReader.cs index 600b2ca2ed0..d7b92b38541 100644 --- a/mcs/class/corlib/System.IO/BinaryReader.cs +++ b/mcs/class/corlib/System.IO/BinaryReader.cs @@ -4,10 +4,12 @@ // Author: // Matt Kimball (matt@kimball.net) // Dick Porter (dick@ximian.com) +// Marek Safar (marek.safar@gmail.com) // // // Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// Copyright 2011 Xamarin Inc. // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -33,14 +35,10 @@ using System; using System.Text; using System.Globalization; using Mono.Security; -#if NET_2_0 using System.Runtime.InteropServices; -#endif namespace System.IO { -#if NET_2_0 [ComVisible (true)] -#endif public class BinaryReader : IDisposable { Stream m_stream; Encoding m_encoding; @@ -48,7 +46,8 @@ namespace System.IO { byte[] m_buffer; Decoder decoder; - char [] charBuffer; + char[] charBuffer; + byte[] charByteBuffer; // // 128 chars should cover most strings in one grab. @@ -56,12 +55,28 @@ namespace System.IO { const int MaxBufferSize = 128; - private bool m_disposed = false; - - public BinaryReader(Stream input) : this(input, Encoding.UTF8UnmarkedUnsafe) { + private bool m_disposed; + + public BinaryReader(Stream input) + : this(input, Encoding.UTF8UnmarkedUnsafe) + { } - - public BinaryReader(Stream input, Encoding encoding) { + +#if NET_4_5 + readonly bool leave_open; + + public BinaryReader(Stream input, Encoding encoding) + : this (input, encoding, false) + { + } + + public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) +#else + const bool leave_open = false; + + public BinaryReader(Stream input, Encoding encoding) +#endif + { if (input == null || encoding == null) throw new ArgumentNullException(Locale.GetText ("Input or Encoding is a null reference.")); if (!input.CanRead) @@ -69,8 +84,14 @@ namespace System.IO { m_stream = input; m_encoding = encoding; +#if NET_4_5 + leave_open = leaveOpen; +#endif decoder = encoding.GetDecoder (); - m_buffer = new byte [32]; + + // internal buffer size is documented to be between 16 and the value + // returned by GetMaxByteCount for the specified encoding + m_buffer = new byte [Math.Max (16, encoding.GetMaxByteCount (1))]; } public virtual Stream BaseStream { @@ -86,7 +107,7 @@ namespace System.IO { protected virtual void Dispose (bool disposing) { - if (disposing && m_stream != null) + if (disposing && m_stream != null && !leave_open) m_stream.Close (); m_disposed = true; @@ -96,20 +117,24 @@ namespace System.IO { charBuffer = null; } +#if NET_4_0 + public void Dispose () +#else void IDisposable.Dispose() +#endif { Dispose (true); } protected virtual void FillBuffer (int numBytes) { + if (numBytes > m_buffer.Length) + throw new ArgumentOutOfRangeException ("numBytes"); if (m_disposed) throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader."); if (m_stream==null) throw new IOException("Stream is invalid"); - CheckBuffer(numBytes); - /* Cope with partial reads */ int pos=0; @@ -343,26 +368,36 @@ namespace System.IO { return((char)ch); } - public virtual char[] ReadChars(int count) { + public virtual char[] ReadChars (int count) + { if (count < 0) { throw new ArgumentOutOfRangeException("count is less than 0"); } + if (m_stream == null) { + if (m_disposed) + throw new ObjectDisposedException ("BinaryReader", "Cannot read from a closed BinaryReader."); + + throw new IOException("Stream is invalid"); + } + if (count == 0) - return new char [0]; + return EmptyArray.Value; char[] full = new char[count]; - int chars = Read(full, 0, count); + int bytes_read; + int chars = ReadCharBytes (full, 0, count, out bytes_read); - if (chars == 0) { + if (chars == 0) throw new EndOfStreamException(); - } else if (chars != full.Length) { - char[] ret = new char[chars]; - Array.Copy(full, 0, ret, 0, chars); - return ret; - } else { - return full; + + if (chars != count) { + var new_buffer = new char[chars]; + Buffer.BlockCopyInternal (full, 0, new_buffer, 0, 2 * chars); + return new_buffer; } + + return full; } unsafe public virtual decimal ReadDecimal() { @@ -469,9 +504,10 @@ namespace System.IO { if (len == 0) return String.Empty; - - if (charBuffer == null) - charBuffer = new char [MaxBufferSize]; + if (charByteBuffer == null) { + charBuffer = new char [m_encoding.GetMaxByteCount (MaxBufferSize)]; + charByteBuffer = new byte [MaxBufferSize]; + } // // We read the string here in small chunks. Also, we @@ -479,13 +515,13 @@ namespace System.IO { // StringBuilder sb = null; do { - int readLen = (len > MaxBufferSize) - ? MaxBufferSize - : len; + int readLen = Math.Min (MaxBufferSize, len); - FillBuffer (readLen); + readLen = m_stream.Read (charByteBuffer, 0, readLen); + if (readLen == 0) + throw new EndOfStreamException(); - int cch = decoder.GetChars (m_buffer, 0, readLen, charBuffer, 0); + int cch = decoder.GetChars (charByteBuffer, 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);