Merge pull request #249 from pohky/master

This commit is contained in:
goaaats 2021-01-24 17:46:53 +01:00 committed by GitHub
commit b1b6621c2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -59,7 +59,7 @@ namespace Dalamud
/// <param name="result">The resulting object.</param> /// <param name="result">The resulting object.</param>
/// <returns>Whether or not the read succeeded.</returns> /// <returns>Whether or not the read succeeded.</returns>
public static bool Read<T>(IntPtr address, out T result) where T : struct { public static bool Read<T>(IntPtr address, out T result) where T : struct {
if (!ReadBytes(address, SizeOf<T>(), out var buffer)) { if (!ReadBytes(address, SizeCache<T>.Size, out var buffer)) {
result = default; result = default;
return false; return false;
} }
@ -82,19 +82,14 @@ namespace Dalamud
public static T[] Read<T>(IntPtr address, int count) where T : struct public static T[] Read<T>(IntPtr address, int count) where T : struct
{ {
var size = SizeOf<T>(); var size = SizeOf<T>();
if (!ReadBytes(address, count * size, out var buffer))
return null;
var result = new T[count]; var result = new T[count];
using var mem = new LocalMemory(buffer.Length);
var readSucceeded = true; mem.Write(buffer);
for (var i = 0; i < count; i++) { for (var i = 0; i < result.Length; i++)
var success = Read<T>(address + i * size, out var res); result[i] = mem.Read<T>(i * size);
return result;
if (!success)
readSucceeded = false;
result[i] = res;
}
return !readSucceeded ? null : result;
} }
/// <summary> /// <summary>
@ -106,7 +101,7 @@ namespace Dalamud
/// <returns>Whether or not the write succeeded.</returns> /// <returns>Whether or not the write succeeded.</returns>
public static bool Write<T>(IntPtr address, T obj) where T : struct public static bool Write<T>(IntPtr address, T obj) where T : struct
{ {
using var mem = new LocalMemory(SizeOf<T>()); using var mem = new LocalMemory(SizeCache<T>.Size);
mem.Write(obj); mem.Write(obj);
return WriteBytes(address, mem.Read()); return WriteBytes(address, mem.Read());
} }
@ -122,11 +117,11 @@ namespace Dalamud
{ {
if (objArray == null || objArray.Length == 0) if (objArray == null || objArray.Length == 0)
return true; return true;
var size = SizeOf<T>(); var size = SizeCache<T>.Size;
using var mem = new LocalMemory(objArray.Length * size);
for (var i = 0; i < objArray.Length; i++) for (var i = 0; i < objArray.Length; i++)
if (!Write(address + i * size, objArray[i])) mem.Write(objArray[i], i * size);
return false; return WriteBytes(address, mem.Read());
return true;
} }
/// <summary> /// <summary>
@ -208,12 +203,23 @@ namespace Dalamud
/// </summary> /// </summary>
/// <typeparam name="T">The type to inspect.</typeparam> /// <typeparam name="T">The type to inspect.</typeparam>
/// <returns>The size of the passed type.</returns> /// <returns>The size of the passed type.</returns>
public static int SizeOf<T>() public static int SizeOf<T>() where T: struct
{
return SizeCache<T>.Size;
}
private static class SizeCache<T>
{
// ReSharper disable once StaticMemberInGenericType
public static readonly int Size;
static SizeCache()
{ {
var type = typeof(T); var type = typeof(T);
if (type.IsEnum) if (type.IsEnum)
type = type.GetEnumUnderlyingType(); type = type.GetEnumUnderlyingType();
return Type.GetTypeCode(type) == TypeCode.Boolean ? 1 : Marshal.SizeOf(type); Size = Type.GetTypeCode(type) == TypeCode.Boolean ? 1 : Marshal.SizeOf(type);
}
} }
private static class Imports private static class Imports
@ -246,9 +252,9 @@ namespace Dalamud
return bytes; return bytes;
} }
public T Read<T>() => (T)Marshal.PtrToStructure(this.hGlobal, typeof(T)); public T Read<T>(int offset = 0) => (T)Marshal.PtrToStructure(this.hGlobal + offset, typeof(T));
public void Write(byte[] data, int index = 0) => Marshal.Copy(data, index, this.hGlobal, this.size); public void Write(byte[] data, int index = 0) => Marshal.Copy(data, index, this.hGlobal, this.size);
public void Write<T>(T data) => Marshal.StructureToPtr(data, this.hGlobal, false); public void Write<T>(T data, int offset = 0) => Marshal.StructureToPtr(data, this.hGlobal + offset, false);
~LocalMemory() => Dispose(); ~LocalMemory() => Dispose();
public void Dispose() public void Dispose()