mirror of
https://gitee.com/csharpui/CPF.git
synced 2026-08-27 11:07:05 +08:00
初始化
This commit is contained in:
110
CPF.Mac/Mac/CoreFoundation/CFAllocator.cs
Normal file
110
CPF.Mac/Mac/CoreFoundation/CFAllocator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
CPF.Mac/Mac/CoreFoundation/CFAllocatorFlags.cs
Normal file
11
CPF.Mac/Mac/CoreFoundation/CFAllocatorFlags.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
[Flags]
|
||||
public enum CFAllocatorFlags : ulong
|
||||
{
|
||||
GCScannedMemory = 0x200,
|
||||
GCObjectMemory = 0x400
|
||||
}
|
||||
}
|
||||
131
CPF.Mac/Mac/CoreFoundation/CFArray.cs
Normal file
131
CPF.Mac/Mac/CoreFoundation/CFArray.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
98
CPF.Mac/Mac/CoreFoundation/CFBoolean.cs
Normal file
98
CPF.Mac/Mac/CoreFoundation/CFBoolean.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
CPF.Mac/Mac/CoreFoundation/CFData.cs
Normal file
91
CPF.Mac/Mac/CoreFoundation/CFData.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
CPF.Mac/Mac/CoreFoundation/CFDataBuffer.cs
Normal file
56
CPF.Mac/Mac/CoreFoundation/CFDataBuffer.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
212
CPF.Mac/Mac/CoreFoundation/CFDictionary.cs
Normal file
212
CPF.Mac/Mac/CoreFoundation/CFDictionary.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
36
CPF.Mac/Mac/CoreFoundation/CFErrorDomain.cs
Normal file
36
CPF.Mac/Mac/CoreFoundation/CFErrorDomain.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
107
CPF.Mac/Mac/CoreFoundation/CFException.cs
Normal file
107
CPF.Mac/Mac/CoreFoundation/CFException.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
39
CPF.Mac/Mac/CoreFoundation/CFExceptionDataKey.cs
Normal file
39
CPF.Mac/Mac/CoreFoundation/CFExceptionDataKey.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
CPF.Mac/Mac/CoreFoundation/CFIndex.cs
Normal file
29
CPF.Mac/Mac/CoreFoundation/CFIndex.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
21
CPF.Mac/Mac/CoreFoundation/CFMutableDictionary.cs
Normal file
21
CPF.Mac/Mac/CoreFoundation/CFMutableDictionary.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
CPF.Mac/Mac/CoreFoundation/CFObject.cs
Normal file
14
CPF.Mac/Mac/CoreFoundation/CFObject.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
35
CPF.Mac/Mac/CoreFoundation/CFRange.cs
Normal file
35
CPF.Mac/Mac/CoreFoundation/CFRange.cs
Normal 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}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
134
CPF.Mac/Mac/CoreFoundation/CFReadStream.cs
Normal file
134
CPF.Mac/Mac/CoreFoundation/CFReadStream.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
208
CPF.Mac/Mac/CoreFoundation/CFRunLoop.cs
Normal file
208
CPF.Mac/Mac/CoreFoundation/CFRunLoop.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
CPF.Mac/Mac/CoreFoundation/CFRunLoopExitReason.cs
Normal file
10
CPF.Mac/Mac/CoreFoundation/CFRunLoopExitReason.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
public enum CFRunLoopExitReason
|
||||
{
|
||||
Finished = 1,
|
||||
Stopped,
|
||||
TimedOut,
|
||||
HandledSource
|
||||
}
|
||||
}
|
||||
73
CPF.Mac/Mac/CoreFoundation/CFRunLoopSource.cs
Normal file
73
CPF.Mac/Mac/CoreFoundation/CFRunLoopSource.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
CPF.Mac/Mac/CoreFoundation/CFRunLoopSourceContext.cs
Normal file
27
CPF.Mac/Mac/CoreFoundation/CFRunLoopSourceContext.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
101
CPF.Mac/Mac/CoreFoundation/CFRunLoopSourceCustom.cs
Normal file
101
CPF.Mac/Mac/CoreFoundation/CFRunLoopSourceCustom.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
CPF.Mac/Mac/CoreFoundation/CFSocketCallBackType.cs
Normal file
15
CPF.Mac/Mac/CoreFoundation/CFSocketCallBackType.cs
Normal 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
|
||||
}
|
||||
}
|
||||
9
CPF.Mac/Mac/CoreFoundation/CFSocketError.cs
Normal file
9
CPF.Mac/Mac/CoreFoundation/CFSocketError.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
public enum CFSocketError
|
||||
{
|
||||
Success = 0,
|
||||
Error = -1,
|
||||
Timeout = -2
|
||||
}
|
||||
}
|
||||
18
CPF.Mac/Mac/CoreFoundation/CFSocketException.cs
Normal file
18
CPF.Mac/Mac/CoreFoundation/CFSocketException.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
CPF.Mac/Mac/CoreFoundation/CFSocketFlags.cs
Normal file
15
CPF.Mac/Mac/CoreFoundation/CFSocketFlags.cs
Normal 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
|
||||
}
|
||||
}
|
||||
17
CPF.Mac/Mac/CoreFoundation/CFSocketNativeHandle.cs
Normal file
17
CPF.Mac/Mac/CoreFoundation/CFSocketNativeHandle.cs
Normal 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}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
335
CPF.Mac/Mac/CoreFoundation/CFStream.cs
Normal file
335
CPF.Mac/Mac/CoreFoundation/CFStream.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
CPF.Mac/Mac/CoreFoundation/CFStreamClientContext.cs
Normal file
89
CPF.Mac/Mac/CoreFoundation/CFStreamClientContext.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
CPF.Mac/Mac/CoreFoundation/CFStreamEventType.cs
Normal file
15
CPF.Mac/Mac/CoreFoundation/CFStreamEventType.cs
Normal 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
|
||||
}
|
||||
}
|
||||
14
CPF.Mac/Mac/CoreFoundation/CFStreamStatus.cs
Normal file
14
CPF.Mac/Mac/CoreFoundation/CFStreamStatus.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
public enum CFStreamStatus
|
||||
{
|
||||
NotOpen,
|
||||
Opening,
|
||||
Open,
|
||||
Reading,
|
||||
Writing,
|
||||
AtEnd,
|
||||
Closed,
|
||||
Error
|
||||
}
|
||||
}
|
||||
151
CPF.Mac/Mac/CoreFoundation/CFString.cs
Normal file
151
CPF.Mac/Mac/CoreFoundation/CFString.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
CPF.Mac/Mac/CoreFoundation/CFType.cs
Normal file
26
CPF.Mac/Mac/CoreFoundation/CFType.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
102
CPF.Mac/Mac/CoreFoundation/CFUrl.cs
Normal file
102
CPF.Mac/Mac/CoreFoundation/CFUrl.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
9
CPF.Mac/Mac/CoreFoundation/CFUrlPathStyle.cs
Normal file
9
CPF.Mac/Mac/CoreFoundation/CFUrlPathStyle.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
public enum CFUrlPathStyle
|
||||
{
|
||||
POSIX,
|
||||
HFS,
|
||||
Windows
|
||||
}
|
||||
}
|
||||
134
CPF.Mac/Mac/CoreFoundation/CFWriteStream.cs
Normal file
134
CPF.Mac/Mac/CoreFoundation/CFWriteStream.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
CPF.Mac/Mac/CoreFoundation/DispatchGroup.cs
Normal file
71
CPF.Mac/Mac/CoreFoundation/DispatchGroup.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
123
CPF.Mac/Mac/CoreFoundation/DispatchObject.cs
Normal file
123
CPF.Mac/Mac/CoreFoundation/DispatchObject.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
208
CPF.Mac/Mac/CoreFoundation/DispatchQueue.cs
Normal file
208
CPF.Mac/Mac/CoreFoundation/DispatchQueue.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
9
CPF.Mac/Mac/CoreFoundation/DispatchQueuePriority.cs
Normal file
9
CPF.Mac/Mac/CoreFoundation/DispatchQueuePriority.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
public enum DispatchQueuePriority
|
||||
{
|
||||
High = 2,
|
||||
Default = 0,
|
||||
Low = -2
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
21
CPF.Mac/Mac/CoreFoundation/DispatchTime.cs
Normal file
21
CPF.Mac/Mac/CoreFoundation/DispatchTime.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
CPF.Mac/Mac/CoreFoundation/ICFType.cs
Normal file
8
CPF.Mac/Mac/CoreFoundation/ICFType.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using CPF.Mac.ObjCRuntime;
|
||||
|
||||
namespace CPF.Mac.CoreFoundation
|
||||
{
|
||||
public interface ICFType : INativeObject
|
||||
{
|
||||
}
|
||||
}
|
||||
26
CPF.Mac/Mac/CoreFoundation/Tuple.cs
Normal file
26
CPF.Mac/Mac/CoreFoundation/Tuple.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user