diff --git a/LibCpp2IL/BinaryReaderHelpers.cs b/LibCpp2IL/BinaryReaderHelpers.cs index 74fdc20d..589d7508 100644 --- a/LibCpp2IL/BinaryReaderHelpers.cs +++ b/LibCpp2IL/BinaryReaderHelpers.cs @@ -1,63 +1,59 @@ -using System; +using System.Buffers.Binary; using System.IO; +using System.Runtime.CompilerServices; namespace LibCpp2IL; public static class BinaryReaderHelpers { - public static byte[] Reverse(this byte[] b) - { - Array.Reverse(b); - return b; - } - public static ushort ReadUInt16WithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToUInt16(binRdr.ReadBytesRequired(sizeof(ushort)).Reverse(), 0); + return BinaryPrimitives.ReverseEndianness(binRdr.ReadUInt16()); } public static short ReadInt16WithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToInt16(binRdr.ReadBytesRequired(sizeof(short)).Reverse(), 0); + return BinaryPrimitives.ReverseEndianness(binRdr.ReadInt16()); } public static uint ReadUInt32WithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToUInt32(binRdr.ReadBytesRequired(sizeof(uint)).Reverse(), 0); + return BinaryPrimitives.ReverseEndianness(binRdr.ReadUInt32()); } public static int ReadInt32WithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToInt32(binRdr.ReadBytesRequired(sizeof(int)).Reverse(), 0); + return BinaryPrimitives.ReverseEndianness(binRdr.ReadInt32()); } public static ulong ReadUInt64WithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToUInt64(binRdr.ReadBytesRequired(sizeof(ulong)).Reverse(), 0); + return BinaryPrimitives.ReverseEndianness(binRdr.ReadUInt64()); } public static long ReadInt64WithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToInt64(binRdr.ReadBytesRequired(sizeof(long)).Reverse(), 0); + return BinaryPrimitives.ReverseEndianness(binRdr.ReadInt64()); } public static float ReadSingleWithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToSingle(binRdr.ReadBytesRequired(sizeof(float)).Reverse(), 0); + return BitCast(binRdr.ReadUInt32WithReversedBits()); } public static double ReadDoubleWithReversedBits(this BinaryReader binRdr) { - return BitConverter.ToDouble(binRdr.ReadBytesRequired(sizeof(double)).Reverse(), 0); + return BitCast(binRdr.ReadUInt64WithReversedBits()); } - private static byte[] ReadBytesRequired(this BinaryReader binRdr, int byteCount) + private static TTo BitCast(TFrom source) + where TFrom : unmanaged + where TTo : unmanaged { - var result = binRdr.ReadBytes(byteCount); - - if (result.Length != byteCount) - throw new EndOfStreamException($"{byteCount} bytes required from stream, but only {result.Length} returned."); - - return result; +#if NET8_0_OR_GREATER + return Unsafe.BitCast(source); +#else + return Unsafe.ReadUnaligned(ref Unsafe.As(ref source)); +#endif } } diff --git a/LibCpp2IL/ClassReadingBinaryReader.cs b/LibCpp2IL/ClassReadingBinaryReader.cs index 52a458fe..623411bb 100644 --- a/LibCpp2IL/ClassReadingBinaryReader.cs +++ b/LibCpp2IL/ClassReadingBinaryReader.cs @@ -423,8 +423,8 @@ protected void WriteWord(int position, long word) rawBytes = BitConverter.GetBytes(word); } - if (ShouldReverseArrays) - rawBytes = rawBytes.Reverse(); + if (BitConverter.IsLittleEndian != IsLittleEndian) + Array.Reverse(rawBytes); if (position > _memoryStream.Length) throw new Exception($"WriteWord: Position {position} beyond length {_memoryStream.Length}"); diff --git a/LibCpp2IL/EndianAwareBinaryReader.cs b/LibCpp2IL/EndianAwareBinaryReader.cs index 80a5d804..e6957585 100644 --- a/LibCpp2IL/EndianAwareBinaryReader.cs +++ b/LibCpp2IL/EndianAwareBinaryReader.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; @@ -6,9 +5,8 @@ namespace LibCpp2IL; public class EndianAwareBinaryReader : BinaryReader { - protected bool ShouldReverseArrays = !BitConverter.IsLittleEndian; //Default to LE mode, so on LE systems, don't invert. - public bool IsBigEndian { get; private set; } = false; + public bool IsLittleEndian => !IsBigEndian; private int _numBytesReadSinceLastCall = 0; @@ -26,7 +24,6 @@ public EndianAwareBinaryReader(Stream input, Encoding encoding, bool leaveOpen) public void SetBigEndian() { - ShouldReverseArrays = BitConverter.IsLittleEndian; //Set to BE mode, so on LE systems we invert. IsBigEndian = true; } @@ -69,7 +66,7 @@ public sealed override short ReadInt16() { _numBytesReadSinceLastCall += 2; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadInt16(); return this.ReadInt16WithReversedBits(); @@ -79,7 +76,7 @@ public sealed override int ReadInt32() { _numBytesReadSinceLastCall += 4; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadInt32(); return this.ReadInt32WithReversedBits(); @@ -89,7 +86,7 @@ public sealed override long ReadInt64() { _numBytesReadSinceLastCall += 8; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadInt64(); return this.ReadInt64WithReversedBits(); @@ -99,7 +96,7 @@ public sealed override ushort ReadUInt16() { _numBytesReadSinceLastCall += 2; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadUInt16(); return this.ReadUInt16WithReversedBits(); @@ -109,7 +106,7 @@ public sealed override uint ReadUInt32() { _numBytesReadSinceLastCall += 4; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadUInt32(); return this.ReadUInt32WithReversedBits(); @@ -119,7 +116,7 @@ public sealed override ulong ReadUInt64() { _numBytesReadSinceLastCall += 8; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadUInt64(); return this.ReadUInt64WithReversedBits(); @@ -129,7 +126,7 @@ public sealed override float ReadSingle() { _numBytesReadSinceLastCall += 4; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadSingle(); return this.ReadSingleWithReversedBits(); @@ -139,7 +136,7 @@ public sealed override double ReadDouble() { _numBytesReadSinceLastCall += 8; - if (!ShouldReverseArrays) + if (IsLittleEndian) return base.ReadDouble(); return this.ReadDoubleWithReversedBits();