初始化

This commit is contained in:
xhm
2023-11-21 23:05:03 +08:00
commit 2455630dad
2252 changed files with 466529 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFAllocator : INativeObject, IDisposable
{
private static CFAllocator Default_cf;
private static CFAllocator SystemDefault_cf;
private static CFAllocator Malloc_cf;
private static CFAllocator MallocZone_cf;
private static CFAllocator Null_cf;
private static readonly IntPtr default_ptr;
private static readonly IntPtr system_default_ptr;
private static readonly IntPtr malloc_ptr;
private static readonly IntPtr malloc_zone_ptr;
internal static readonly IntPtr null_ptr;
private IntPtr handle;
public IntPtr Handle => handle;
public static CFAllocator Default => Default_cf ?? (Default_cf = new CFAllocator(default_ptr));
public static CFAllocator SystemDefault => SystemDefault_cf ?? (SystemDefault_cf = new CFAllocator(system_default_ptr));
public static CFAllocator Malloc => Malloc_cf ?? (Malloc_cf = new CFAllocator(malloc_ptr));
public static CFAllocator MallocZone => MallocZone_cf ?? (MallocZone_cf = new CFAllocator(malloc_zone_ptr));
public static CFAllocator Null => Null_cf ?? (Null_cf = new CFAllocator(null_ptr));
static CFAllocator()
{
IntPtr intPtr = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
try
{
default_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorDefault");
system_default_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorSystemDefault");
malloc_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorMalloc");
malloc_zone_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorMallocZone");
null_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorNull");
}
finally
{
Dlfcn.dlclose(intPtr);
}
}
public CFAllocator(IntPtr handle)
{
this.handle = handle;
}
public CFAllocator(IntPtr handle, bool owns)
{
if (!owns)
{
CFObject.CFRetain(handle);
}
this.handle = handle;
}
~CFAllocator()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFAllocatorAllocate(IntPtr allocator, long size, CFAllocatorFlags hint);
public IntPtr Allocate(long size, CFAllocatorFlags hint = (CFAllocatorFlags)0uL)
{
return CFAllocatorAllocate(handle, size, hint);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFAllocatorDeallocate(IntPtr allocator, IntPtr ptr);
public void Deallocate(IntPtr ptr)
{
CFAllocatorDeallocate(handle, ptr);
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace CPF.Mac.CoreFoundation
{
[Flags]
public enum CFAllocatorFlags : ulong
{
GCScannedMemory = 0x200,
GCObjectMemory = 0x400
}
}

View File

@@ -0,0 +1,131 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
internal class CFArray : INativeObject, IDisposable
{
internal IntPtr handle;
private static readonly IntPtr kCFTypeArrayCallbacks_ptr;
public IntPtr Handle => handle;
public int Count => CFArrayGetCount(handle);
internal CFArray(IntPtr handle)
: this(handle, owns: false)
{
}
[Preserve(Conditional = true)]
internal CFArray(IntPtr handle, bool owns)
{
if (handle == IntPtr.Zero)
{
throw new ArgumentNullException("handle");
}
this.handle = handle;
if (!owns)
{
CFObject.CFRetain(handle);
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", EntryPoint = "CFArrayGetTypeID")]
public static extern int GetTypeID();
~CFArray()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
static CFArray()
{
IntPtr value = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
if (!(value == IntPtr.Zero))
{
try
{
kCFTypeArrayCallbacks_ptr = Dlfcn.GetIndirect(value, "kCFTypeArrayCallBacks");
}
finally
{
Dlfcn.dlclose(value);
}
}
}
public static CFArray FromIntPtrs(params IntPtr[] values)
{
return new CFArray(Create(values), owns: true);
}
public static CFArray FromNativeObjects(params INativeObject[] values)
{
return new CFArray(Create(values), owns: true);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFArrayCreate(IntPtr allocator, IntPtr values, CFIndex numValues, IntPtr callbacks);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFArrayGetValueAtIndex(IntPtr theArray, IntPtr index);
public IntPtr GetValue(int index)
{
return CFArrayGetValueAtIndex(handle, new IntPtr(index));
}
public unsafe static IntPtr Create(params IntPtr[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
fixed (IntPtr* value = values)
{
return CFArrayCreate(IntPtr.Zero, (IntPtr)(void*)value, values.Length, kCFTypeArrayCallbacks_ptr);
}
}
public static IntPtr Create(params INativeObject[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
IntPtr[] array = new IntPtr[values.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = values[i].Handle;
}
return Create(array);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFIndex CFArrayGetCount(IntPtr theArray);
public static int GetCount(IntPtr array)
{
return CFArrayGetCount(array);
}
}
}

View File

@@ -0,0 +1,98 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
[Since(3, 2)]
internal class CFBoolean : INativeObject, IDisposable
{
private IntPtr handle;
public static readonly CFBoolean True;
public static readonly CFBoolean False;
public IntPtr Handle => handle;
public bool Value => CFBooleanGetValue(handle);
static CFBoolean()
{
IntPtr value = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
if (!(value == IntPtr.Zero))
{
try
{
True = new CFBoolean(Dlfcn.GetIntPtr(value, "kCFBooleanTrue"), owns: false);
False = new CFBoolean(Dlfcn.GetIntPtr(value, "kCFBooleanFalse"), owns: false);
}
finally
{
Dlfcn.dlclose(value);
}
}
}
[Preserve(Conditional = true)]
internal CFBoolean(IntPtr handle, bool owns)
{
this.handle = handle;
if (!owns)
{
CFObject.CFRetain(handle);
}
}
~CFBoolean()
{
Dispose(disposing: false);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", EntryPoint = "CFBooleanGetTypeID")]
public static extern int GetTypeID();
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
public static implicit operator bool(CFBoolean value)
{
return value.Value;
}
public static explicit operator CFBoolean(bool value)
{
return FromBoolean(value);
}
public static CFBoolean FromBoolean(bool value)
{
if (!value)
{
return False;
}
return True;
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern bool CFBooleanGetValue(IntPtr boolean);
public static bool GetValue(IntPtr boolean)
{
return CFBooleanGetValue(boolean);
}
}
}

View File

@@ -0,0 +1,91 @@
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
internal class CFData : INativeObject, IDisposable
{
internal IntPtr handle;
public IntPtr Handle => handle;
public int Length => CFDataGetLength(handle);
public IntPtr Bytes => CFDataGetBytePtr(handle);
public CFData(IntPtr handle)
: this(handle, owns: false)
{
}
public CFData(IntPtr handle, bool owns)
{
if (!owns)
{
CFObject.CFRetain(handle);
}
this.handle = handle;
}
~CFData()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", EntryPoint = "CFDataGetTypeID")]
public static extern int GetTypeID();
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
public static CFData FromDataNoCopy(IntPtr buffer, int length)
{
return new CFData(CFDataCreateWithBytesNoCopy(IntPtr.Zero, buffer, length, CFAllocator.null_ptr), owns: true);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFDataCreateWithBytesNoCopy(IntPtr allocator, IntPtr bytes, int len, IntPtr deallocator);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFIndex CFDataGetLength(IntPtr data);
public byte[] GetBuffer()
{
byte[] array = new byte[Length];
Marshal.Copy(CFDataGetBytePtr(handle), array, 0, array.Length);
return array;
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFDataGetBytePtr(IntPtr data);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFDataCreate(IntPtr allocator, IntPtr bytes, CFIndex len);
public static CFData FromData(IntPtr buffer, int length)
{
return new CFData(CFDataCreate(IntPtr.Zero, buffer, length), owns: true);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFDataCreateCopy(IntPtr allocator, IntPtr data);
public CFData Copy()
{
return new CFData(CFDataCreateCopy(IntPtr.Zero, Handle), owns: true);
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
internal class CFDataBuffer : IDisposable
{
private byte[] buffer;
private CFData data;
private bool owns;
public IntPtr Handle => data.Handle;
public byte[] Data => buffer;
public byte this[int idx] => buffer[idx];
public CFDataBuffer(byte[] buffer)
{
this.buffer = buffer;
GCHandle gCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
data = CFData.FromData(gCHandle.AddrOfPinnedObject(), buffer.Length);
gCHandle.Free();
owns = true;
}
public CFDataBuffer(IntPtr ptr)
{
data = new CFData(ptr, owns: false);
buffer = data.GetBuffer();
owns = false;
}
~CFDataBuffer()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (data != null)
{
data.Dispose();
data = null;
}
}
}
}

View File

@@ -0,0 +1,212 @@
using CPF.Mac.ObjCRuntime;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
[Since(3, 2)]
internal class CFDictionary : INativeObject, IDisposable
{
public static IntPtr KeyCallbacks;
public static IntPtr ValueCallbacks;
public IntPtr Handle
{
get;
private set;
}
public int Count => CFDictionaryGetCount(Handle);
public CFDictionary(IntPtr handle)
: this(handle, owns: false)
{
}
public CFDictionary(IntPtr handle, bool owns)
{
if (!owns)
{
CFObject.CFRetain(handle);
}
Handle = handle;
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", EntryPoint = "CFDictionaryGetTypeID")]
public static extern int GetTypeID();
~CFDictionary()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (Handle != IntPtr.Zero)
{
CFObject.CFRelease(Handle);
Handle = IntPtr.Zero;
}
}
static CFDictionary()
{
IntPtr handle = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
try
{
KeyCallbacks = Dlfcn.GetIndirect(handle, "kCFTypeDictionaryKeyCallBacks");
ValueCallbacks = Dlfcn.GetIndirect(handle, "kCFTypeDictionaryValueCallBacks");
}
finally
{
Dlfcn.dlclose(handle);
}
}
public static CFDictionary FromObjectAndKey(INativeObject obj, INativeObject key)
{
return new CFDictionary(CFDictionaryCreate(IntPtr.Zero, new IntPtr[1]
{
key.Handle
}, new IntPtr[1]
{
obj.Handle
}, 1, KeyCallbacks, ValueCallbacks), owns: true);
}
public static CFDictionary FromObjectsAndKeys(INativeObject[] objects, INativeObject[] keys)
{
if (objects == null)
{
throw new ArgumentNullException("objects");
}
if (keys == null)
{
throw new ArgumentNullException("keys");
}
if (objects.Length != keys.Length)
{
throw new ArgumentException("The length of both arrays must be the same");
}
IntPtr[] array = new IntPtr[keys.Length];
IntPtr[] array2 = new IntPtr[keys.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = keys[i].Handle;
array2[i] = objects[i].Handle;
}
return new CFDictionary(CFDictionaryCreate(IntPtr.Zero, array, array2, array.Length, KeyCallbacks, ValueCallbacks), owns: true);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFDictionaryCreate(IntPtr allocator, IntPtr[] keys, IntPtr[] vals, int len, IntPtr keyCallbacks, IntPtr valCallbacks);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFDictionaryGetValue(IntPtr theDict, IntPtr key);
public static IntPtr GetValue(IntPtr theDict, IntPtr key)
{
return CFDictionaryGetValue(theDict, key);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern int CFDictionaryGetCount(IntPtr theDict);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFDictionaryGetKeysAndValues(IntPtr theDict, IntPtr[] keys, IntPtr[] values);
public void GetKeysAndValues(out IntPtr[] keys, out IntPtr[] values)
{
int count = Count;
keys = new IntPtr[count];
values = new IntPtr[count];
CFDictionaryGetKeysAndValues(Handle, keys, values);
}
public static bool GetBooleanValue(IntPtr theDict, IntPtr key)
{
IntPtr value = GetValue(theDict, key);
if (value == IntPtr.Zero)
{
return false;
}
return CFBoolean.GetValue(value);
}
public string GetStringValue(string key)
{
using (CFString cFString = new CFString(key))
{
return CFString.FetchString(CFDictionaryGetValue(Handle, cFString.handle));
}
}
public int GetInt32Value(string key)
{
int value = 0;
using (CFString cFString = new CFString(key))
{
if (!CFNumberGetValue(CFDictionaryGetValue(Handle, cFString.Handle), 3, out value))
{
throw new KeyNotFoundException($"Key {key} not found");
}
return value;
}
}
public long GetInt64Value(string key)
{
long value = 0L;
using (CFString cFString = new CFString(key))
{
if (!CFNumberGetValue(CFDictionaryGetValue(Handle, cFString.Handle), 4, out value))
{
throw new KeyNotFoundException($"Key {key} not found");
}
return value;
}
}
public IntPtr GetIntPtrValue(string key)
{
using (CFString cFString = new CFString(key))
{
return CFDictionaryGetValue(Handle, cFString.handle);
}
}
public CFDictionary GetDictionaryValue(string key)
{
using (CFString cFString = new CFString(key))
{
IntPtr intPtr = CFDictionaryGetValue(Handle, cFString.handle);
return (intPtr == IntPtr.Zero) ? null : new CFDictionary(intPtr);
}
}
public bool ContainsKey(string key)
{
using (CFString cFString = new CFString(key))
{
return CFDictionaryContainsKey(Handle, cFString.handle);
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFNumberGetValue(IntPtr number, int theType, out int value);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFNumberGetValue(IntPtr number, int theType, out long value);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFDictionaryContainsKey(IntPtr theDict, IntPtr key);
}
}

View File

@@ -0,0 +1,36 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
namespace CPF.Mac.CoreFoundation
{
public static class CFErrorDomain
{
public static readonly NSString Cocoa;
public static readonly NSString Mach;
public static readonly NSString OSStatus;
public static readonly NSString Posix;
static CFErrorDomain()
{
IntPtr intPtr = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
if (!(intPtr == IntPtr.Zero))
{
try
{
Cocoa = Dlfcn.GetStringConstant(intPtr, "kCFErrorDomainCocoa");
Mach = Dlfcn.GetStringConstant(intPtr, "kCFErrorDomainMach");
OSStatus = Dlfcn.GetStringConstant(intPtr, "kCFErrorDomainOSStatus");
Posix = Dlfcn.GetStringConstant(intPtr, "kCFErrorDomainPosix");
}
finally
{
Dlfcn.dlclose(intPtr);
}
}
}
}
}

View File

@@ -0,0 +1,107 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFException : Exception
{
public int Code
{
get;
private set;
}
public NSString Domain
{
get;
private set;
}
public string FailureReason
{
get;
private set;
}
public string RecoverySuggestion
{
get;
private set;
}
public CFException(string description, NSString domain, int code, string failureReason, string recoverySuggestion)
: base(description)
{
Code = code;
Domain = domain;
FailureReason = failureReason;
RecoverySuggestion = recoverySuggestion;
}
public static CFException FromCFError(IntPtr cfErrorHandle)
{
return FromCFError(cfErrorHandle, release: true);
}
public static CFException FromCFError(IntPtr cfErrorHandle, bool release)
{
if (cfErrorHandle == IntPtr.Zero)
{
throw new ArgumentException("cfErrorHandle must not be null.", "cfErrorHandle");
}
CFException ex = new CFException(ToString(CFErrorCopyDescription(cfErrorHandle)), (NSString)Runtime.GetNSObject(CFErrorGetDomain(cfErrorHandle)), CFErrorGetCode(cfErrorHandle), ToString(CFErrorCopyFailureReason(cfErrorHandle)), ToString(CFErrorCopyRecoverySuggestion(cfErrorHandle)));
IntPtr intPtr = CFErrorCopyUserInfo(cfErrorHandle);
if (intPtr != IntPtr.Zero)
{
using (NSDictionary nSDictionary = new NSDictionary(intPtr))
{
foreach (KeyValuePair<NSObject, NSObject> item in nSDictionary)
{
ex.Data.Add(item.Key, item.Value);
}
}
}
if (release)
{
CFObject.CFRelease(cfErrorHandle);
}
return ex;
}
private static string ToString(IntPtr cfStringRef)
{
return ToString(cfStringRef, release: true);
}
private static string ToString(IntPtr cfStringRef, bool release)
{
string result = CFString.FetchString(cfStringRef);
if (release && cfStringRef != IntPtr.Zero)
{
CFObject.CFRelease(cfStringRef);
}
return result;
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFErrorCopyDescription(IntPtr err);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFErrorCopyFailureReason(IntPtr err);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFErrorCopyRecoverySuggestion(IntPtr err);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFErrorCopyUserInfo(IntPtr err);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern int CFErrorGetCode(IntPtr err);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFErrorGetDomain(IntPtr err);
}
}

View File

@@ -0,0 +1,39 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
namespace CPF.Mac.CoreFoundation
{
public static class CFExceptionDataKey
{
public static readonly NSString Description;
public static readonly NSString LocalizedDescription;
public static readonly NSString LocalizedFailureReason;
public static readonly NSString LocalizedRecoverySuggestion;
public static readonly NSString UnderlyingError;
static CFExceptionDataKey()
{
IntPtr intPtr = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
if (!(intPtr == IntPtr.Zero))
{
try
{
Description = Dlfcn.GetStringConstant(intPtr, "kCFErrorDescriptionKey");
LocalizedDescription = Dlfcn.GetStringConstant(intPtr, "kCFErrorLocalizedDescriptionKey");
LocalizedFailureReason = Dlfcn.GetStringConstant(intPtr, "kCFErrorLocalizedFailureReasonKey");
LocalizedRecoverySuggestion = Dlfcn.GetStringConstant(intPtr, "kCFErrorLocalizedRecoverySuggestionKey");
UnderlyingError = Dlfcn.GetStringConstant(intPtr, "kCFErrorUnderlyingErrorKey");
}
finally
{
Dlfcn.dlclose(intPtr);
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
namespace CPF.Mac.CoreFoundation
{
public struct CFIndex
{
private IntPtr value;
private CFIndex(IntPtr value)
{
this.value = value;
}
public static implicit operator int(CFIndex index)
{
return index.value.ToInt32();
}
public static implicit operator CFIndex(int value)
{
return new CFIndex(new IntPtr(value));
}
public static implicit operator long(CFIndex index)
{
return index.value.ToInt64();
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
internal static class CFMutableDictionary
{
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFDictionarySetValue(IntPtr theDict, IntPtr key, IntPtr value);
public static void SetValue(IntPtr theDict, IntPtr key, IntPtr value)
{
CFDictionarySetValue(theDict, key, value);
}
public static void SetValue(IntPtr theDict, IntPtr key, bool value)
{
SetValue(theDict, key, value ? CFBoolean.True.Handle : CFBoolean.False.Handle);
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public static class CFObject
{
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
internal static extern void CFRelease(IntPtr obj);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
internal static extern IntPtr CFRetain(IntPtr obj);
}
}

View File

@@ -0,0 +1,35 @@
using System;
namespace CPF.Mac.CoreFoundation
{
public struct CFRange
{
private IntPtr loc;
private IntPtr len;
public int Location => loc.ToInt32();
public int Length => len.ToInt32();
public long LongLocation => loc.ToInt64();
public long LongLength => len.ToInt64();
public CFRange(int loc, int len)
{
this = new CFRange((long)loc, (long)len);
}
public CFRange(long l, long len)
{
loc = new IntPtr(l);
this.len = new IntPtr(len);
}
public override string ToString()
{
return $"CFRange [Location: {loc} Length: {len}]";
}
}
}

View File

@@ -0,0 +1,134 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFReadStream : CFStream
{
public CFReadStream(IntPtr handle)
: base(handle)
{
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFReadStreamCopyError(IntPtr handle);
public override CFException GetError()
{
IntPtr intPtr = CFReadStreamCopyError(base.Handle);
if (intPtr == IntPtr.Zero)
{
return null;
}
return CFException.FromCFError(intPtr);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFReadStreamOpen(IntPtr handle);
protected override bool DoOpen()
{
return CFReadStreamOpen(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFReadStreamClose(IntPtr handle);
protected override void DoClose()
{
CFReadStreamClose(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFStreamStatus CFReadStreamGetStatus(IntPtr handle);
protected override CFStreamStatus DoGetStatus()
{
return CFReadStreamGetStatus(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFReadStreamHasBytesAvailable(IntPtr handle);
public bool HasBytesAvailable()
{
return CFReadStreamHasBytesAvailable(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFReadStreamScheduleWithRunLoop(IntPtr handle, IntPtr loop, IntPtr mode);
protected override void ScheduleWithRunLoop(CFRunLoop loop, NSString mode)
{
CFReadStreamScheduleWithRunLoop(base.Handle, loop.Handle, mode.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFReadStreamUnscheduleFromRunLoop(IntPtr handle, IntPtr loop, IntPtr mode);
protected override void UnscheduleFromRunLoop(CFRunLoop loop, NSString mode)
{
CFReadStreamUnscheduleFromRunLoop(base.Handle, loop.Handle, mode.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFReadStreamSetClient(IntPtr stream, CFIndex eventTypes, CFStreamCallback cb, IntPtr context);
protected override bool DoSetClient(CFStreamCallback callback, CFIndex eventTypes, IntPtr context)
{
return CFReadStreamSetClient(base.Handle, eventTypes, callback, context);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFIndex CFReadStreamRead(IntPtr handle, IntPtr buffer, CFIndex count);
public int Read(byte[] buffer)
{
return Read(buffer, 0, buffer.Length);
}
public int Read(byte[] buffer, int offset, int count)
{
CheckHandle();
if (offset < 0)
{
throw new ArgumentException();
}
if (count < 1)
{
throw new ArgumentException();
}
if (offset + count > buffer.Length)
{
throw new ArgumentException();
}
GCHandle gCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
return CFReadStreamRead(buffer: new IntPtr(gCHandle.AddrOfPinnedObject().ToInt64() + offset), handle: base.Handle, count: count);
}
finally
{
gCHandle.Free();
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFReadStreamCopyProperty(IntPtr handle, IntPtr name);
protected override IntPtr DoGetProperty(NSString name)
{
return CFReadStreamCopyProperty(base.Handle, name.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFReadStreamSetProperty(IntPtr handle, IntPtr name, IntPtr value);
protected override bool DoSetProperty(NSString name, INativeObject value)
{
return CFReadStreamSetProperty(base.Handle, name.Handle, value.Handle);
}
}
}

View File

@@ -0,0 +1,208 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFRunLoop : INativeObject, IDisposable
{
private static IntPtr CoreFoundationLibraryHandle = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0);
internal IntPtr handle;
private static NSString _CFDefaultRunLoopMode;
private static NSString _CFRunLoopCommonModes;
public const string ModeDefault = "kCFRunLoopDefaultMode";
public const string ModeCommon = "kCFRunLoopCommonModes";
public static NSString CFDefaultRunLoopMode
{
get
{
if (_CFDefaultRunLoopMode == null)
{
_CFDefaultRunLoopMode = Dlfcn.GetStringConstant(CoreFoundationLibraryHandle, "kCFRunLoopDefaultMode");
}
return _CFDefaultRunLoopMode;
}
}
public static NSString CFRunLoopCommonModes
{
get
{
if (_CFRunLoopCommonModes == null)
{
_CFRunLoopCommonModes = Dlfcn.GetStringConstant(CoreFoundationLibraryHandle, "kCFRunLoopCommonModes");
}
return _CFRunLoopCommonModes;
}
}
public static CFRunLoop Current => new CFRunLoop(CFRunLoopGetCurrent());
public static CFRunLoop Main => new CFRunLoop(CFRunLoopGetMain());
public bool IsWaiting => CFRunLoopIsWaiting(handle) != 0;
public IntPtr Handle => handle;
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFRunLoopGetCurrent();
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFRunLoopGetMain();
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFRunLoopRun();
public void Run()
{
CFRunLoopRun();
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFRunLoopStop(IntPtr loop);
public void Stop()
{
CFRunLoopStop(handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFRunLoopWakeUp(IntPtr loop);
public void WakeUp()
{
CFRunLoopWakeUp(handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern int CFRunLoopIsWaiting(IntPtr loop);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern int CFRunLoopRunInMode(IntPtr mode, double seconds, int returnAfterSourceHandled);
public CFRunLoopExitReason RunInMode(NSString mode, double seconds, bool returnAfterSourceHandled)
{
if (mode == null)
{
throw new ArgumentNullException("mode");
}
return (CFRunLoopExitReason)CFRunLoopRunInMode(mode.Handle, seconds, returnAfterSourceHandled ? 1 : 0);
}
[Obsolete("Use the NSString version of CFRunLoop.RunInMode() instead.")]
public CFRunLoopExitReason RunInMode(string mode, double seconds, bool returnAfterSourceHandled)
{
if (mode == null)
{
throw new ArgumentNullException("mode");
}
CFString cFString = new CFString(mode);
int result = CFRunLoopRunInMode(cFString.Handle, seconds, returnAfterSourceHandled ? 1 : 0);
cFString.Dispose();
return (CFRunLoopExitReason)result;
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFRunLoopAddSource(IntPtr loop, IntPtr source, IntPtr mode);
public void AddSource(CFRunLoopSource source, NSString mode)
{
if (mode == null)
{
throw new ArgumentNullException("mode");
}
CFRunLoopAddSource(handle, source.Handle, mode.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFRunLoopContainsSource(IntPtr loop, IntPtr source, IntPtr mode);
public bool ContainsSource(CFRunLoopSource source, NSString mode)
{
if (mode == null)
{
throw new ArgumentNullException("mode");
}
return CFRunLoopContainsSource(handle, source.Handle, mode.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFRunLoopRemoveSource(IntPtr loop, IntPtr source, IntPtr mode);
public bool RemoveSource(CFRunLoopSource source, NSString mode)
{
if (mode == null)
{
throw new ArgumentNullException("mode");
}
return CFRunLoopRemoveSource(handle, source.Handle, mode.Handle);
}
internal CFRunLoop(IntPtr handle)
: this(handle, owns: false)
{
}
[Preserve(Conditional = true)]
internal CFRunLoop(IntPtr handle, bool owns)
{
if (!owns)
{
CFObject.CFRetain(handle);
}
this.handle = handle;
}
~CFRunLoop()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
public static bool operator ==(CFRunLoop a, CFRunLoop b)
{
return object.Equals(a, b);
}
public static bool operator !=(CFRunLoop a, CFRunLoop b)
{
return !object.Equals(a, b);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override bool Equals(object other)
{
CFRunLoop cFRunLoop = other as CFRunLoop;
if (cFRunLoop == null)
{
return false;
}
return cFRunLoop.Handle == Handle;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace CPF.Mac.CoreFoundation
{
public enum CFRunLoopExitReason
{
Finished = 1,
Stopped,
TimedOut,
HandledSource
}
}

View File

@@ -0,0 +1,73 @@
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFRunLoopSource : INativeObject, IDisposable
{
internal IntPtr handle;
public IntPtr Handle => handle;
public int Order => CFRunLoopSourceGetOrder(handle);
public bool IsValid => CFRunLoopSourceIsValid(handle) != 0;
internal CFRunLoopSource(IntPtr handle)
: this(handle, ownsHandle: false)
{
}
internal CFRunLoopSource(IntPtr handle, bool ownsHandle)
{
if (!ownsHandle)
{
CFObject.CFRetain(handle);
}
this.handle = handle;
}
~CFRunLoopSource()
{
Dispose(disposing: false);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFIndex CFRunLoopSourceGetOrder(IntPtr source);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFRunLoopSourceInvalidate(IntPtr source);
public void Invalidate()
{
CFRunLoopSourceInvalidate(handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern int CFRunLoopSourceIsValid(IntPtr source);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFRunLoopSourceSignal(IntPtr source);
public void Signal()
{
CFRunLoopSourceSignal(handle);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
namespace CPF.Mac.CoreFoundation
{
internal struct CFRunLoopSourceContext
{
public CFIndex Version;
public IntPtr Info;
public IntPtr Retain;
public IntPtr Release;
public IntPtr CopyDescription;
public IntPtr Equal;
public IntPtr Hash;
public IntPtr Schedule;
public IntPtr Cancel;
public IntPtr Perform;
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public abstract class CFRunLoopSourceCustom : CFRunLoopSource
{
private delegate void ScheduleCallback(IntPtr info, IntPtr runLoop, IntPtr mode);
private delegate void CancelCallback(IntPtr info, IntPtr runLoop, IntPtr mode);
private delegate void PerformCallback(IntPtr info);
private GCHandle gch;
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFRunLoopSourceCreate(IntPtr allocator, int order, IntPtr context);
protected CFRunLoopSourceCustom()
: base(IntPtr.Zero, ownsHandle: true)
{
gch = GCHandle.Alloc(this);
CFRunLoopSourceContext structure = new CFRunLoopSourceContext
{
Info = GCHandle.ToIntPtr(gch),
Schedule = Marshal.GetFunctionPointerForDelegate<ScheduleCallback>(Schedule),
Cancel = Marshal.GetFunctionPointerForDelegate<CancelCallback>(Cancel),
Perform = Marshal.GetFunctionPointerForDelegate<PerformCallback>(Perform)
};
IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CFRunLoopSourceContext)));
try
{
Marshal.StructureToPtr(structure, intPtr, fDeleteOld: false);
handle = CFRunLoopSourceCreate(IntPtr.Zero, 0, intPtr);
}
finally
{
Marshal.FreeHGlobal(intPtr);
}
if (handle == IntPtr.Zero)
{
throw new NotSupportedException();
}
}
[MonoPInvokeCallback(typeof(ScheduleCallback))]
private static void Schedule(IntPtr info, IntPtr runLoop, IntPtr mode)
{
CFRunLoopSourceCustom cFRunLoopSourceCustom = GCHandle.FromIntPtr(info).Target as CFRunLoopSourceCustom;
CFRunLoop cFRunLoop = new CFRunLoop(runLoop);
CFString cFString = new CFString(mode);
try
{
cFRunLoopSourceCustom.OnSchedule(cFRunLoop, cFString);
}
finally
{
cFRunLoop.Dispose();
cFString.Dispose();
}
}
protected abstract void OnSchedule(CFRunLoop loop, string mode);
[MonoPInvokeCallback(typeof(CancelCallback))]
private static void Cancel(IntPtr info, IntPtr runLoop, IntPtr mode)
{
CFRunLoopSourceCustom cFRunLoopSourceCustom = GCHandle.FromIntPtr(info).Target as CFRunLoopSourceCustom;
CFRunLoop cFRunLoop = new CFRunLoop(runLoop);
CFString cFString = new CFString(mode);
try
{
cFRunLoopSourceCustom.OnCancel(cFRunLoop, cFString);
}
finally
{
cFRunLoop.Dispose();
cFString.Dispose();
}
}
protected abstract void OnCancel(CFRunLoop loop, string mode);
[MonoPInvokeCallback(typeof(PerformCallback))]
private static void Perform(IntPtr info)
{
(GCHandle.FromIntPtr(info).Target as CFRunLoopSourceCustom).OnPerform();
}
protected abstract void OnPerform();
public override void Dispose(bool disposing)
{
if (disposing && gch.IsAllocated)
{
gch.Free();
}
base.Dispose(disposing);
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace CPF.Mac.CoreFoundation
{
[Flags]
public enum CFSocketCallBackType
{
NoCallBack = 0x0,
ReadCallBack = 0x1,
AcceptCallBack = 0x2,
DataCallBack = 0x3,
ConnectCallBack = 0x4,
WriteCallBack = 0x8
}
}

View File

@@ -0,0 +1,9 @@
namespace CPF.Mac.CoreFoundation
{
public enum CFSocketError
{
Success = 0,
Error = -1,
Timeout = -2
}
}

View File

@@ -0,0 +1,18 @@
using System;
namespace CPF.Mac.CoreFoundation
{
public class CFSocketException : Exception
{
public CFSocketError Error
{
get;
private set;
}
public CFSocketException(CFSocketError error)
{
Error = error;
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace CPF.Mac.CoreFoundation
{
[Flags]
public enum CFSocketFlags
{
AutomaticallyReenableReadCallBack = 0x1,
AutomaticallyReenableAcceptCallBack = 0x2,
AutomaticallyReenableDataCallBack = 0x3,
AutomaticallyReenableWriteCallBack = 0x8,
LeaveErrors = 0x40,
CloseOnInvalidate = 0x80
}
}

View File

@@ -0,0 +1,17 @@
namespace CPF.Mac.CoreFoundation
{
public struct CFSocketNativeHandle
{
internal readonly int handle;
internal CFSocketNativeHandle(int handle)
{
this.handle = handle;
}
public override string ToString()
{
return $"[CFSocketNativeHandle {handle}]";
}
}
}

View File

@@ -0,0 +1,335 @@
using CPF.Mac.CoreServices;
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public abstract class CFStream : CFType, INativeObject, IDisposable
{
public class StreamEventArgs : EventArgs
{
public CFStreamEventType EventType
{
get;
private set;
}
public StreamEventArgs(CFStreamEventType type)
{
EventType = type;
}
public override string ToString()
{
return $"[StreamEventArgs: EventType={EventType}]";
}
}
protected delegate void CFStreamCallback(IntPtr s, CFStreamEventType type, IntPtr info);
private IntPtr handle;
private GCHandle gch;
private CFRunLoop loop;
private NSString loopMode;
private bool open;
private bool closed;
public IntPtr Handle => handle;
public event EventHandler<StreamEventArgs> OpenCompletedEvent;
public event EventHandler<StreamEventArgs> HasBytesAvailableEvent;
public event EventHandler<StreamEventArgs> CanAcceptBytesEvent;
public event EventHandler<StreamEventArgs> ErrorEvent;
public event EventHandler<StreamEventArgs> ClosedEvent;
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFStreamCreatePairWithSocket(IntPtr allocator, CFSocketNativeHandle socket, out IntPtr read, out IntPtr write);
[DllImport("/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork")]
private static extern void CFStreamCreatePairWithSocketToHost(IntPtr allocator, IntPtr host, int port, out IntPtr read, out IntPtr write);
public static void CreatePairWithSocketToHost(string host, int port, out CFReadStream readStream, out CFWriteStream writeStream)
{
using (CFString cFString = new CFString(host))
{
CFStreamCreatePairWithSocketToHost(IntPtr.Zero, cFString.Handle, port, out IntPtr read, out IntPtr write);
readStream = new CFReadStream(read);
writeStream = new CFWriteStream(write);
}
}
[DllImport("/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork")]
private static extern IntPtr CFReadStreamCreateForHTTPRequest(IntPtr alloc, IntPtr request);
public static CFHTTPStream CreateForHTTPRequest(CFHTTPMessage request)
{
IntPtr value = CFReadStreamCreateForHTTPRequest(IntPtr.Zero, request.Handle);
if (value == IntPtr.Zero)
{
return null;
}
return new CFHTTPStream(value);
}
[DllImport("/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork")]
private static extern IntPtr CFReadStreamCreateForStreamedHTTPRequest(IntPtr alloc, IntPtr request, IntPtr body);
public static CFHTTPStream CreateForStreamedHTTPRequest(CFHTTPMessage request, CFReadStream body)
{
IntPtr value = CFReadStreamCreateForStreamedHTTPRequest(IntPtr.Zero, request.Handle, body.Handle);
if (value == IntPtr.Zero)
{
return null;
}
return new CFHTTPStream(value);
}
[DllImport("/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork")]
private static extern void CFStreamCreateBoundPair(IntPtr alloc, out IntPtr readStream, out IntPtr writeStream, CFIndex transferBufferSize);
public static void CreateBoundPair(out CFReadStream readStream, out CFWriteStream writeStream, int bufferSize)
{
CFStreamCreateBoundPair(IntPtr.Zero, out IntPtr readStream2, out IntPtr writeStream2, bufferSize);
readStream = new CFReadStream(readStream2);
writeStream = new CFWriteStream(writeStream2);
}
public abstract CFException GetError();
protected void CheckError()
{
CFException error = GetError();
if (error != null)
{
throw error;
}
}
public void Open()
{
if (open || closed)
{
throw new InvalidOperationException();
}
CheckHandle();
if (!DoOpen())
{
CheckError();
throw new InvalidOperationException();
}
open = true;
}
protected abstract bool DoOpen();
public void Close()
{
if (open)
{
CheckHandle();
if (loop != null)
{
DoSetClient(null, 0, IntPtr.Zero);
UnscheduleFromRunLoop(loop, loopMode);
loop = null;
loopMode = null;
}
try
{
DoClose();
}
finally
{
open = false;
closed = true;
}
}
}
protected abstract void DoClose();
public CFStreamStatus GetStatus()
{
CheckHandle();
return DoGetStatus();
}
protected abstract CFStreamStatus DoGetStatus();
internal IntPtr GetProperty(NSString name)
{
CheckHandle();
return DoGetProperty(name);
}
protected abstract IntPtr DoGetProperty(NSString name);
protected abstract bool DoSetProperty(NSString name, INativeObject value);
internal void SetProperty(NSString name, INativeObject value)
{
CheckHandle();
if (DoSetProperty(name, value))
{
return;
}
throw new InvalidOperationException($"Cannot set property '{name}' on {GetType().Name}.");
}
protected virtual void OnOpenCompleted(StreamEventArgs args)
{
if (this.OpenCompletedEvent != null)
{
this.OpenCompletedEvent(this, args);
}
}
protected virtual void OnHasBytesAvailableEvent(StreamEventArgs args)
{
if (this.HasBytesAvailableEvent != null)
{
this.HasBytesAvailableEvent(this, args);
}
}
protected virtual void OnCanAcceptBytesEvent(StreamEventArgs args)
{
if (this.CanAcceptBytesEvent != null)
{
this.CanAcceptBytesEvent(this, args);
}
}
protected virtual void OnErrorEvent(StreamEventArgs args)
{
if (this.ErrorEvent != null)
{
this.ErrorEvent(this, args);
}
}
protected virtual void OnClosedEvent(StreamEventArgs args)
{
if (this.ClosedEvent != null)
{
this.ClosedEvent(this, args);
}
}
protected abstract void ScheduleWithRunLoop(CFRunLoop loop, NSString mode);
protected abstract void UnscheduleFromRunLoop(CFRunLoop loop, NSString mode);
[MonoPInvokeCallback(typeof(CFStreamCallback))]
private static void OnCallback(IntPtr s, CFStreamEventType type, IntPtr info)
{
(GCHandle.FromIntPtr(info).Target as CFStream).OnCallback(type);
}
protected virtual void OnCallback(CFStreamEventType type)
{
StreamEventArgs args = new StreamEventArgs(type);
switch (type)
{
case CFStreamEventType.OpenCompleted:
OnOpenCompleted(args);
break;
case CFStreamEventType.CanAcceptBytes:
OnCanAcceptBytesEvent(args);
break;
case CFStreamEventType.HasBytesAvailable:
OnHasBytesAvailableEvent(args);
break;
case CFStreamEventType.ErrorOccurred:
OnErrorEvent(args);
break;
case CFStreamEventType.EndEncountered:
OnClosedEvent(args);
break;
}
}
public void EnableEvents(CFRunLoop runLoop, NSString runLoopMode)
{
if (open || closed || loop != null)
{
throw new InvalidOperationException();
}
CheckHandle();
loop = runLoop;
loopMode = runLoopMode;
CFStreamClientContext structure = default(CFStreamClientContext);
structure.Info = GCHandle.ToIntPtr(gch);
CFStreamEventType value = CFStreamEventType.OpenCompleted | CFStreamEventType.HasBytesAvailable | CFStreamEventType.CanAcceptBytes | CFStreamEventType.ErrorOccurred | CFStreamEventType.EndEncountered;
IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CFStreamClientContext)));
try
{
Marshal.StructureToPtr(structure, intPtr, fDeleteOld: false);
if (!DoSetClient(OnCallback, (int)value, intPtr))
{
throw new InvalidOperationException("Stream does not support async events.");
}
}
finally
{
Marshal.FreeHGlobal(intPtr);
}
ScheduleWithRunLoop(runLoop, runLoopMode);
}
protected abstract bool DoSetClient(CFStreamCallback callback, CFIndex eventTypes, IntPtr context);
protected CFStream(IntPtr handle)
{
this.handle = handle;
gch = GCHandle.Alloc(this);
}
protected void CheckHandle()
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException(GetType().Name);
}
}
~CFStream()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Close();
if (gch.IsAllocated)
{
gch.Free();
}
}
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
}
}

View File

@@ -0,0 +1,89 @@
using CPF.Mac.Foundation;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public struct CFStreamClientContext
{
[MonoNativeFunctionWrapper]
private delegate IntPtr RetainDelegate(IntPtr info);
[MonoNativeFunctionWrapper]
private delegate void ReleaseDelegate(IntPtr info);
[MonoNativeFunctionWrapper]
private delegate IntPtr CopyDescriptionDelegate(IntPtr info);
[MonoNativeFunctionWrapper]
private delegate void CallbackDelegate(IntPtr stream, CFStreamEventType eventType, IntPtr info);
public int Version;
public IntPtr Info;
private IntPtr retain;
private IntPtr release;
private IntPtr copyDescription;
public void Retain()
{
if (!(retain == IntPtr.Zero) && !(Info == IntPtr.Zero))
{
CFReadStreamRef_InvokeRetain(retain, Info);
}
}
public void Release()
{
if (!(release == IntPtr.Zero) && !(Info == IntPtr.Zero))
{
CFReadStreamRef_InvokeRelease(release, Info);
}
}
public override string ToString()
{
if (copyDescription == IntPtr.Zero)
{
return ((ValueType)this).ToString();
}
IntPtr intPtr = CFReadStreamRef_InvokeCopyDescription(copyDescription, Info);
if (!(intPtr == IntPtr.Zero))
{
return new NSString(intPtr).ToString();
}
return ((ValueType)this).ToString();
}
internal void Invoke(IntPtr callback, IntPtr stream, CFStreamEventType eventType)
{
if (!(callback == IntPtr.Zero))
{
CFReadStreamRef_InvokeCallback(callback, stream, eventType, Info);
}
}
private static IntPtr CFReadStreamRef_InvokeRetain(IntPtr retain, IntPtr info)
{
return ((RetainDelegate)Marshal.GetDelegateForFunctionPointer(retain, typeof(RetainDelegate)))(info);
}
private static void CFReadStreamRef_InvokeRelease(IntPtr release, IntPtr info)
{
((ReleaseDelegate)Marshal.GetDelegateForFunctionPointer(release, typeof(ReleaseDelegate)))(info);
}
private static IntPtr CFReadStreamRef_InvokeCopyDescription(IntPtr copyDescription, IntPtr info)
{
return ((CopyDescriptionDelegate)Marshal.GetDelegateForFunctionPointer(copyDescription, typeof(CopyDescriptionDelegate)))(info);
}
private static void CFReadStreamRef_InvokeCallback(IntPtr callback, IntPtr stream, CFStreamEventType eventType, IntPtr info)
{
((CallbackDelegate)Marshal.GetDelegateForFunctionPointer(callback, typeof(CallbackDelegate)))(stream, eventType, info);
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace CPF.Mac.CoreFoundation
{
[Flags]
public enum CFStreamEventType
{
None = 0x0,
OpenCompleted = 0x1,
HasBytesAvailable = 0x2,
CanAcceptBytes = 0x4,
ErrorOccurred = 0x8,
EndEncountered = 0x10
}
}

View File

@@ -0,0 +1,14 @@
namespace CPF.Mac.CoreFoundation
{
public enum CFStreamStatus
{
NotOpen,
Opening,
Open,
Reading,
Writing,
AtEnd,
Closed,
Error
}
}

View File

@@ -0,0 +1,151 @@
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);
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFType
{
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", EntryPoint = "CFGetTypeID")]
public static extern int GetTypeID(IntPtr typeRef);
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFCopyDescription(IntPtr ptr);
public string GetDescription(IntPtr handle)
{
if (handle == IntPtr.Zero)
{
throw new ArgumentNullException("handle");
}
using (CFString cFString = new CFString(CFCopyDescription(handle)))
{
return cFString.ToString();
}
}
}
}

View File

@@ -0,0 +1,102 @@
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFUrl : INativeObject, IDisposable
{
internal IntPtr handle;
public IntPtr Handle => handle;
public string FileSystemPath => GetFileSystemPath(handle);
~CFUrl()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern IntPtr CFURLCreateWithFileSystemPath(IntPtr allocator, IntPtr cfstringref, CFUrlPathStyle pathstyle, bool isdir);
internal CFUrl(IntPtr handle)
{
this.handle = handle;
}
public static CFUrl FromFile(string filename)
{
using (CFString cFString = new CFString(filename))
{
IntPtr value = CFURLCreateWithFileSystemPath(IntPtr.Zero, cFString.Handle, CFUrlPathStyle.POSIX, isdir: false);
if (value == IntPtr.Zero)
{
return null;
}
return new CFUrl(value);
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", CharSet = CharSet.Unicode)]
private static extern IntPtr CFURLCreateWithString(IntPtr allocator, IntPtr stringref, IntPtr baseUrl);
public static CFUrl FromUrlString(string url, CFUrl baseurl)
{
using (CFString cFString = new CFString(url))
{
return FromStringHandle(cFString.Handle, baseurl);
}
}
internal static CFUrl FromStringHandle(IntPtr cfstringHandle, CFUrl baseurl)
{
IntPtr value = CFURLCreateWithString(IntPtr.Zero, cfstringHandle, baseurl?.Handle ?? IntPtr.Zero);
if (value == IntPtr.Zero)
{
return null;
}
return new CFUrl(value);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFURLGetString(IntPtr anURL);
public override string ToString()
{
using (CFString cFString = new CFString(CFURLGetString(handle)))
{
return cFString.ToString();
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFURLCopyFileSystemPath(IntPtr cfUrl, int style);
internal static string GetFileSystemPath(IntPtr hcfurl)
{
using (CFString cFString = new CFString(CFURLCopyFileSystemPath(hcfurl, 0), owns: true))
{
return cFString.ToString();
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", EntryPoint = "CFURLGetTypeID")]
public static extern int GetTypeID();
}
}

View File

@@ -0,0 +1,9 @@
namespace CPF.Mac.CoreFoundation
{
public enum CFUrlPathStyle
{
POSIX,
HFS,
Windows
}
}

View File

@@ -0,0 +1,134 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class CFWriteStream : CFStream
{
internal CFWriteStream(IntPtr handle)
: base(handle)
{
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFWriteStreamCopyError(IntPtr handle);
public override CFException GetError()
{
IntPtr intPtr = CFWriteStreamCopyError(base.Handle);
if (intPtr == IntPtr.Zero)
{
return null;
}
return CFException.FromCFError(intPtr);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFWriteStreamOpen(IntPtr handle);
protected override bool DoOpen()
{
return CFWriteStreamOpen(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFWriteStreamClose(IntPtr handle);
protected override void DoClose()
{
CFWriteStreamClose(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFStreamStatus CFWriteStreamGetStatus(IntPtr handle);
protected override CFStreamStatus DoGetStatus()
{
return CFWriteStreamGetStatus(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFWriteStreamCanAcceptBytes(IntPtr handle);
public bool CanAcceptBytes()
{
return CFWriteStreamCanAcceptBytes(base.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern CFIndex CFWriteStreamWrite(IntPtr handle, IntPtr buffer, CFIndex count);
public int Write(byte[] buffer)
{
return Write(buffer, 0, buffer.Length);
}
public int Write(byte[] buffer, int offset, int count)
{
CheckHandle();
if (offset < 0)
{
throw new ArgumentException();
}
if (count < 1)
{
throw new ArgumentException();
}
if (offset + count > buffer.Length)
{
throw new ArgumentException();
}
GCHandle gCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
return CFWriteStreamWrite(buffer: new IntPtr(gCHandle.AddrOfPinnedObject().ToInt64() + offset), handle: base.Handle, count: count);
}
finally
{
gCHandle.Free();
}
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFWriteStreamSetClient(IntPtr stream, CFIndex eventTypes, CFStreamCallback cb, IntPtr context);
protected override bool DoSetClient(CFStreamCallback callback, CFIndex eventTypes, IntPtr context)
{
return CFWriteStreamSetClient(base.Handle, eventTypes, callback, context);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFWriteStreamScheduleWithRunLoop(IntPtr handle, IntPtr loop, IntPtr mode);
protected override void ScheduleWithRunLoop(CFRunLoop loop, NSString mode)
{
CFWriteStreamScheduleWithRunLoop(base.Handle, loop.Handle, mode.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern void CFWriteStreamUnscheduleFromRunLoop(IntPtr handle, IntPtr loop, IntPtr mode);
protected override void UnscheduleFromRunLoop(CFRunLoop loop, NSString mode)
{
CFWriteStreamUnscheduleFromRunLoop(base.Handle, loop.Handle, mode.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern IntPtr CFReadStreamCopyProperty(IntPtr handle, IntPtr name);
protected override IntPtr DoGetProperty(NSString name)
{
return CFReadStreamCopyProperty(base.Handle, name.Handle);
}
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private static extern bool CFWriteStreamSetProperty(IntPtr handle, IntPtr name, IntPtr value);
protected override bool DoSetProperty(NSString name, INativeObject value)
{
return CFWriteStreamSetProperty(base.Handle, name.Handle, value.Handle);
}
}
}

View File

@@ -0,0 +1,71 @@
using CPF.Mac.Foundation;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public class DispatchGroup : DispatchObject
{
private DispatchGroup(IntPtr handle, bool owns)
: base(handle, owns)
{
}
public static DispatchGroup Create()
{
IntPtr intPtr = dispatch_group_create();
if (intPtr == IntPtr.Zero)
{
return null;
}
return new DispatchGroup(intPtr, owns: true);
}
public void DispatchAsync(DispatchQueue queue, NSAction action)
{
if (queue == null)
{
throw new ArgumentNullException("queue");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
Check();
dispatch_group_async_f(handle, queue.handle, (IntPtr)GCHandle.Alloc(Tuple.Create(action, queue)), DispatchQueue.static_dispatch);
}
public void Enter()
{
Check();
dispatch_group_enter(handle);
}
public void Leave()
{
Check();
dispatch_group_leave(handle);
}
public bool Wait(DispatchTime timeout)
{
Check();
return dispatch_group_wait(handle, timeout.Nanoseconds) == IntPtr.Zero;
}
[DllImport("libc")]
private static extern IntPtr dispatch_group_create();
[DllImport("libc")]
private static extern void dispatch_group_async_f(IntPtr group, IntPtr queue, IntPtr context, DispatchQueue.dispatch_callback_t block);
[DllImport("libc")]
private static extern void dispatch_group_enter(IntPtr group);
[DllImport("libc")]
private static extern void dispatch_group_leave(IntPtr group);
[DllImport("libc")]
private static extern IntPtr dispatch_group_wait(IntPtr group, ulong timeout);
}
}

View File

@@ -0,0 +1,123 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreFoundation
{
public abstract class DispatchObject : INativeObject, IDisposable
{
internal IntPtr handle;
public IntPtr Handle => handle;
[Preserve(Conditional = true)]
internal DispatchObject(IntPtr handle, bool owns)
{
if (handle == IntPtr.Zero)
{
throw new ArgumentNullException("handle");
}
this.handle = handle;
if (!owns)
{
dispatch_retain(handle);
}
}
internal DispatchObject()
{
}
[DllImport("libc")]
private static extern IntPtr dispatch_release(IntPtr o);
[DllImport("libc")]
private static extern IntPtr dispatch_retain(IntPtr o);
~DispatchObject()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
dispatch_release(handle);
handle = IntPtr.Zero;
}
}
public static bool operator ==(DispatchObject a, DispatchObject b)
{
if ((object)a == null)
{
if ((object)b == null)
{
return true;
}
return false;
}
if ((object)b == null)
{
return false;
}
return a.handle == b.handle;
}
public static bool operator !=(DispatchObject a, DispatchObject b)
{
if ((object)a == null)
{
if ((object)b == null)
{
return false;
}
return true;
}
if ((object)b == null)
{
return true;
}
return a.handle != b.handle;
}
public override bool Equals(object other)
{
if (other == null)
{
return false;
}
return (other as DispatchQueue).handle == handle;
}
public override int GetHashCode()
{
return (int)handle;
}
protected void Check()
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException(GetType().ToString());
}
}
[DllImport("libc")]
private static extern void dispatch_set_target_queue(IntPtr queue, IntPtr target);
public void SetTargetQueue(DispatchQueue queue)
{
IntPtr target = (queue == null) ? IntPtr.Zero : queue.Handle;
dispatch_set_target_queue(handle, target);
}
}
}

View File

@@ -0,0 +1,208 @@
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace CPF.Mac.CoreFoundation
{
public class DispatchQueue : DispatchObject
{
internal delegate void dispatch_callback_t(IntPtr context);
private static IntPtr main_q;
private static object lockobj = new object();
internal static readonly dispatch_callback_t static_dispatch = static_dispatcher_to_managed;
public string Label
{
get
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("DispatchQueue");
}
return Marshal.PtrToStringAnsi(dispatch_queue_get_label(handle));
}
}
public IntPtr Context
{
get
{
Check();
return dispatch_get_context(handle);
}
set
{
Check();
dispatch_set_context(handle, value);
}
}
[Obsolete("Deprecated in iOS 6.0")]
public static DispatchQueue CurrentQueue => new DispatchQueue(dispatch_get_current_queue(), owns: false);
public static DispatchQueue DefaultGlobalQueue => new DispatchQueue(dispatch_get_global_queue((IntPtr)0, IntPtr.Zero), owns: false);
public static DispatchQueue MainQueue
{
get
{
lock (lockobj)
{
if (main_q == IntPtr.Zero)
{
main_q = Dlfcn.dlsym((IntPtr)(-2), "_dispatch_main_q");
if (main_q == IntPtr.Zero)
{
IntPtr handle = Dlfcn.dlopen("/usr/lib/libSystem.dylib", 0);
main_q = Dlfcn.GetIndirect(handle, "_dispatch_main_q");
Dlfcn.dlclose(handle);
}
}
}
if (main_q == IntPtr.Zero)
{
return PInvokeDispatchGetMainQueue();
}
return new DispatchQueue(main_q, owns: false);
}
}
[Preserve(Conditional = true)]
internal DispatchQueue(IntPtr handle, bool owns)
: base(handle, owns)
{
}
public DispatchQueue(IntPtr handle)
: base(handle, owns: false)
{
}
public DispatchQueue(string label)
{
handle = dispatch_queue_create(label, IntPtr.Zero);
if (handle == IntPtr.Zero)
{
throw new Exception("Error creating dispatch queue");
}
}
[DllImport("libc")]
private static extern void dispatch_suspend(IntPtr o);
public void Suspend()
{
Check();
dispatch_suspend(handle);
}
[DllImport("libc")]
private static extern void dispatch_resume(IntPtr o);
public void Resume()
{
Check();
dispatch_resume(handle);
}
[DllImport("libc")]
private static extern IntPtr dispatch_get_context(IntPtr o);
[DllImport("libc")]
private static extern void dispatch_set_context(IntPtr o, IntPtr ctx);
public static DispatchQueue GetGlobalQueue(DispatchQueuePriority priority)
{
return new DispatchQueue(dispatch_get_global_queue((IntPtr)(int)priority, IntPtr.Zero), owns: false);
}
private static DispatchQueue PInvokeDispatchGetMainQueue()
{
return new DispatchQueue(dispatch_get_main_queue(), owns: false);
}
[MonoPInvokeCallback(typeof(dispatch_callback_t))]
private static void static_dispatcher_to_managed(IntPtr context)
{
GCHandle gCHandle = GCHandle.FromIntPtr(context);
Tuple<NSAction, DispatchQueue> tuple = gCHandle.Target as Tuple<NSAction, DispatchQueue>;
if (tuple != null)
{
SynchronizationContext current = SynchronizationContext.Current;
if (current == null)
{
SynchronizationContext.SetSynchronizationContext(new DispatchQueueSynchronizationContext(tuple.Item2));
}
try
{
tuple.Item1();
}
catch
{
gCHandle.Free();
throw;
}
finally
{
if (current == null)
{
SynchronizationContext.SetSynchronizationContext(null);
}
}
}
gCHandle.Free();
}
public void DispatchAsync(NSAction action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
dispatch_async_f(handle, (IntPtr)GCHandle.Alloc(Tuple.Create(action, this)), static_dispatch);
}
public void DispatchSync(NSAction action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
dispatch_sync_f(handle, (IntPtr)GCHandle.Alloc(Tuple.Create(action, this)), static_dispatch);
}
[DllImport("libc")]
private static extern IntPtr dispatch_queue_create(string label, IntPtr attr);
[DllImport("libc")]
private static extern void dispatch_async_f(IntPtr queue, IntPtr context, dispatch_callback_t dispatch);
[DllImport("libc")]
private static extern void dispatch_sync_f(IntPtr queue, IntPtr context, dispatch_callback_t dispatch);
[DllImport("libc")]
private static extern IntPtr dispatch_get_current_queue();
[DllImport("libc")]
private static extern IntPtr dispatch_get_global_queue(IntPtr priority, IntPtr flags);
[DllImport("libc")]
private static extern IntPtr dispatch_get_main_queue();
[DllImport("libc")]
private static extern IntPtr dispatch_queue_get_label(IntPtr queue);
[DllImport("libc")]
private static extern IntPtr dispatch_main();
public static void MainIteration()
{
dispatch_main();
}
}
}

View File

@@ -0,0 +1,9 @@
namespace CPF.Mac.CoreFoundation
{
public enum DispatchQueuePriority
{
High = 2,
Default = 0,
Low = -2
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Threading;
namespace CPF.Mac.CoreFoundation
{
internal sealed class DispatchQueueSynchronizationContext : SynchronizationContext
{
private readonly DispatchQueue queue;
public DispatchQueueSynchronizationContext(DispatchQueue dispatchQueue)
{
if (dispatchQueue == null)
{
throw new ArgumentNullException("dispatchQueue");
}
queue = dispatchQueue;
}
public override SynchronizationContext CreateCopy()
{
return new DispatchQueueSynchronizationContext(queue);
}
public override void Post(SendOrPostCallback d, object state)
{
queue.DispatchAsync(delegate
{
d(state);
});
}
public override void Send(SendOrPostCallback d, object state)
{
queue.DispatchSync(delegate
{
d(state);
});
}
}
}

View File

@@ -0,0 +1,21 @@
namespace CPF.Mac.CoreFoundation
{
public struct DispatchTime
{
public static readonly DispatchTime Now = default(DispatchTime);
public static readonly DispatchTime Forever = new DispatchTime(ulong.MaxValue);
public ulong Nanoseconds
{
get;
private set;
}
public DispatchTime(ulong nanoseconds)
{
this = default(DispatchTime);
Nanoseconds = nanoseconds;
}
}
}

View File

@@ -0,0 +1,8 @@
using CPF.Mac.ObjCRuntime;
namespace CPF.Mac.CoreFoundation
{
public interface ICFType : INativeObject
{
}
}

View File

@@ -0,0 +1,26 @@
namespace CPF.Mac.CoreFoundation
{
internal static class Tuple
{
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new Tuple<T1, T2>(item1, item2);
}
}
internal class Tuple<T1, T2>
{
private T1 item1;
private T2 item2;
public T1 Item1 => item1;
public T2 Item2 => item2;
public Tuple(T1 item1, T2 item2)
{
this.item1 = item1;
this.item2 = item2;
}
}
}