Improved conversion of struct arrays to/from byte arrays

This commit is contained in:
dexy 2022-05-08 20:54:21 +10:00
parent df77346daf
commit 9904e92082
3 changed files with 71 additions and 35 deletions

View File

@ -1449,21 +1449,31 @@ namespace CodeWalker.GameFiles
public static byte[] ConvertArrayToBytes<T>(params T[] items) where T : struct
{
if (items == null) return null;
int size = Marshal.SizeOf(typeof(T));
int sizetot = size * items.Length;
byte[] arrout = new byte[sizetot];
int offset = 0;
for (int i = 0; i < items.Length; i++)
{
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(items[i], ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
Buffer.BlockCopy(arr, 0, arrout, offset, size);
offset += size;
}
return arrout;
var size = Marshal.SizeOf(typeof(T)) * items.Length;
var b = new byte[size];
GCHandle handle = GCHandle.Alloc(items, GCHandleType.Pinned);
var h = handle.AddrOfPinnedObject();
Marshal.Copy(h, b, 0, size);
handle.Free();
return b;
//int size = Marshal.SizeOf(typeof(T));
//int sizetot = size * items.Length;
//byte[] arrout = new byte[sizetot];
//int offset = 0;
//for (int i = 0; i < items.Length; i++)
//{
// byte[] arr = new byte[size];
// IntPtr ptr = Marshal.AllocHGlobal(size);
// Marshal.StructureToPtr(items[i], ptr, true);
// Marshal.Copy(ptr, arr, 0, size);
// Marshal.FreeHGlobal(ptr);
// Buffer.BlockCopy(arr, 0, arrout, offset, size);
// offset += size;
//}
//return arrout;
}
@ -1487,11 +1497,16 @@ namespace CodeWalker.GameFiles
{
T[] items = new T[count];
int itemsize = Marshal.SizeOf(typeof(T));
for (int i = 0; i < count; i++)
{
int off = offset + i * itemsize;
items[i] = ConvertData<T>(data, off);
}
//for (int i = 0; i < count; i++)
//{
// int off = offset + i * itemsize;
// items[i] = ConvertData<T>(data, off);
//}
GCHandle handle = GCHandle.Alloc(items, GCHandleType.Pinned);
var h = handle.AddrOfPinnedObject();
Marshal.Copy(data, offset, h, itemsize * count);
handle.Free();
return items;
}
public static T[] ConvertDataArray<T>(Meta meta, MetaName name, Array_StructurePointer array) where T : struct

View File

@ -15848,11 +15848,17 @@ namespace CodeWalker.GameFiles
{
T[] items = new T[count];
int itemsize = Marshal.SizeOf(typeof(T));
for (int i = 0; i < count; i++)
{
int off = offset + i * itemsize;
items[i] = ConvertDataRaw<T>(data, off);
}
//for (int i = 0; i < count; i++)
//{
// int off = offset + i * itemsize;
// items[i] = ConvertDataRaw<T>(data, off);
//}
GCHandle handle = GCHandle.Alloc(items, GCHandleType.Pinned);
var h = handle.AddrOfPinnedObject();
Marshal.Copy(data, offset, h, itemsize * count);
handle.Free();
return items;
}

View File

@ -369,15 +369,22 @@ namespace CodeWalker.GameFiles
//var result2 = new T[count];
//Buffer.BlockCopy(data, 0, result2, 0, (int)length); //error: "object must be an array of primitives" :(
//var result = new T[count];
//GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
//var h = handle.AddrOfPinnedObject();
//for (uint i = 0; i < count; i++)
//{
// result[i] = Marshal.PtrToStructure<T>(h + (int)(i * structsize));
//}
//handle.Free();
var result = new T[count];
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
GCHandle handle = GCHandle.Alloc(result, GCHandleType.Pinned);
var h = handle.AddrOfPinnedObject();
for (uint i = 0; i < count; i++)
{
result[i] = Marshal.PtrToStructure<T>(h + (int)(i * structsize));
}
Marshal.Copy(data, 0, h, (int)length);
handle.Free();
if (cache) arrayPool[(long)position] = result;
return result;
@ -388,13 +395,21 @@ namespace CodeWalker.GameFiles
var result = new T[count];
var length = count * structsize;
byte[] data = ReadBytes((int)length);
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
//GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
//var h = handle.AddrOfPinnedObject();
//for (uint i = 0; i < count; i++)
//{
// result[i] = Marshal.PtrToStructure<T>(h + (int)(i * structsize));
//}
//handle.Free();
GCHandle handle = GCHandle.Alloc(result, GCHandleType.Pinned);
var h = handle.AddrOfPinnedObject();
for (uint i = 0; i < count; i++)
{
result[i] = Marshal.PtrToStructure<T>(h + (int)(i * structsize));
}
Marshal.Copy(data, 0, h, (int)length);
handle.Free();
return result;
}