using System;
using System.Reflection;
using System.Reflection.Emit;
using BF = System.Reflection.BindingFlags;
using System.Runtime.InteropServices;
namespace Krimskrams
{
public static class UnsafeHelper
{
public static unsafe void* GetPtr<T>(ref T arg) where T : struct
{
return UnsafeHelper<T>.GetPtr(ref arg);
}
public static unsafe void MoveMemory<T1, T2>(ref T1 dest, ref T2 src, int size)
where T1 : struct
where T2 : struct
{
MoveMemory(UnsafeHelper<T1>.GetPtr(ref dest), UnsafeHelper<T2>.GetPtr(ref src), size);
}
public static unsafe void MoveMemory<T>(ref T dest, void* src, int size) where T : struct
{
MoveMemory(UnsafeHelper<T>.GetPtr(ref dest), src, size);
}
public static unsafe void MoveMemory<T>(int numDestObjs,ref T dest, void* src) where T : struct
{
MoveMemory(UnsafeHelper<T>.GetPtr(ref dest), src, numDestObjs * UnsafeHelper<T>.Size);
}
public static unsafe void MoveMemory<T>(void* dest, ref T src, int size) where T : struct
{
MoveMemory(dest, UnsafeHelper<T>.GetPtr(ref src), size);
}
public static unsafe void MoveMemory<T>(void* dest,int numSrcObjs, ref T src) where T : struct
{
MoveMemory(dest, UnsafeHelper<T>.GetPtr(ref src), numSrcObjs * UnsafeHelper<T>.Size);
}
[DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory", SetLastError=false)]
public static unsafe extern void MoveMemory(void* dest, void* src, int size);
public static int SizeOf<T>()
{
return UnsafeHelper<T>.Size;
}
public static int SizeOf(Type type)
{
object[] attrs=type.GetCustomAttributes(typeof(StructLayoutAttribute), false);
if (attrs.Length > 0)
{
StructLayoutAttribute attr = (StructLayoutAttribute)attrs[0];
if (attr.Size > 0) return attr.Size;
}
if (type.IsPrimitive)
{
if (type == typeof(IntPtr))
return IntPtr.Size;
if (type == typeof(double) ||
type == typeof(long) ||
type == typeof(ulong))
return 8;
if (type == typeof(float) ||
type == typeof(int) ||
type == typeof(uint))
return 4;
if (type == typeof(char) ||
type == typeof(short) ||
type == typeof(ushort))
return 2;
if (type == typeof(bool) ||
type == typeof(sbyte) ||
type == typeof(byte))
return 1;
}
else if (type.IsPointer)
{
return IntPtr.Size;
}
else if (type.IsValueType)
{
int sum = 0;
foreach (FieldInfo info in type.GetFields(BF.Instance | BF.Public | BF.NonPublic))
{
sum += SizeOf(info.FieldType);
}
return sum;
}
throw new NotSupportedException(type.FullName);
}
}
public static class UnsafeHelper<T>
{
public unsafe delegate void* getPtrFunc(ref T value);
public unsafe readonly static getPtrFunc GetPtr = BuildFunction();
public static readonly int Size = UnsafeHelper.SizeOf(typeof(T));
private static DynamicMethod method;
private unsafe static getPtrFunc BuildFunction()
{
method = new DynamicMethod("getPtr<" + typeof(T).FullName.Replace(".", "<>") + ">",
typeof(void*), new Type[1] { typeof(T).MakeByRefType() }, typeof(UnsafeHelper).Module);
ILGenerator generator = method.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Conv_U);
generator.Emit(OpCodes.Ret);
return (getPtrFunc)method.CreateDelegate(typeof(getPtrFunc));
}
}
}
|