diff --git a/Marshal.cs b/Marshal.cs index 48fba483f..2a54e64fd 100644 --- a/Marshal.cs +++ b/Marshal.cs @@ -46,7 +46,10 @@ namespace DiscImageChef.Helpers /// The type whose size is to be returned. /// The size, in bytes, of the type that is specified by the generic type parameter. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SizeOf() => System.Runtime.InteropServices.Marshal.SizeOf(); + public static int SizeOf() + { + return System.Runtime.InteropServices.Marshal.SizeOf(); + } /// /// Marshal little-endian binary data to a structure @@ -57,9 +60,9 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T ByteArrayToStructureLittleEndian(byte[] bytes) where T : struct { - GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); - T str = - (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + var str = + (T) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); ptr.Free(); return str; } @@ -88,11 +91,11 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T ByteArrayToStructureBigEndian(byte[] bytes) where T : struct { - GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); object str = - (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + (T) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); ptr.Free(); - return (T)SwapStructureMembersEndian(str); + return (T) SwapStructureMembersEndian(str); } /// @@ -120,11 +123,11 @@ namespace DiscImageChef.Helpers public static T ByteArrayToStructurePdpEndian(byte[] bytes) where T : struct { { - GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); object str = - (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + (T) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); ptr.Free(); - return (T)SwapStructureMembersEndianPdp(str); + return (T) SwapStructureMembersEndianPdp(str); } } @@ -151,8 +154,10 @@ namespace DiscImageChef.Helpers /// Type of the structure to marshal /// The binary data marshalled in a structure with the specified type [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T SpanToStructureLittleEndian(ReadOnlySpan bytes) where T : struct => - MemoryMarshal.Read(bytes); + public static T SpanToStructureLittleEndian(ReadOnlySpan bytes) where T : struct + { + return MemoryMarshal.Read(bytes); + } /// /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this method @@ -165,8 +170,10 @@ namespace DiscImageChef.Helpers /// The binary data marshalled in a structure with the specified type [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T SpanToStructureLittleEndian(ReadOnlySpan bytes, int start, int length) - where T : struct => - MemoryMarshal.Read(bytes.Slice(start, length)); + where T : struct + { + return MemoryMarshal.Read(bytes.Slice(start, length)); + } /// /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method will @@ -178,8 +185,8 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T SpanToStructureBigEndian(ReadOnlySpan bytes) where T : struct { - T str = SpanToStructureLittleEndian(bytes); - return (T)SwapStructureMembersEndian(str); + var str = SpanToStructureLittleEndian(bytes); + return (T) SwapStructureMembersEndian(str); } /// @@ -194,8 +201,8 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T SpanToStructureBigEndian(ReadOnlySpan bytes, int start, int length) where T : struct { - T str = SpanToStructureLittleEndian(bytes.Slice(start, length)); - return (T)SwapStructureMembersEndian(str); + var str = SpanToStructureLittleEndian(bytes.Slice(start, length)); + return (T) SwapStructureMembersEndian(str); } /// @@ -209,7 +216,7 @@ namespace DiscImageChef.Helpers public static T SpanToStructurePdpEndian(ReadOnlySpan bytes) where T : struct { object str = SpanToStructureLittleEndian(bytes); - return (T)SwapStructureMembersEndianPdp(str); + return (T) SwapStructureMembersEndianPdp(str); } /// @@ -223,7 +230,7 @@ namespace DiscImageChef.Helpers public static T SpanToStructurePdpEndian(ReadOnlySpan bytes, int start, int length) where T : struct { object str = SpanToStructureLittleEndian(bytes.Slice(start, length)); - return (T)SwapStructureMembersEndianPdp(str); + return (T) SwapStructureMembersEndianPdp(str); } /// @@ -240,28 +247,28 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T MarshalStructure(byte[] bytes) where T : struct { - if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute - properties)) return ByteArrayToStructureLittleEndian(bytes); + if (!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute + properties)) return ByteArrayToStructureLittleEndian(bytes); - switch(properties.Endian) + switch (properties.Endian) { case BitEndian.Little: return properties.HasReferences - ? ByteArrayToStructureLittleEndian(bytes) - : SpanToStructureLittleEndian(bytes); + ? ByteArrayToStructureLittleEndian(bytes) + : SpanToStructureLittleEndian(bytes); break; case BitEndian.Big: return properties.HasReferences - ? ByteArrayToStructureBigEndian(bytes) - : SpanToStructureBigEndian(bytes); + ? ByteArrayToStructureBigEndian(bytes) + : SpanToStructureBigEndian(bytes); break; case BitEndian.Pdp: return properties.HasReferences - ? ByteArrayToStructurePdpEndian(bytes) - : SpanToStructurePdpEndian(bytes); + ? ByteArrayToStructurePdpEndian(bytes) + : SpanToStructurePdpEndian(bytes); default: throw new ArgumentOutOfRangeException(); } } @@ -274,76 +281,77 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static object SwapStructureMembersEndian(object str) { - Type t = str.GetType(); - FieldInfo[] fieldInfo = t.GetFields(); - foreach(FieldInfo fi in fieldInfo) - if(fi.FieldType == typeof(short)) + var t = str.GetType(); + var fieldInfo = t.GetFields(); + foreach (var fi in fieldInfo) + if (fi.FieldType == typeof(short)) { - short x = (short)fi.GetValue(str); - fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF))); + var x = (short) fi.GetValue(str); + fi.SetValue(str, (short) ((x << 8) | ((x >> 8) & 0xFF))); } - else if(fi.FieldType == typeof(int)) + else if (fi.FieldType == typeof(int)) { - int x = (int)fi.GetValue(str); - x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF)); - fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF))); + var x = (int) fi.GetValue(str); + x = (int) (((x << 8) & 0xFF00FF00) | (((uint) x >> 8) & 0xFF00FF)); + fi.SetValue(str, (int) (((uint) x << 16) | (((uint) x >> 16) & 0xFFFF))); } - else if(fi.FieldType == typeof(long)) + else if (fi.FieldType == typeof(long)) { - long x = (long)fi.GetValue(str); - x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); - x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); - x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); + var x = (long) fi.GetValue(str); + x = ((x & 0x00000000FFFFFFFF) << 32) | (long) (((ulong) x & 0xFFFFFFFF00000000) >> 32); + x = ((x & 0x0000FFFF0000FFFF) << 16) | (long) (((ulong) x & 0xFFFF0000FFFF0000) >> 16); + x = ((x & 0x00FF00FF00FF00FF) << 8) | (long) (((ulong) x & 0xFF00FF00FF00FF00) >> 8); fi.SetValue(str, x); } - else if(fi.FieldType == typeof(ushort)) + else if (fi.FieldType == typeof(ushort)) { - ushort x = (ushort)fi.GetValue(str); - fi.SetValue(str, (ushort)((x << 8) | (x >> 8))); + var x = (ushort) fi.GetValue(str); + fi.SetValue(str, (ushort) ((x << 8) | (x >> 8))); } - else if(fi.FieldType == typeof(uint)) + else if (fi.FieldType == typeof(uint)) { - uint x = (uint)fi.GetValue(str); - x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); - fi.SetValue(str, (x << 16) | (x >> 16)); + var x = (uint) fi.GetValue(str); + x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); + fi.SetValue(str, (x << 16) | (x >> 16)); } - else if(fi.FieldType == typeof(ulong)) + else if (fi.FieldType == typeof(ulong)) { - ulong x = (ulong)fi.GetValue(str); + var x = (ulong) fi.GetValue(str); x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32); x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16); - x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); + x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); fi.SetValue(str, x); } - else if(fi.FieldType == typeof(float)) + else if (fi.FieldType == typeof(float)) { - float flt = (float)fi.GetValue(str); - byte[] flt_b = BitConverter.GetBytes(flt); + var flt = (float) fi.GetValue(str); + var flt_b = BitConverter.GetBytes(flt); fi.SetValue(str, BitConverter.ToSingle(new[] {flt_b[3], flt_b[2], flt_b[1], flt_b[0]}, 0)); } - else if(fi.FieldType == typeof(double)) + else if (fi.FieldType == typeof(double)) { - double dbl = (double)fi.GetValue(str); - byte[] dbl_b = BitConverter.GetBytes(dbl); + var dbl = (double) fi.GetValue(str); + var dbl_b = BitConverter.GetBytes(dbl); fi.SetValue(str, - BitConverter - .ToDouble(new[] {dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0]}, - 0)); + BitConverter + .ToDouble( + new[] {dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0]}, + 0)); } - else if(fi.FieldType == typeof(byte) || fi.FieldType == typeof(sbyte)) + else if (fi.FieldType == typeof(byte) || fi.FieldType == typeof(sbyte)) { // Do nothing, can't byteswap them! } - else if(fi.FieldType == typeof(Guid)) + else if (fi.FieldType == typeof(Guid)) { // TODO: Swap GUID } // TODO: Swap arrays and enums - else if(fi.FieldType.IsValueType && !fi.FieldType.IsEnum && !fi.FieldType.IsArray) + else if (fi.FieldType.IsValueType && !fi.FieldType.IsEnum && !fi.FieldType.IsArray) { - object obj = fi.GetValue(str); - object strc = SwapStructureMembersEndian(obj); + var obj = fi.GetValue(str); + var strc = SwapStructureMembersEndian(obj); fi.SetValue(str, strc); } @@ -353,34 +361,50 @@ namespace DiscImageChef.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static object SwapStructureMembersEndianPdp(object str) { - Type t = str.GetType(); - FieldInfo[] fieldInfo = t.GetFields(); - foreach(FieldInfo fi in fieldInfo) - if(fi.FieldType == typeof(short) || fi.FieldType == typeof(long) || fi.FieldType == typeof(ushort) || - fi.FieldType == typeof(ulong) || fi.FieldType == typeof(float) || fi.FieldType == typeof(double) || - fi.FieldType == typeof(byte) || fi.FieldType == typeof(sbyte) || fi.FieldType == typeof(Guid)) + var t = str.GetType(); + var fieldInfo = t.GetFields(); + foreach (var fi in fieldInfo) + if (fi.FieldType == typeof(short) || fi.FieldType == typeof(long) || fi.FieldType == typeof(ushort) || + fi.FieldType == typeof(ulong) || fi.FieldType == typeof(float) || fi.FieldType == typeof(double) || + fi.FieldType == typeof(byte) || fi.FieldType == typeof(sbyte) || fi.FieldType == typeof(Guid)) { // Do nothing } - else if(fi.FieldType == typeof(int)) + else if (fi.FieldType == typeof(int)) { - int x = (int)fi.GetValue(str); + var x = (int) fi.GetValue(str); fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16)); } - else if(fi.FieldType == typeof(uint)) + else if (fi.FieldType == typeof(uint)) { - uint x = (uint)fi.GetValue(str); + var x = (uint) fi.GetValue(str); fi.SetValue(str, ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16)); } // TODO: Swap arrays and enums - else if(fi.FieldType.IsValueType && !fi.FieldType.IsEnum && !fi.FieldType.IsArray) + else if (fi.FieldType.IsValueType && !fi.FieldType.IsEnum && !fi.FieldType.IsArray) { - object obj = fi.GetValue(str); - object strc = SwapStructureMembersEndianPdp(obj); + var obj = fi.GetValue(str); + var strc = SwapStructureMembersEndianPdp(obj); fi.SetValue(str, strc); } return str; } + + /// + /// Marshal a structure to little-endian binary data + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] StructureToByteArrayLittleEndian(T str) where T : struct + { + var buf = new byte[SizeOf()]; + var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned); + System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false); + ptr.Free(); + return buf; + } } } \ No newline at end of file