Преглед изворни кода

* BinaryReader.cs: internal buffer fix. Little-endian conversions.
* BinaryWriter.cs: little-endian conversions.

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

Sergey Chaban пре 24 година
родитељ
комит
fc3048b245

+ 49 - 18
mcs/class/corlib/System.IO/BinaryReader.cs

@@ -7,6 +7,7 @@
 
 using System;
 using System.Text;
+using System.Globalization;
 
 namespace System.IO {
 	public class BinaryReader : IDisposable {
@@ -24,13 +25,14 @@ namespace System.IO {
 
 		public BinaryReader(Stream input, Encoding encoding) {
 			if (input == null || encoding == null) 
-				throw new ArgumentNullException();
+				throw new ArgumentNullException(Locale.GetText ("Input or Encoding is a null reference."));
 			if (!input.CanRead)
-				throw new ArgumentException();
+				throw new ArgumentException(Locale.GetText ("The stream doesn't support reading."));
 
 			m_stream = input;
 			m_encoding = encoding;
 			m_encoding_max_byte = m_encoding.GetMaxByteCount(1);
+			m_buffer = new byte [32];
 		}
 
 		public virtual Stream BaseStream {
@@ -153,7 +155,9 @@ namespace System.IO {
 				throw new EndOfStreamException();
 			}
 
-			bool ret = BitConverter.ToBoolean(m_buffer, m_buffer_pos);
+			// Return value:
+			//  true if the byte is non-zero; otherwise false.
+			bool ret = (m_buffer[m_buffer_pos] != 0);
 			ConsumeBuffered(1);
 			return ret;
 		}
@@ -240,18 +244,22 @@ namespace System.IO {
 				throw new EndOfStreamException();
 			}
 
-			short ret = BitConverter.ToInt16(m_buffer, m_buffer_pos);
+			short ret = (short) (m_buffer[m_buffer_pos] | (m_buffer[m_buffer_pos + 1] << 8));
 			ConsumeBuffered(2);
 			return ret;
 		}
 
 		public virtual int ReadInt32() {
-			if (!EnsureBuffered(1)) {
+			if (!EnsureBuffered(4)) {
 				throw new EndOfStreamException();
 			}
 
-			int ret = BitConverter.ToInt32(m_buffer, m_buffer_pos);
-			ConsumeBuffered(1);
+			int ret = (m_buffer[m_buffer_pos]             |
+			           (m_buffer[m_buffer_pos + 1] << 8)  |
+			           (m_buffer[m_buffer_pos + 2] << 16) |
+			           (m_buffer[m_buffer_pos + 3] << 24)
+			          );
+			ConsumeBuffered(4);
 			return ret;
 		}
 
@@ -260,9 +268,18 @@ namespace System.IO {
 				throw new EndOfStreamException();
 			}
 
-			long ret = BitConverter.ToInt64(m_buffer, m_buffer_pos);
+			uint ret_low  = (uint) (m_buffer[m_buffer_pos]            |
+			                       (m_buffer[m_buffer_pos + 1] << 8)  |
+			                       (m_buffer[m_buffer_pos + 2] << 16) |
+			                       (m_buffer[m_buffer_pos + 3] << 24)
+			                       );
+			uint ret_high = (uint) (m_buffer[m_buffer_pos + 4]        |
+			                       (m_buffer[m_buffer_pos + 5] << 8)  |
+			                       (m_buffer[m_buffer_pos + 6] << 16) |
+			                       (m_buffer[m_buffer_pos + 7] << 24)
+			                       );
 			ConsumeBuffered(8);
-			return ret;
+			return (long) ((((ulong) ret_high) << 32) | ret_low);
 		}
 
 		[CLSCompliant(false)]
@@ -307,7 +324,7 @@ namespace System.IO {
 				throw new EndOfStreamException();
 			}
 
-			ushort ret = BitConverter.ToUInt16(m_buffer, m_buffer_pos);
+			ushort ret = (ushort) (m_buffer[m_buffer_pos] | (m_buffer[m_buffer_pos + 1] << 8));
 			ConsumeBuffered(2);
 			return ret;
 		}
@@ -318,7 +335,11 @@ namespace System.IO {
 				throw new EndOfStreamException();
 			}
 
-			uint ret = BitConverter.ToUInt32(m_buffer, m_buffer_pos);
+			uint ret = (uint) (m_buffer[m_buffer_pos]            |
+			                  (m_buffer[m_buffer_pos + 1] << 8)  |
+			                  (m_buffer[m_buffer_pos + 2] << 16) |
+			                  (m_buffer[m_buffer_pos + 3] << 24)
+			                  );
 			ConsumeBuffered(4);
 			return ret;
 		}
@@ -329,24 +350,37 @@ namespace System.IO {
 				throw new EndOfStreamException();
 			}
 
-			ulong ret = BitConverter.ToUInt64(m_buffer, m_buffer_pos);
+			uint ret_low  = (uint) (m_buffer[m_buffer_pos]            |
+			                       (m_buffer[m_buffer_pos + 1] << 8)  |
+			                       (m_buffer[m_buffer_pos + 2] << 16) |
+			                       (m_buffer[m_buffer_pos + 3] << 24)
+			                       );
+			uint ret_high = (uint) (m_buffer[m_buffer_pos + 4]        |
+			                       (m_buffer[m_buffer_pos + 5] << 8)  |
+			                       (m_buffer[m_buffer_pos + 6] << 16) |
+			                       (m_buffer[m_buffer_pos + 7] << 24)
+			                       );
 			ConsumeBuffered(8);
-			return ret;
+			return (((ulong) ret_high) << 32) | ret_low;
 		}
 
 		
 		bool EnsureBuffered(int bytes) {
 			int needed = bytes - (m_buffer_used - m_buffer_pos);
-			if (needed <= 0)
+			if (needed < 0)
 				return true;
 
 			if (m_buffer_used + needed > m_buffer.Length) {
 				byte[] old_buffer = m_buffer;
 				m_buffer = new byte[m_buffer_used + needed];
 				Array.Copy(old_buffer, 0, m_buffer, 0, m_buffer_used);
+				m_buffer_pos = m_buffer_used;
 			}
 
-			m_buffer_used += m_stream.Read(m_buffer, m_buffer_used, needed);
+			int n = m_stream.Read(m_buffer, m_buffer_used, needed);
+			if (n == 0) return false;
+
+			m_buffer_used += n;
 
 			return (m_buffer_used >= m_buffer_pos + bytes);
 		}
@@ -354,9 +388,6 @@ namespace System.IO {
 
 		void ConsumeBuffered(int bytes) {
 			m_buffer_pos += bytes;
-			if (m_buffer_pos == m_buffer_used) {
-				m_buffer_pos = 0;
-			}
 		}
 	}
 }

+ 51 - 21
mcs/class/corlib/System.IO/BinaryWriter.cs

@@ -7,17 +7,24 @@
 
 using System;
 using System.Text;
+using System.Globalization;
 
 namespace System.IO {
 	[Serializable]
 	public class BinaryWriter : IDisposable {
+
+		// Null is a BinaryWriter with no backing store.
 		public static readonly BinaryWriter Null;
 
 		protected Stream OutStream;
-		Encoding m_encoding;
-		
-		protected BinaryWriter() {
-			m_encoding = Encoding.UTF8;
+		private Encoding m_encoding;
+		private byte [] buffer;
+
+		static BinaryWriter() {
+			Null = new BinaryWriter();
+		}
+
+		protected BinaryWriter() : this (Stream.Null, Encoding.UTF8) {
 		}
 
 		public BinaryWriter(Stream output) : this(output, Encoding.UTF8) {
@@ -25,12 +32,13 @@ namespace System.IO {
 
 		public BinaryWriter(Stream output, Encoding encoding) {
 			if (output == null || encoding == null) 
-				throw new ArgumentNullException();
+				throw new ArgumentNullException(Locale.GetText ("Output or Encoding is a null reference."));
 			if (!output.CanWrite)
-				throw new ArgumentException();
+				throw new ArgumentException(Locale.GetText ("Stream does not support writing or already closed."));
 
 			OutStream = output;
 			m_encoding = encoding;
+			buffer = new byte [16];
 		}
 
 		public virtual Stream BaseStream {
@@ -57,7 +65,8 @@ namespace System.IO {
 		}
 
 		public virtual void Write(bool value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 1);
+			buffer [0] = (byte) (value ? 1 : 0);
+			OutStream.Write(buffer, 0, 1);
 		}
 
 		public virtual void Write(byte value) {
@@ -65,10 +74,14 @@ namespace System.IO {
 		}
 
 		public virtual void Write(byte[] value) {
+			if (value == null)
+				throw new ArgumentNullException(Locale.GetText ("Byte buffer is a null reference."));
 			OutStream.Write(value, 0, value.Length);
 		}
 
 		public virtual void Write(byte[] value, int offset, int length) {
+			if (value == null)
+				throw new ArgumentNullException(Locale.GetText ("Byte buffer is a null reference."));
 			OutStream.Write(value, offset, length);
 		}
 
@@ -80,23 +93,26 @@ namespace System.IO {
 		}
 		
 		public virtual void Write(char[] value) {
+			if (value == null)
+				throw new ArgumentNullException(Locale.GetText ("Chars is a null reference."));
 			byte[] enc = m_encoding.GetBytes(value, 0, value.Length);
 			OutStream.Write(enc, 0, enc.Length);
 		}
 
 		public virtual void Write(char[] value, int offset, int length) {
+			if (value == null)
+				throw new ArgumentNullException(Locale.GetText ("Chars is a null reference."));
 			byte[] enc = m_encoding.GetBytes(value, offset, length);
 			OutStream.Write(enc, 0, enc.Length);
 		}
 
 		unsafe public virtual void Write(decimal value) {
-			byte[] to_write = new byte[16];
 			byte* value_ptr = (byte *)&value;
 			for (int i = 0; i < 16; i++) {
-				to_write[i] = value_ptr[i];
+				buffer [i] = value_ptr [i];
 			}
 
-			OutStream.Write(to_write, 0, 16);
+			OutStream.Write(buffer, 0, 16);
 		}
 
 		public virtual void Write(double value) {
@@ -104,23 +120,29 @@ namespace System.IO {
 		}
 		
 		public virtual void Write(short value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 2);
+			buffer [0] = (byte) value;
+			buffer [1] = (byte) (value >> 8);
+			OutStream.Write(buffer, 0, 2);
 		}
 		
 		public virtual void Write(int value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 4);
+			buffer [0] = (byte) value;
+			buffer [1] = (byte) (value >> 8);
+			buffer [2] = (byte) (value >> 16);
+			buffer [3] = (byte) (value >> 24);
+			OutStream.Write(buffer, 0, 4);
 		}
 
 		public virtual void Write(long value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 8);
+			for (int i = 0, sh = 0; i < 8; i++, sh += 8)
+				buffer [i] = (byte) (value >> sh);
+			OutStream.Write(buffer, 0, 8);
 		}
 
 		[CLSCompliant(false)]
-		unsafe public virtual void Write(sbyte value) {
-			byte[] to_write = new byte[1];
-
-			to_write[0] = *(byte *)&value;
-			OutStream.Write(to_write, 0, 1);
+		public virtual void Write(sbyte value) {
+			buffer [0] = (byte) value;
+			OutStream.Write(buffer, 0, 1);
 		}
 
 		public virtual void Write(float value) {
@@ -135,17 +157,25 @@ namespace System.IO {
 
 		[CLSCompliant(false)]
 		public virtual void Write(ushort value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 2);
+			buffer [0] = (byte) value;
+			buffer [1] = (byte) (value >> 8);
+			OutStream.Write(buffer, 0, 2);
 		}
 
 		[CLSCompliant(false)]
 		public virtual void Write(uint value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 4);
+			buffer [0] = (byte) value;
+			buffer [1] = (byte) (value >> 8);
+			buffer [2] = (byte) (value >> 16);
+			buffer [3] = (byte) (value >> 24);
+			OutStream.Write(buffer, 0, 4);
 		}
 
 		[CLSCompliant(false)]
 		public virtual void Write(ulong value) {
-			OutStream.Write(BitConverter.GetBytes(value), 0, 8);
+			for (int i = 0, sh = 0; i < 8; i++, sh += 8)
+				buffer [i] = (byte) (value >> sh);
+			OutStream.Write(buffer, 0, 8);
 		}
 
 		protected void Write7BitEncodedInt(int value) {

+ 9 - 0
mcs/class/corlib/System.IO/ChangeLog

@@ -1,3 +1,12 @@
+2002-04-30  Sergey Chaban  <[email protected]>
+
+	* BinaryReader.cs: Allocate buffer before its first use.
+	Handle end of stream properly. Methods to read native types
+	(ReadInt* etc.) are little-endian (see Compact Framework docs).
+
+	* BinaryWriter.cs: Store data in little-endian format.
+	Use internal buffer for conversions.
+
 2002-03-31  Dick Porter  <[email protected]>
 
 	* Directory.cs: Strip out "." and ".." from returned list