diff --git a/src/IO/DataReader.cs b/src/IO/DataReader.cs index 33a99b7fe..8ab81aa7f 100644 --- a/src/IO/DataReader.cs +++ b/src/IO/DataReader.cs @@ -180,19 +180,49 @@ public readonly DataReader Slice(int start) { /// Reads a /// /// - public bool ReadBoolean() => ReadByte() != 0; + public bool ReadBoolean() { + VerifyState(); + const uint SIZE = 1; + var currentOffset = this.currentOffset; + if (currentOffset == endOffset) + ThrowNoMoreBytesLeft(); + var value = stream.ReadBoolean(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; + } /// /// Reads a /// /// - public char ReadChar() => (char)ReadUInt16(); + public char ReadChar() { + VerifyState(); + const uint SIZE = 2; + var currentOffset = this.currentOffset; + if (endOffset - currentOffset < SIZE) + ThrowNoMoreBytesLeft(); + var value = stream.ReadChar(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; + } /// /// Reads a /// /// - public sbyte ReadSByte() => (sbyte)ReadByte(); + public sbyte ReadSByte() { + VerifyState(); + const uint SIZE = 1; + var currentOffset = this.currentOffset; + if (currentOffset == endOffset) + ThrowNoMoreBytesLeft(); + var value = stream.ReadSByte(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; + } /// /// Reads a @@ -214,7 +244,17 @@ public byte ReadByte() { /// Reads a /// /// - public short ReadInt16() => (short)ReadUInt16(); + public short ReadInt16() { + VerifyState(); + const uint SIZE = 2; + var currentOffset = this.currentOffset; + if (endOffset - currentOffset < SIZE) + ThrowNoMoreBytesLeft(); + var value = stream.ReadInt16(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; + } /// /// Reads a @@ -236,7 +276,17 @@ public ushort ReadUInt16() { /// Reads a /// /// - public int ReadInt32() => (int)ReadUInt32(); + public int ReadInt32() { + VerifyState(); + const uint SIZE = 4; + var currentOffset = this.currentOffset; + if (endOffset - currentOffset < SIZE) + ThrowNoMoreBytesLeft(); + var value = stream.ReadInt32(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; + } /// /// Reads a @@ -291,7 +341,17 @@ internal uint Unsafe_ReadUInt32() { /// Reads a /// /// - public long ReadInt64() => (long)ReadUInt64(); + public long ReadInt64() { + VerifyState(); + const uint SIZE = 8; + var currentOffset = this.currentOffset; + if (endOffset - currentOffset < SIZE) + ThrowNoMoreBytesLeft(); + var value = stream.ReadInt64(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; + } /// /// Reads a @@ -362,13 +422,15 @@ public Guid ReadGuid() { /// /// public decimal ReadDecimal() { - var bits = new int[4] { - ReadInt32(), // lo - ReadInt32(), // mid - ReadInt32(), // hi - ReadInt32(), // flags - }; - return new decimal(bits); + VerifyState(); + const uint SIZE = 16; + var currentOffset = this.currentOffset; + if (endOffset - currentOffset < SIZE) + ThrowNoMoreBytesLeft(); + var value = stream.ReadDecimal(currentOffset); + this.currentOffset = currentOffset + SIZE; + VerifyState(); + return value; } /// diff --git a/src/IO/DataStream.cs b/src/IO/DataStream.cs index 654374a3b..6bdb959a2 100644 --- a/src/IO/DataStream.cs +++ b/src/IO/DataStream.cs @@ -34,6 +34,20 @@ public abstract class DataStream { /// public abstract byte ReadByte(uint offset); + /// + /// Reads a + /// + /// Offset of data + /// + public virtual sbyte ReadSByte(uint offset) => (sbyte)ReadByte(offset); + + /// + /// Reads a 1-byte-long + /// + /// Offset of data + /// + public virtual bool ReadBoolean(uint offset) => ReadByte(offset) != 0; + /// /// Reads a /// @@ -41,6 +55,20 @@ public abstract class DataStream { /// public abstract ushort ReadUInt16(uint offset); + /// + /// Reads a + /// + /// Offset of data + /// + public virtual short ReadInt16(uint offset) => (short)ReadUInt16(offset); + + /// + /// Reads a 2-byte-long + /// + /// Offset of data + /// + public virtual char ReadChar(uint offset) => (char)ReadUInt16(offset); + /// /// Reads a /// @@ -48,6 +76,13 @@ public abstract class DataStream { /// public abstract uint ReadUInt32(uint offset); + /// + /// Reads a + /// + /// Offset of data + /// + public virtual int ReadInt32(uint offset) => (int)ReadUInt32(offset); + /// /// Reads a /// @@ -55,6 +90,13 @@ public abstract class DataStream { /// public abstract ulong ReadUInt64(uint offset); + /// + /// Reads a + /// + /// Offset of data + /// + public virtual long ReadInt64(uint offset) => (long)ReadUInt64(offset); + /// /// Reads a /// @@ -79,6 +121,22 @@ public virtual Guid ReadGuid(uint offset) => ReadByte(offset + 8), ReadByte(offset + 9), ReadByte(offset + 10), ReadByte(offset + 11), ReadByte(offset + 12), ReadByte(offset + 13), ReadByte(offset + 14), ReadByte(offset + 15)); + /// + /// Reads a + /// + /// Offset of data + /// + public virtual decimal ReadDecimal(uint offset) { + int lo = ReadInt32(offset); + int mid = ReadInt32(offset + 4); + int hi = ReadInt32(offset + 8); + int flags = ReadInt32(offset + 12); + + byte scale = (byte)(flags >> 16); + bool isNegative = (flags & 0x80000000) != 0; + return new decimal(lo, mid, hi, isNegative, scale); + } + /// /// Reads a UTF-16 encoded ///