using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Mesen.GUI { public class Utf8Marshaler : ICustomMarshaler { static Utf8Marshaler _instance; public IntPtr MarshalManagedToNative(object managedObj) { if(managedObj == null) { return IntPtr.Zero; } if(!(managedObj is string)) { throw new MarshalDirectiveException("UTF8Marshaler must be used on a string."); } // not null terminated byte[] strbuf = Encoding.UTF8.GetBytes((string)managedObj); IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1); Marshal.Copy(strbuf, 0, buffer, strbuf.Length); // write the terminating null Marshal.WriteByte(buffer + strbuf.Length, 0); return buffer; } public object MarshalNativeToManaged(IntPtr pNativeData) { return GetStringFromIntPtr(pNativeData); } public void CleanUpNativeData(IntPtr pNativeData) { Marshal.FreeHGlobal(pNativeData); } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } public static ICustomMarshaler GetInstance(string cookie) { if(_instance == null) { return _instance = new Utf8Marshaler(); } return _instance; } public static string GetStringFromIntPtr(IntPtr pNativeData) { int offset = 0; byte b = 0; do { b = Marshal.ReadByte(pNativeData, offset); offset++; } while(b != 0); int length = offset - 1; // should not be null terminated byte[] strbuf = new byte[length]; // skip the trailing null Marshal.Copy((IntPtr)pNativeData, strbuf, 0, length); string data = Encoding.UTF8.GetString(strbuf); return data; } public static string PtrToStringUtf8(IntPtr ptr) { if(ptr == IntPtr.Zero) { return ""; } int len = 0; while(Marshal.ReadByte(ptr, len) != 0) { len++; } if(len == 0) { return ""; } byte[] array = new byte[len]; Marshal.Copy(ptr, array, 0, len); return Encoding.UTF8.GetString(array); } } }