CPF/CPF.Mac/Mac/CoreFoundation/CFString.cs
2023-11-21 23:05:03 +08:00

152 lines
3.4 KiB
C#

using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFString : INativeObject, IDisposable
{
internal IntPtr handle;
internal string str;
public IntPtr Handle => handle;
public int Length
{
get
{
if (str != null)
{
return str.Length;
}
return CFStringGetLength(handle);
}
}
public char this[int p]
{
get
{
if (str != null)
{
return str[p];
}
return CFStringGetCharacterAtIndex(handle, p);
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern IntPtr CFStringCreateWithCharacters(IntPtr allocator, string str, int count);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern int CFStringGetLength(IntPtr handle);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern IntPtr CFStringGetCharactersPtr(IntPtr handle);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern IntPtr CFStringGetCharacters(IntPtr handle, CFRange range, IntPtr buffer);
public CFString(string str)
{
if (str == null)
{
throw new ArgumentNullException("str");
}
handle = CFStringCreateWithCharacters(IntPtr.Zero, str, str.Length);
this.str = str;
}
~CFString()
{
Dispose(disposing: false);
}
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText", EntryPoint = "CFStringGetTypeID")]
public static extern int GetTypeID();
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
str = null;
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
public CFString(IntPtr handle)
: this(handle, owns: false)
{
}
[Preserve(Conditional = true)]
internal CFString(IntPtr handle, bool owns)
{
this.handle = handle;
if (!owns)
{
CFObject.CFRetain(handle);
}
}
internal unsafe static string FetchString(IntPtr handle)
{
if (handle == IntPtr.Zero)
{
return null;
}
int num = CFStringGetLength(handle);
IntPtr intPtr = CFStringGetCharactersPtr(handle);
IntPtr intPtr2 = IntPtr.Zero;
if (intPtr == IntPtr.Zero)
{
CFRange range = new CFRange(0, num);
intPtr2 = Marshal.AllocCoTaskMem(num * 2);
CFStringGetCharacters(handle, range, intPtr2);
intPtr = intPtr2;
}
string result = new string((char*)(void*)intPtr, 0, num);
if (intPtr2 != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(intPtr2);
}
return result;
}
public static implicit operator string(CFString x)
{
if (x.str == null)
{
x.str = FetchString(x.handle);
}
return x.str;
}
public static implicit operator CFString(string s)
{
return new CFString(s);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern char CFStringGetCharacterAtIndex(IntPtr handle, int p);
public override string ToString()
{
if (str != null)
{
return str;
}
return FetchString(handle);
}
}
}