171 lines
4.7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Pico.Platform
{
public class UTF8Marshaller : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
=> Marshal.FreeHGlobal(pNativeData);
public int GetNativeDataSize() => -1;
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.");
return MarshalUtil.StringToPtr((string) managedObj);
}
public object MarshalNativeToManaged(IntPtr str)
{
if (str == IntPtr.Zero)
return null;
return MarshalUtil.PtrToString(str);
}
public static ICustomMarshaler GetInstance(string pstrCookie)
{
if (marshaler == null)
marshaler = new UTF8Marshaller();
return marshaler;
}
private static UTF8Marshaller marshaler;
}
public class PtrManager
{
public IntPtr ptr;
private bool freed = false;
public PtrManager(byte[] a)
{
this.ptr = MarshalUtil.ByteArrayToNative(a);
}
public void Free()
{
if (freed) return;
freed = true;
Marshal.FreeHGlobal(ptr);
}
~PtrManager()
{
this.Free();
}
}
class PtrArray
{
public IntPtr[] a;
private bool freed = false;
public PtrArray(string[] a)
{
if (a == null)
{
a = Array.Empty<string>();
}
this.a = a.Select(x => MarshalUtil.StringToPtr(x)).ToArray();
}
public void Free()
{
if (freed) return;
freed = true;
foreach (var i in a)
{
Marshal.FreeHGlobal(i);
}
}
~PtrArray()
{
this.Free();
}
}
public static class MarshalUtil
{
public static IntPtr StringToPtr(string s)
{
if (s == null) return IntPtr.Zero;
// not null terminated
byte[] strbuf = Encoding.UTF8.GetBytes(s);
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 static string PtrToString(IntPtr p)
{
return GetString(Encoding.UTF8, p);
}
public static string GetString(Encoding encoding, IntPtr str)
{
if (str == IntPtr.Zero)
return null;
int byteCount = 0;
if (Equals(encoding, Encoding.UTF32))
{
while (Marshal.ReadInt32(str, byteCount) != 0) byteCount += sizeof(int);
}
else if (Equals(encoding, Encoding.Unicode) || Equals(encoding, Encoding.BigEndianUnicode))
{
while (Marshal.ReadInt16(str, byteCount) != 0) byteCount += sizeof(short);
}
else
{
while (Marshal.ReadByte(str, byteCount) != 0) byteCount += sizeof(byte);
}
var bytes = new byte[byteCount];
Marshal.Copy(str, bytes, 0, byteCount);
return encoding.GetString(bytes);
}
public static byte[] ByteArrayFromNative(IntPtr ptr, uint length)
{
var ans = new byte[length];
Marshal.Copy(ptr, ans, 0, (int) length);
return ans;
}
public static IntPtr ByteArrayToNative(byte[] a)
{
var ptr = Marshal.AllocHGlobal(a.Length);
Marshal.Copy(a, 0, ptr, a.Length);
return ptr;
}
}
}