Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@gnome.org>2002-09-17 05:18:57 +0400
committerMiguel de Icaza <miguel@gnome.org>2002-09-17 05:18:57 +0400
commit9b1aad2b6fcc31dbec9c65a2424eceedb7e5364c (patch)
tree7aaec6525e9cd7d1c28ae81b84534cd199f864fa /mcs/class/Mono.PEToolkit/PEUtils.cs
parent501655c80dcc5c0593f07fe2657c778dc336018d (diff)
Add Sergey Chaban's Mono.PEToolkit
svn path=/trunk/mcs/; revision=7542
Diffstat (limited to 'mcs/class/Mono.PEToolkit/PEUtils.cs')
-rw-r--r--mcs/class/Mono.PEToolkit/PEUtils.cs161
1 files changed, 161 insertions, 0 deletions
diff --git a/mcs/class/Mono.PEToolkit/PEUtils.cs b/mcs/class/Mono.PEToolkit/PEUtils.cs
new file mode 100644
index 00000000000..1375a7ebec5
--- /dev/null
+++ b/mcs/class/Mono.PEToolkit/PEUtils.cs
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
+ */
+
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace Mono.PEToolkit {
+
+ public sealed class PEUtils {
+
+ private PEUtils()
+ {
+ }
+
+
+
+ /// <summary>
+ /// Reads structure from the input stream preserving its endianess.
+ /// </summary>
+ /// <param name="reader"></param>
+ /// <param name="pStruct"></param>
+ /// <param name="len"></param>
+ unsafe internal static void ReadStruct(BinaryReader reader, void* pStruct, int len)
+ {
+ byte* p = (byte*) pStruct;
+
+ if (System.BitConverter.IsLittleEndian) {
+ // On a little-endian machine read data in 64-bit chunks,
+ // this won't work on big-endian machine because
+ // BinaryReader APIs are little-endian while
+ // memory writes are platform-native.
+ // This seems faster than ReadBytes/Copy method
+ // in the "else" clause, especially if used often
+ // (no extra memory allocation for byte[]?).
+ int whole = len >> 3;
+ int rem = len & 7;
+
+ for (int i = whole; --i >= 0;) {
+ long qw = reader.ReadInt64();
+ Marshal.WriteInt64((IntPtr) p, qw);
+ p += sizeof (long);
+ }
+ for (int i = rem; --i >= 0;) {
+ *p++ = (byte) reader.ReadByte();
+ }
+ } else {
+ byte [] buff = reader.ReadBytes(len);
+ Marshal.Copy(buff, 0, (IntPtr) p, len);
+ }
+ }
+
+ /// <summary>
+ /// Reads structure from the input stream
+ /// changing its endianess if required
+ /// (if running on big-endian hardware).
+ /// </summary>
+ /// <param name="reader"></param>
+ /// <param name="pStruct"></param>
+ /// <param name="len"></param>
+ /// <param name="type"></param>
+ unsafe internal static void ReadStruct(BinaryReader reader, void* pStruct, int len, Type type)
+ {
+ ReadStruct(reader, pStruct, len);
+ if (!System.BitConverter.IsLittleEndian) {
+ ChangeStructEndianess(pStruct, type);
+ }
+ }
+
+
+ unsafe private static int SwapByTypeCode(byte* p, TypeCode tcode)
+ {
+ int inc = 0;
+ switch (tcode) {
+ case TypeCode.Int16 :
+ short* sp = (short*) p;
+ short sx = *sp;
+ sx = LEBitConverter.SwapInt16(sx);
+ *sp = sx;
+ inc = sizeof (short);
+ break;
+ case TypeCode.UInt16 :
+ ushort* usp = (ushort*) p;
+ ushort usx = *usp;
+ usx = LEBitConverter.SwapUInt16(usx);
+ *usp = usx;
+ inc = sizeof (ushort);
+ break;
+ case TypeCode.Int32 :
+ int* ip = (int*) p;
+ int ix = *ip;
+ ix = LEBitConverter.SwapInt32(ix);
+ *ip = ix;
+ inc = sizeof (int);
+ break;
+ case TypeCode.UInt32 :
+ uint* uip = (uint*) p;
+ uint uix = *uip;
+ uix = LEBitConverter.SwapUInt32(uix);
+ *uip = uix;
+ inc = sizeof (uint);
+ break;
+ case TypeCode.Int64 :
+ long* lp = (long*) p;
+ long lx = *lp;
+ lx = LEBitConverter.SwapInt64(lx);
+ *lp = lx;
+ inc = sizeof (long);
+ break;
+ case TypeCode.UInt64 :
+ ulong* ulp = (ulong*) p;
+ ulong ulx = *ulp;
+ ulx = LEBitConverter.SwapUInt64(ulx);
+ *ulp = ulx;
+ inc = sizeof (ulong);
+ break;
+ case TypeCode.Byte :
+ case TypeCode.SByte :
+ inc = sizeof (byte);
+ break;
+ default :
+ break;
+ }
+ return inc;
+ }
+
+ unsafe internal static int ChangeStructEndianess(void* pStruct, Type type)
+ {
+ if (type == null || !type.IsValueType) return 0;
+ if (!type.IsLayoutSequential && !type.IsExplicitLayout) {
+ throw new Exception("Internal error: struct must have explicit or sequential layout.");
+ }
+
+ bool seq = type.IsLayoutSequential;
+ byte* p = (byte*) pStruct;
+ int offs = 0;
+ int inc;
+ FieldInfo [] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+
+ foreach (FieldInfo fi in fields) {
+ if (!seq) offs = Marshal.OffsetOf(type, fi.Name).ToInt32 ();
+ Type ft = fi.FieldType;
+ TypeCode tcode = Type.GetTypeCode(ft);
+ if (tcode == TypeCode.Object) {
+ // not a primitive type, process recursively.
+ inc = ChangeStructEndianess(p + offs, ft);
+ } else {
+ inc = SwapByTypeCode(p + offs, tcode);
+ }
+ if (seq) offs += inc;
+ }
+
+ return offs;
+ }
+
+ }
+
+}
+