Mesen-SX/UI/Interop/Utf8Marshaler.cs

99 lines
2 KiB
C#

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);
}
}
}