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

View File

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