diff --git a/BigEndianMarshal.cs b/BigEndianMarshal.cs new file mode 100644 index 0000000..3b6f728 --- /dev/null +++ b/BigEndianMarshal.cs @@ -0,0 +1,131 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : BigEndianMarshal.cs +// Author(s) : Natalia Portillo +// +// Component : Component +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2016 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Linq; + +namespace DiscImageChef +{ + public static class BigEndianMarshal + { + /// + /// Marshals a big endian structure from a byte array. + /// Nested structures are still marshalled as little endian. + /// + /// The structure. + /// Byte array. + /// Structure type. + public static T ByteArrayToStructureBigEndian(byte[] bytes) where T : struct + { + GCHandle ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + T str = (T)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + ptr.Free(); + return SwapStructureMembersEndian(str); + } + + /// + /// Swaps endian of structure members that correspond to numerical types. + /// Does not traverse nested structures. + /// + /// The structure with its members endian swapped. + /// The structure. + /// Structure type. + public static T SwapStructureMembersEndian(T str) where T : struct + { + Type t = str.GetType(); + FieldInfo[] fieldInfo = t.GetFields(); + foreach(FieldInfo fi in fieldInfo) + { + if(fi.FieldType == typeof(short)) + { + short int16 = (short)fi.GetValue(str); + byte[] int16_b = BitConverter.GetBytes(int16); + byte[] int16_r = int16_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToInt16(int16_r, 0)); + } + else if(fi.FieldType == typeof(int)) + { + int int32 = (int)fi.GetValue(str); + byte[] int32_b = BitConverter.GetBytes(int32); + byte[] int32_r = int32_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToInt32(int32_r, 0)); + } + else if(fi.FieldType == typeof(long)) + { + long int64 = (long)fi.GetValue(str); + byte[] int64_b = BitConverter.GetBytes(int64); + byte[] int64_r = int64_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToInt64(int64_r, 0)); + } + else if(fi.FieldType == typeof(ushort)) + { + ushort uint16 = (ushort)fi.GetValue(str); + byte[] uint16_b = BitConverter.GetBytes(uint16); + byte[] uint16_r = uint16_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToInt16(uint16_r, 0)); + } + else if(fi.FieldType == typeof(uint)) + { + uint uint32 = (uint)fi.GetValue(str); + byte[] uint32_b = BitConverter.GetBytes(uint32); + byte[] uint32_r = uint32_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToInt32(uint32_r, 0)); + } + else if(fi.FieldType == typeof(ulong)) + { + ulong uint64 = (ulong)fi.GetValue(str); + byte[] uint64_b = BitConverter.GetBytes(uint64); + byte[] uint64_r = uint64_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToInt64(uint64_r, 0)); + } + else if(fi.FieldType == typeof(float)) + { + float flt = (float)fi.GetValue(str); + byte[] flt_b = BitConverter.GetBytes(flt); + byte[] flt_r = flt_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToSingle(flt_r, 0)); + } + else if(fi.FieldType == typeof(double)) + { + double dbl = (double)fi.GetValue(str); + byte[] dbl_b = BitConverter.GetBytes(dbl); + byte[] dbl_r = dbl_b.Reverse().ToArray(); + fi.SetValueDirect(__makeref(str), BitConverter.ToDouble(dbl_r, 0)); + } + } + return str; + } + } +} + diff --git a/BigEndianStructure.cs b/BigEndianStructure.cs deleted file mode 100644 index c15ca8d..0000000 --- a/BigEndianStructure.cs +++ /dev/null @@ -1,118 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : EndianSwapStructure.cs -// Author(s) : Natalia Portillo -// -// Component : Component -// -// --[ Description ] ---------------------------------------------------------- -// -// Description -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2016 Natalia Portillo -// ****************************************************************************/ -using System; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace DiscImageChef.Helpers -{ - public static class BigEndianStructure - { - // TODO: Check this works - /// - /// Marshals a big-endian byte array to a C# structure. Dunno if it works with nested structures. - /// - /// The big endian byte array. - /// Byte array. - /// C# structure type. - public static T ByteArrayToStructureBigEndian(byte[] bytes) where T : struct - { - GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); - handle.Free(); - Type t = stuff.GetType(); - FieldInfo[] fieldInfo = t.GetFields(); - foreach(FieldInfo fi in fieldInfo) - { - if(fi.FieldType == typeof(short)) - { - short i16 = (short)fi.GetValue(stuff); - byte[] b16 = BitConverter.GetBytes(i16); - byte[] b16r = b16.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToInt16(b16r, 0)); - } - else if(fi.FieldType == typeof(int)) - { - int i32 = (int)fi.GetValue(stuff); - byte[] b32 = BitConverter.GetBytes(i32); - byte[] b32r = b32.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToInt32(b32r, 0)); - } - else if(fi.FieldType == typeof(long)) - { - long i64 = (long)fi.GetValue(stuff); - byte[] b64 = BitConverter.GetBytes(i64); - byte[] b64r = b64.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToInt64(b64r, 0)); - } - else if(fi.FieldType == typeof(ushort)) - { - ushort i16 = (ushort)fi.GetValue(stuff); - byte[] b16 = BitConverter.GetBytes(i16); - byte[] b16r = b16.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToUInt16(b16r, 0)); - } - else if(fi.FieldType == typeof(uint)) - { - uint i32 = (uint)fi.GetValue(stuff); - byte[] b32 = BitConverter.GetBytes(i32); - byte[] b32r = b32.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToUInt32(b32r, 0)); - } - else if(fi.FieldType == typeof(ulong)) - { - ulong i64 = (ulong)fi.GetValue(stuff); - byte[] b64 = BitConverter.GetBytes(i64); - byte[] b64r = b64.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToUInt64(b64r, 0)); - } - else if(fi.FieldType == typeof(float)) - { - float iflt = (float)fi.GetValue(stuff); - byte[] bflt = BitConverter.GetBytes(iflt); - byte[] bfltr = bflt.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToSingle(bfltr, 0)); - } - else if(fi.FieldType == typeof(double)) - { - double idbl = (double)fi.GetValue(stuff); - byte[] bdbl = BitConverter.GetBytes(idbl); - byte[] bdblr = bdbl.Reverse().ToArray(); - fi.SetValueDirect(__makeref(stuff), BitConverter.ToDouble(bdblr, 0)); - } - } - return stuff; - } - } -} - diff --git a/ChangeLog b/ChangeLog index 486a931..b50dcf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-08-22 Natalia Portillo + + * BigEndianMarshal.cs: + * BigEndianStructure.cs: + * DiscImageChef.Helpers.csproj: Reworked big endian marshal. + Does not traverse nested structures. + 2016-08-21 Natalia Portillo * BigEndianStructure.cs: diff --git a/DiscImageChef.Helpers.csproj b/DiscImageChef.Helpers.csproj index f1d6aea..bdccdb8 100644 --- a/DiscImageChef.Helpers.csproj +++ b/DiscImageChef.Helpers.csproj @@ -42,7 +42,7 @@ - +