diff options
Diffstat (limited to 'src/mscorlib/src/System/IO/BinaryReader.cs')
-rw-r--r-- | src/mscorlib/src/System/IO/BinaryReader.cs | 347 |
1 files changed, 208 insertions, 139 deletions
diff --git a/src/mscorlib/src/System/IO/BinaryReader.cs b/src/mscorlib/src/System/IO/BinaryReader.cs index d973860472..54358d601d 100644 --- a/src/mscorlib/src/System/IO/BinaryReader.cs +++ b/src/mscorlib/src/System/IO/BinaryReader.cs @@ -13,54 +13,60 @@ ** ** ============================================================*/ -namespace System.IO { - using System; - using System.Runtime; - using System.Text; - using System.Globalization; - using System.Diagnostics; - using System.Diagnostics.Contracts; - using System.Security; +using System; +using System.Runtime; +using System.Text; +using System.Globalization; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Security; +namespace System.IO +{ public class BinaryReader : IDisposable { private const int MaxCharBytesSize = 128; - private Stream m_stream; - private byte[] m_buffer; - private Decoder m_decoder; - private byte[] m_charBytes; - private char[] m_singleChar; - private char[] m_charBuffer; - private int m_maxCharsSize; // From MaxCharBytesSize & Encoding + private Stream m_stream; + private byte[] m_buffer; + private Decoder m_decoder; + private byte[] m_charBytes; + private char[] m_singleChar; + private char[] m_charBuffer; + private int m_maxCharsSize; // From MaxCharBytesSize & Encoding // Performance optimization for Read() w/ Unicode. Speeds us up by ~40% - private bool m_2BytesPerChar; - private bool m_isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf - private bool m_leaveOpen; + private bool m_2BytesPerChar; + private bool m_isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf + private bool m_leaveOpen; - public BinaryReader(Stream input) : this(input, Encoding.UTF8, false) { + public BinaryReader(Stream input) : this(input, Encoding.UTF8, false) + { } - public BinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) { + public BinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) + { } - public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) { - if (input==null) { + public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) + { + if (input == null) + { throw new ArgumentNullException(nameof(input)); } - if (encoding==null) { + if (encoding == null) + { throw new ArgumentNullException(nameof(encoding)); } if (!input.CanRead) - throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable")); + throw new ArgumentException(SR.Argument_StreamNotReadable); Contract.EndContractBlock(); m_stream = input; m_decoder = encoding.GetDecoder(); m_maxCharsSize = encoding.GetMaxCharCount(MaxCharBytesSize); int minBufferSize = encoding.GetMaxByteCount(1); // max bytes per one char - if (minBufferSize < 16) + if (minBufferSize < 16) minBufferSize = 16; m_buffer = new byte[minBufferSize]; // m_charBuffer and m_charBytes will be left null. @@ -73,21 +79,26 @@ namespace System.IO { m_isMemoryStream = (m_stream.GetType() == typeof(MemoryStream)); m_leaveOpen = leaveOpen; - Debug.Assert(m_decoder!=null, "[BinaryReader.ctor]m_decoder!=null"); + Debug.Assert(m_decoder != null, "[BinaryReader.ctor]m_decoder!=null"); } - public virtual Stream BaseStream { - get { + public virtual Stream BaseStream + { + get + { return m_stream; } } - public virtual void Close() { + public virtual void Close() + { Dispose(true); } - protected virtual void Dispose(bool disposing) { - if (disposing) { + protected virtual void Dispose(bool disposing) + { + if (disposing) + { Stream copyOfStream = m_stream; m_stream = null; if (copyOfStream != null && !m_leaveOpen) @@ -106,10 +117,11 @@ namespace System.IO { Dispose(true); } - public virtual int PeekChar() { + public virtual int PeekChar() + { Contract.Ensures(Contract.Result<int>() >= -1); - if (m_stream==null) __Error.FileNotOpen(); + if (m_stream == null) __Error.FileNotOpen(); if (!m_stream.CanSeek) return -1; @@ -118,59 +130,70 @@ namespace System.IO { m_stream.Position = origPos; return ch; } - - public virtual int Read() { + + public virtual int Read() + { Contract.Ensures(Contract.Result<int>() >= -1); - if (m_stream==null) { + if (m_stream == null) + { __Error.FileNotOpen(); } return InternalReadOneChar(); } - public virtual bool ReadBoolean(){ + public virtual bool ReadBoolean() + { FillBuffer(1); - return (m_buffer[0]!=0); + return (m_buffer[0] != 0); } - public virtual byte ReadByte() { + public virtual byte ReadByte() + { // Inlined to avoid some method call overhead with FillBuffer. - if (m_stream==null) __Error.FileNotOpen(); + if (m_stream == null) __Error.FileNotOpen(); int b = m_stream.ReadByte(); if (b == -1) __Error.EndOfFile(); - return (byte) b; + return (byte)b; } [CLSCompliant(false)] - public virtual sbyte ReadSByte() { + public virtual sbyte ReadSByte() + { FillBuffer(1); return (sbyte)(m_buffer[0]); } - public virtual char ReadChar() { + public virtual char ReadChar() + { int value = Read(); - if (value==-1) { + if (value == -1) + { __Error.EndOfFile(); } return (char)value; } - public virtual short ReadInt16() { + public virtual short ReadInt16() + { FillBuffer(2); return (short)(m_buffer[0] | m_buffer[1] << 8); } [CLSCompliant(false)] - public virtual ushort ReadUInt16(){ + public virtual ushort ReadUInt16() + { FillBuffer(2); return (ushort)(m_buffer[0] | m_buffer[1] << 8); } - public virtual int ReadInt32() { - if (m_isMemoryStream) { - if (m_stream==null) __Error.FileNotOpen(); + public virtual int ReadInt32() + { + if (m_isMemoryStream) + { + if (m_stream == null) __Error.FileNotOpen(); // read directly from MemoryStream buffer MemoryStream mStream = m_stream as MemoryStream; Debug.Assert(mStream != null, "m_stream as MemoryStream != null"); @@ -185,22 +208,25 @@ namespace System.IO { } [CLSCompliant(false)] - public virtual uint ReadUInt32() { + public virtual uint ReadUInt32() + { FillBuffer(4); return (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24); } - public virtual long ReadInt64() { + public virtual long ReadInt64() + { FillBuffer(8); uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24); uint hi = (uint)(m_buffer[4] | m_buffer[5] << 8 | m_buffer[6] << 16 | m_buffer[7] << 24); - return (long) ((ulong)hi) << 32 | lo; + return (long)((ulong)hi) << 32 | lo; } [CLSCompliant(false)] - public virtual ulong ReadUInt64() { + public virtual ulong ReadUInt64() + { FillBuffer(8); uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24); @@ -209,13 +235,15 @@ namespace System.IO { return ((ulong)hi) << 32 | lo; } - public virtual unsafe float ReadSingle() { + public virtual unsafe float ReadSingle() + { FillBuffer(4); uint tmpBuffer = (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24); return *((float*)&tmpBuffer); } - public virtual unsafe double ReadDouble() { + public virtual unsafe double ReadDouble() + { FillBuffer(8); uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24); @@ -226,18 +254,22 @@ namespace System.IO { return *((double*)&tmpBuffer); } - public virtual decimal ReadDecimal() { + public virtual decimal ReadDecimal() + { FillBuffer(16); - try { + try + { return Decimal.ToDecimal(m_buffer); } - catch (ArgumentException e) { + catch (ArgumentException e) + { // ReadDecimal cannot leak out ArgumentException - throw new IOException(Environment.GetResourceString("Arg_DecBitCtor"), e); + throw new IOException(SR.Arg_DecBitCtor, e); } } - public virtual String ReadString() { + public virtual String ReadString() + { Contract.Ensures(Contract.Result<String>() != null); if (m_stream == null) @@ -251,29 +283,34 @@ namespace System.IO { // Length of the string in bytes, not chars stringLength = Read7BitEncodedInt(); - if (stringLength<0) { - throw new IOException(Environment.GetResourceString("IO.IO_InvalidStringLen_Len", stringLength)); + if (stringLength < 0) + { + throw new IOException(SR.Format(SR.IO_InvalidStringLen_Len, stringLength)); } - if (stringLength==0) { + if (stringLength == 0) + { return String.Empty; } - if (m_charBytes==null) { - m_charBytes = new byte[MaxCharBytesSize]; + if (m_charBytes == null) + { + m_charBytes = new byte[MaxCharBytesSize]; } - - if (m_charBuffer == null) { + + if (m_charBuffer == null) + { m_charBuffer = new char[m_maxCharsSize]; } - - StringBuilder sb = null; + + StringBuilder sb = null; do { - readLength = ((stringLength - currPos)>MaxCharBytesSize)?MaxCharBytesSize:(stringLength - currPos); + readLength = ((stringLength - currPos) > MaxCharBytesSize) ? MaxCharBytesSize : (stringLength - currPos); n = m_stream.Read(m_charBytes, 0, readLength); - if (n==0) { + if (n == 0) + { __Error.EndOfFile(); } @@ -285,38 +322,43 @@ namespace System.IO { if (sb == null) sb = StringBuilderCache.Acquire(stringLength); // Actual string length in chars may be smaller. sb.Append(m_charBuffer, 0, charsRead); - currPos +=n; - - } while (currPos<stringLength); + currPos += n; + } while (currPos < stringLength); return StringBuilderCache.GetStringAndRelease(sb); } - public virtual int Read(char[] buffer, int index, int count) { - if (buffer==null) { - throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); + public virtual int Read(char[] buffer, int index, int count) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer); } - if (index < 0) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (index < 0) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_NeedNonNegNum); } - if (count < 0) { - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); } - if (buffer.Length - index < count) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); + if (buffer.Length - index < count) + { + throw new ArgumentException(SR.Argument_InvalidOffLen); } Contract.Ensures(Contract.Result<int>() >= 0); Contract.Ensures(Contract.Result<int>() <= count); Contract.EndContractBlock(); - if (m_stream==null) + if (m_stream == null) __Error.FileNotOpen(); // SafeCritical: index and count have already been verified to be a valid range for the buffer return InternalReadChars(buffer, index, count); } - private int InternalReadChars(char[] buffer, int index, int count) { + private int InternalReadChars(char[] buffer, int index, int count) + { Contract.Requires(buffer != null); Contract.Requires(index >= 0 && count >= 0); Debug.Assert(m_stream != null); @@ -324,11 +366,13 @@ namespace System.IO { int numBytes = 0; int charsRemaining = count; - if (m_charBytes==null) { + if (m_charBytes == null) + { m_charBytes = new byte[MaxCharBytesSize]; } - while (charsRemaining > 0) { + while (charsRemaining > 0) + { int charsRead = 0; // We really want to know what the minimum number of bytes per char // is for our encoding. Otherwise for UnicodeEncoding we'd have to @@ -337,7 +381,8 @@ namespace System.IO { // special case for DecoderNLS subclasses when there is a hanging byte from the previous loop DecoderNLS decoder = m_decoder as DecoderNLS; - if (decoder != null && decoder.HasState && numBytes > 1) { + if (decoder != null && decoder.HasState && numBytes > 1) + { numBytes -= 1; } @@ -360,10 +405,11 @@ namespace System.IO { else { numBytes = m_stream.Read(m_charBytes, 0, numBytes); - byteBuffer = m_charBytes; + byteBuffer = m_charBytes; } - if (numBytes == 0) { + if (numBytes == 0) + { return (count - charsRemaining); } @@ -390,7 +436,7 @@ namespace System.IO { } charsRemaining -= charsRead; - index+=charsRead; + index += charsRead; } // this should never fail @@ -401,7 +447,8 @@ namespace System.IO { return (count - charsRemaining); } - private int InternalReadOneChar() { + private int InternalReadOneChar() + { // I know having a separate InternalReadOneChar method seems a little // redundant, but this makes a scenario like the security parser code // 20% faster, in addition to the optimizations for UnicodeEncoding I @@ -409,18 +456,21 @@ namespace System.IO { int charsRead = 0; int numBytes = 0; long posSav = posSav = 0; - + if (m_stream.CanSeek) posSav = m_stream.Position; - if (m_charBytes==null) { + if (m_charBytes == null) + { m_charBytes = new byte[MaxCharBytesSize]; } - if (m_singleChar==null) { + if (m_singleChar == null) + { m_singleChar = new char[1]; } - while (charsRead == 0) { + while (charsRead == 0) + { // We really want to know what the minimum number of bytes per char // is for our encoding. Otherwise for UnicodeEncoding we'd have to // do ~1+log(n) reads to read n characters. @@ -428,25 +478,27 @@ namespace System.IO { numBytes = m_2BytesPerChar ? 2 : 1; int r = m_stream.ReadByte(); - m_charBytes[0] = (byte) r; + m_charBytes[0] = (byte)r; if (r == -1) numBytes = 0; - if (numBytes == 2) { + if (numBytes == 2) + { r = m_stream.ReadByte(); - m_charBytes[1] = (byte) r; + m_charBytes[1] = (byte)r; if (r == -1) numBytes = 1; } - if (numBytes==0) { + if (numBytes == 0) + { // Console.WriteLine("Found no bytes. We're outta here."); return -1; } Debug.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::InternalReadOneChar assumes it's reading one or 2 bytes only."); - try { - + try + { charsRead = m_decoder.GetChars(m_charBytes, 0, numBytes, m_singleChar, 0); } catch @@ -468,65 +520,74 @@ namespace System.IO { return m_singleChar[0]; } - public virtual char[] ReadChars(int count) { - if (count<0) { - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + public virtual char[] ReadChars(int count) + { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.Ensures(Contract.Result<char[]>() != null); Contract.Ensures(Contract.Result<char[]>().Length <= count); Contract.EndContractBlock(); - if (m_stream == null) { + if (m_stream == null) + { __Error.FileNotOpen(); } - if (count == 0) { - return EmptyArray<Char>.Value; + if (count == 0) + { + return Array.Empty<Char>(); } // SafeCritical: we own the chars buffer, and therefore can guarantee that the index and count are valid char[] chars = new char[count]; int n = InternalReadChars(chars, 0, count); - if (n!=count) { + if (n != count) + { char[] copy = new char[n]; - Buffer.InternalBlockCopy(chars, 0, copy, 0, 2*n); // sizeof(char) + Buffer.InternalBlockCopy(chars, 0, copy, 0, 2 * n); // sizeof(char) chars = copy; } return chars; } - public virtual int Read(byte[] buffer, int index, int count) { - if (buffer==null) - throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); + public virtual int Read(byte[] buffer, int index, int count) + { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer); if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_NeedNonNegNum); if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); + throw new ArgumentException(SR.Argument_InvalidOffLen); Contract.Ensures(Contract.Result<int>() >= 0); Contract.Ensures(Contract.Result<int>() <= count); Contract.EndContractBlock(); - if (m_stream==null) __Error.FileNotOpen(); + if (m_stream == null) __Error.FileNotOpen(); return m_stream.Read(buffer, index, count); } - public virtual byte[] ReadBytes(int count) { - if (count < 0) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + public virtual byte[] ReadBytes(int count) + { + if (count < 0) throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); Contract.Ensures(Contract.Result<byte[]>() != null); Contract.Ensures(Contract.Result<byte[]>().Length <= Contract.OldValue(count)); Contract.EndContractBlock(); - if (m_stream==null) __Error.FileNotOpen(); + if (m_stream == null) __Error.FileNotOpen(); - if (count == 0) { - return EmptyArray<Byte>.Value; + if (count == 0) + { + return Array.Empty<Byte>(); } byte[] result = new byte[count]; int numRead = 0; - do { + do + { int n = m_stream.Read(result, numRead, count); if (n == 0) break; @@ -534,7 +595,8 @@ namespace System.IO { count -= n; } while (count > 0); - if (numRead != result.Length) { + if (numRead != result.Length) + { // Trim array. This should happen on EOF & possibly net streams. byte[] copy = new byte[numRead]; Buffer.InternalBlockCopy(result, 0, copy, 0, numRead); @@ -544,46 +606,53 @@ namespace System.IO { return result; } - protected virtual void FillBuffer(int numBytes) { - if (m_buffer != null && (numBytes < 0 || numBytes > m_buffer.Length)) { - throw new ArgumentOutOfRangeException(nameof(numBytes), Environment.GetResourceString("ArgumentOutOfRange_BinaryReaderFillBuffer")); + protected virtual void FillBuffer(int numBytes) + { + if (m_buffer != null && (numBytes < 0 || numBytes > m_buffer.Length)) + { + throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_BinaryReaderFillBuffer); } - int bytesRead=0; + int bytesRead = 0; int n = 0; - if (m_stream==null) __Error.FileNotOpen(); + if (m_stream == null) __Error.FileNotOpen(); // Need to find a good threshold for calling ReadByte() repeatedly // vs. calling Read(byte[], int, int) for both buffered & unbuffered // streams. - if (numBytes==1) { + if (numBytes == 1) + { n = m_stream.ReadByte(); - if (n==-1) + if (n == -1) __Error.EndOfFile(); m_buffer[0] = (byte)n; return; } - do { - n = m_stream.Read(m_buffer, bytesRead, numBytes-bytesRead); - if (n==0) { + do + { + n = m_stream.Read(m_buffer, bytesRead, numBytes - bytesRead); + if (n == 0) + { __Error.EndOfFile(); } - bytesRead+=n; - } while (bytesRead<numBytes); + bytesRead += n; + } while (bytesRead < numBytes); } - internal protected int Read7BitEncodedInt() { + internal protected int Read7BitEncodedInt() + { // Read out an Int32 7 bits at a time. The high bit // of the byte when on means to continue reading more bytes. int count = 0; int shift = 0; byte b; - do { + do + { // Check for a corrupted stream. Read a max of 5 bytes. // In a future version, add a DataFormatException. if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7 - throw new FormatException(Environment.GetResourceString("Format_Bad7BitInt32")); + throw new FormatException(SR.Format_Bad7BitInt32); // ReadByte handles end of stream cases for us. b = ReadByte(); |