[CF[Read|Write|HTTP]Stream] Subclass NativeObject + numerous other code updates (#13127)
* Subclass NativeObject to reuse object lifetime code. * Enable nullability and fix code accordingly. * Use 'is' and 'is not' instead of '==' and '!=' for object identity. * Use the null-safe NativeObjectExtensions.GetHandle extension method to get the handle instead of checking for null (avoids some code duplication). * Use 'nameof (parameter)' instead of string constants. * Call 'GetCheckedHandle ()' (which will throw an ObjectDisposedException if Handle == IntPtr.Zero) instead of manually checking for IntPtr.Zero and throwing ObjectDisposedException. * Use Array.Empty<T> instead of creating an empty array manually. * Remove the (IntPtr) constructor for XAMCORE_4_0. * Add an internal (IntPtr, bool) constructor.
This commit is contained in:
Родитель
cf8008cbc0
Коммит
a28fc44056
|
@ -7,6 +7,8 @@
|
||||||
// Copyright 2012-2015 Xamarin Inc. (http://www.xamarin.com)
|
// Copyright 2012-2015 Xamarin Inc. (http://www.xamarin.com)
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Foundation;
|
using Foundation;
|
||||||
using CoreFoundation;
|
using CoreFoundation;
|
||||||
|
@ -28,12 +30,12 @@ namespace CoreServices {
|
||||||
#endif
|
#endif
|
||||||
public partial class CFHTTPStream : CFReadStream {
|
public partial class CFHTTPStream : CFReadStream {
|
||||||
|
|
||||||
internal CFHTTPStream (IntPtr handle)
|
internal CFHTTPStream (IntPtr handle, bool owns)
|
||||||
: base (handle)
|
: base (handle, owns)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri FinalURL {
|
public Uri? FinalURL {
|
||||||
get {
|
get {
|
||||||
var handle = GetProperty (_FinalURL);
|
var handle = GetProperty (_FinalURL);
|
||||||
if (handle == IntPtr.Zero)
|
if (handle == IntPtr.Zero)
|
||||||
|
@ -44,12 +46,12 @@ namespace CoreServices {
|
||||||
throw new InvalidCastException ();
|
throw new InvalidCastException ();
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var url = new CFUrl (handle))
|
using (var url = new CFUrl (handle, false))
|
||||||
return new Uri (url.ToString ());
|
return new Uri (url.ToString ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CFHTTPMessage GetFinalRequest ()
|
public CFHTTPMessage? GetFinalRequest ()
|
||||||
{
|
{
|
||||||
var handle = GetProperty (_FinalRequest);
|
var handle = GetProperty (_FinalRequest);
|
||||||
if (handle == IntPtr.Zero)
|
if (handle == IntPtr.Zero)
|
||||||
|
@ -63,7 +65,7 @@ namespace CoreServices {
|
||||||
return new CFHTTPMessage (handle, true);
|
return new CFHTTPMessage (handle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CFHTTPMessage GetResponseHeader ()
|
public CFHTTPMessage? GetResponseHeader ()
|
||||||
{
|
{
|
||||||
var handle = GetProperty (_ResponseHeader);
|
var handle = GetProperty (_ResponseHeader);
|
||||||
if (handle == IntPtr.Zero)
|
if (handle == IntPtr.Zero)
|
||||||
|
@ -132,8 +134,8 @@ namespace CoreServices {
|
||||||
#if !WATCHOS
|
#if !WATCHOS
|
||||||
public void SetProxy (CFProxySettings proxySettings)
|
public void SetProxy (CFProxySettings proxySettings)
|
||||||
{
|
{
|
||||||
if (proxySettings == null)
|
if (proxySettings is null)
|
||||||
throw new ArgumentNullException ("proxySettings");
|
throw new ArgumentNullException (nameof (proxySettings));
|
||||||
|
|
||||||
SetProperty (_Proxy, proxySettings.Dictionary);
|
SetProperty (_Proxy, proxySettings.Dictionary);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,9 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CoreFoundation;
|
using CoreFoundation;
|
||||||
using Foundation;
|
using Foundation;
|
||||||
|
@ -43,15 +41,22 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
// CFStream.h
|
// CFStream.h
|
||||||
public class CFReadStream : CFStream {
|
public class CFReadStream : CFStream {
|
||||||
|
#if !XAMCORE_4_0
|
||||||
public CFReadStream (IntPtr handle)
|
public CFReadStream (IntPtr handle)
|
||||||
: base (handle)
|
: base (handle, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal CFReadStream (IntPtr handle, bool owns)
|
||||||
|
: base (handle, owns)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
extern static /* CFErrorRef */ IntPtr CFReadStreamCopyError (/* CFReadStreamRef */ IntPtr stream);
|
extern static /* CFErrorRef */ IntPtr CFReadStreamCopyError (/* CFReadStreamRef */ IntPtr stream);
|
||||||
|
|
||||||
public override CFException GetError ()
|
public override CFException? GetError ()
|
||||||
{
|
{
|
||||||
var error = CFReadStreamCopyError (Handle);
|
var error = CFReadStreamCopyError (Handle);
|
||||||
if (error == IntPtr.Zero)
|
if (error == IntPtr.Zero)
|
||||||
|
@ -96,36 +101,36 @@ namespace CoreFoundation {
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
extern static void CFReadStreamScheduleWithRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
extern static void CFReadStreamScheduleWithRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
||||||
|
|
||||||
protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString mode)
|
protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString? mode)
|
||||||
{
|
{
|
||||||
if (loop == null)
|
if (loop is null)
|
||||||
throw new ArgumentNullException ("loop");
|
throw new ArgumentNullException (nameof (loop));
|
||||||
if (mode == null)
|
if (mode is null)
|
||||||
throw new ArgumentNullException ("mode");
|
throw new ArgumentNullException (nameof (mode));
|
||||||
CFReadStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle);
|
CFReadStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
extern static void CFReadStreamUnscheduleFromRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
extern static void CFReadStreamUnscheduleFromRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
||||||
|
|
||||||
protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode)
|
protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString? mode)
|
||||||
{
|
{
|
||||||
if (loop == null)
|
if (loop is null)
|
||||||
throw new ArgumentNullException ("loop");
|
throw new ArgumentNullException (nameof (loop));
|
||||||
if (mode == null)
|
if (mode is null)
|
||||||
throw new ArgumentNullException ("mode");
|
throw new ArgumentNullException (nameof (mode));
|
||||||
CFReadStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle);
|
CFReadStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
[return: MarshalAs (UnmanagedType.I1)]
|
[return: MarshalAs (UnmanagedType.I1)]
|
||||||
static extern bool CFReadStreamSetClient (/* CFReadStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents,
|
static extern bool CFReadStreamSetClient (/* CFReadStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents,
|
||||||
/* CFReadStreamClientCallBack */ CFStreamCallback clientCB, /* CFStreamClientContext* */ IntPtr clientContext);
|
/* CFReadStreamClientCallBack */ CFStreamCallback? clientCB, /* CFStreamClientContext* */ IntPtr clientContext);
|
||||||
|
|
||||||
protected override bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes,
|
protected override bool DoSetClient (CFStreamCallback? callback, CFIndex eventTypes,
|
||||||
IntPtr context)
|
IntPtr context)
|
||||||
{
|
{
|
||||||
return CFReadStreamSetClient (Handle, eventTypes, callback, context);
|
return CFReadStreamSetClient (Handle, (nint) eventTypes, callback, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
|
@ -133,16 +138,16 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
public nint Read (byte[] buffer)
|
public nint Read (byte[] buffer)
|
||||||
{
|
{
|
||||||
if (buffer == null)
|
if (buffer is null)
|
||||||
throw new ArgumentNullException ("buffer");
|
throw new ArgumentNullException (nameof (buffer));
|
||||||
return Read (buffer, 0, buffer.Length);
|
return Read (buffer, 0, buffer.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe nint Read (byte[] buffer, int offset, int count)
|
public unsafe nint Read (byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (buffer == null)
|
if (buffer is null)
|
||||||
throw new ArgumentNullException ("buffer");
|
throw new ArgumentNullException (nameof (buffer));
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
throw new ArgumentException ();
|
throw new ArgumentException ();
|
||||||
if (count < 1)
|
if (count < 1)
|
||||||
|
@ -158,8 +163,8 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
protected override IntPtr DoGetProperty (NSString name)
|
protected override IntPtr DoGetProperty (NSString name)
|
||||||
{
|
{
|
||||||
if (name == null)
|
if (name is null)
|
||||||
throw new ArgumentNullException ("name");
|
throw new ArgumentNullException (nameof (name));
|
||||||
return CFReadStreamCopyProperty (Handle, name.Handle);
|
return CFReadStreamCopyProperty (Handle, name.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,11 +172,11 @@ namespace CoreFoundation {
|
||||||
[return: MarshalAs (UnmanagedType.I1)]
|
[return: MarshalAs (UnmanagedType.I1)]
|
||||||
extern static /* Boolean */ bool CFReadStreamSetProperty (/* CFReadStreamRef */ IntPtr stream, /* CFStreamRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr propertyValue);
|
extern static /* Boolean */ bool CFReadStreamSetProperty (/* CFReadStreamRef */ IntPtr stream, /* CFStreamRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr propertyValue);
|
||||||
|
|
||||||
protected override bool DoSetProperty (NSString name, INativeObject value)
|
protected override bool DoSetProperty (NSString name, INativeObject? value)
|
||||||
{
|
{
|
||||||
if (name == null)
|
if (name is null)
|
||||||
throw new ArgumentNullException ("name");
|
throw new ArgumentNullException (nameof (name));
|
||||||
return CFReadStreamSetProperty (Handle, name.Handle, value == null ? IntPtr.Zero : value.Handle);
|
return CFReadStreamSetProperty (Handle, name.Handle, value.GetHandle ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
@ -84,14 +86,13 @@ namespace CoreFoundation {
|
||||||
CFReadStreamRef_InvokeRelease (release, Info);
|
CFReadStreamRef_InvokeRelease (release, Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString ()
|
public override string? ToString ()
|
||||||
{
|
{
|
||||||
if (copyDescription != IntPtr.Zero) {
|
if (copyDescription != IntPtr.Zero) {
|
||||||
var ptr = CFReadStreamRef_InvokeCopyDescription (copyDescription, Info);
|
var ptr = CFReadStreamRef_InvokeCopyDescription (copyDescription, Info);
|
||||||
if (ptr != IntPtr.Zero) {
|
if (ptr != IntPtr.Zero) {
|
||||||
// Copy* -> so we must not retain again
|
// Copy* -> so we must not retain again
|
||||||
using (var s = new CFString (ptr, true))
|
return CFString.FromHandle (ptr, true);
|
||||||
return s.ToString ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return base.ToString ();
|
return base.ToString ();
|
||||||
|
@ -151,11 +152,10 @@ namespace CoreFoundation {
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class CFStream : CFType, INativeObject, IDisposable {
|
public abstract class CFStream : CFType {
|
||||||
IntPtr handle;
|
|
||||||
GCHandle gch;
|
GCHandle gch;
|
||||||
CFRunLoop loop;
|
CFRunLoop? loop;
|
||||||
NSString loopMode;
|
NSString? loopMode;
|
||||||
bool open, closed;
|
bool open, closed;
|
||||||
|
|
||||||
#region Stream Constructors
|
#region Stream Constructors
|
||||||
|
@ -209,13 +209,13 @@ namespace CoreFoundation {
|
||||||
public static void CreatePairWithSocket (CFSocket socket, out CFReadStream readStream,
|
public static void CreatePairWithSocket (CFSocket socket, out CFReadStream readStream,
|
||||||
out CFWriteStream writeStream)
|
out CFWriteStream writeStream)
|
||||||
{
|
{
|
||||||
if (socket == null)
|
if (socket is null)
|
||||||
throw new ArgumentNullException ("socket");
|
throw new ArgumentNullException (nameof (socket));
|
||||||
|
|
||||||
IntPtr read, write;
|
IntPtr read, write;
|
||||||
CFStreamCreatePairWithSocket (IntPtr.Zero, socket.GetNative (), out read, out write);
|
CFStreamCreatePairWithSocket (IntPtr.Zero, socket.GetNative (), out read, out write);
|
||||||
readStream = new CFReadStream (read);
|
readStream = new CFReadStream (read, true);
|
||||||
writeStream = new CFWriteStream (write);
|
writeStream = new CFWriteStream (write, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !NET
|
#if !NET
|
||||||
|
@ -274,8 +274,8 @@ namespace CoreFoundation {
|
||||||
var sig = new CFSocketSignature (family, type, proto, address);
|
var sig = new CFSocketSignature (family, type, proto, address);
|
||||||
IntPtr read, write;
|
IntPtr read, write;
|
||||||
CFStreamCreatePairWithPeerSocketSignature (IntPtr.Zero, ref sig, out read, out write);
|
CFStreamCreatePairWithPeerSocketSignature (IntPtr.Zero, ref sig, out read, out write);
|
||||||
readStream = new CFReadStream (read);
|
readStream = new CFReadStream (read, true);
|
||||||
writeStream = new CFWriteStream (write);
|
writeStream = new CFWriteStream (write, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,15 +331,15 @@ namespace CoreFoundation {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
public static void CreatePairWithSocketToHost (IPEndPoint endpoint,
|
public static void CreatePairWithSocketToHost (IPEndPoint endpoint,
|
||||||
out CFReadStream readStream,
|
out CFReadStream? readStream,
|
||||||
out CFWriteStream writeStream)
|
out CFWriteStream? writeStream)
|
||||||
{
|
{
|
||||||
using (var host = CFHost.Create (endpoint)) {
|
using (var host = CFHost.Create (endpoint)) {
|
||||||
IntPtr read, write;
|
IntPtr read, write;
|
||||||
CFStreamCreatePairWithSocketToCFHost (IntPtr.Zero, host.Handle, endpoint.Port, out read, out write);
|
CFStreamCreatePairWithSocketToCFHost (IntPtr.Zero, host.Handle, endpoint.Port, out read, out write);
|
||||||
// API can return null streams
|
// API can return null streams
|
||||||
readStream = read == IntPtr.Zero ? null : new CFReadStream (read);
|
readStream = read == IntPtr.Zero ? null : new CFReadStream (read, true);
|
||||||
writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write);
|
writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -392,16 +392,16 @@ namespace CoreFoundation {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
public static void CreatePairWithSocketToHost (string host, int port,
|
public static void CreatePairWithSocketToHost (string host, int port,
|
||||||
out CFReadStream readStream,
|
out CFReadStream? readStream,
|
||||||
out CFWriteStream writeStream)
|
out CFWriteStream? writeStream)
|
||||||
{
|
{
|
||||||
using (var str = new CFString (host)) {
|
using (var str = new CFString (host)) {
|
||||||
IntPtr read, write;
|
IntPtr read, write;
|
||||||
CFStreamCreatePairWithSocketToHost (
|
CFStreamCreatePairWithSocketToHost (
|
||||||
IntPtr.Zero, str.Handle, port, out read, out write);
|
IntPtr.Zero, str.Handle, port, out read, out write);
|
||||||
// API not annotated (yet?) but it's safe to bet it match CFStreamCreatePairWithSocketToCFHost
|
// API not annotated (yet?) but it's safe to bet it match CFStreamCreatePairWithSocketToCFHost
|
||||||
readStream = read == IntPtr.Zero ? null : new CFReadStream (read);
|
readStream = read == IntPtr.Zero ? null : new CFReadStream (read, true);
|
||||||
writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write);
|
writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !WATCH
|
#if !WATCH
|
||||||
|
@ -431,11 +431,11 @@ namespace CoreFoundation {
|
||||||
#endif
|
#endif
|
||||||
public static CFHTTPStream CreateForHTTPRequest (CFHTTPMessage request)
|
public static CFHTTPStream CreateForHTTPRequest (CFHTTPMessage request)
|
||||||
{
|
{
|
||||||
if (request == null)
|
if (request is null)
|
||||||
throw new ArgumentNullException ("request");
|
throw new ArgumentNullException (nameof (request));
|
||||||
|
|
||||||
var handle = CFReadStreamCreateForHTTPRequest (IntPtr.Zero, request.Handle);
|
var handle = CFReadStreamCreateForHTTPRequest (IntPtr.Zero, request.Handle);
|
||||||
return new CFHTTPStream (handle);
|
return new CFHTTPStream (handle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CFHTTPStream.h in CFNetwork.framework (not CoreFoundation)
|
// CFHTTPStream.h in CFNetwork.framework (not CoreFoundation)
|
||||||
|
@ -465,24 +465,24 @@ namespace CoreFoundation {
|
||||||
#endif
|
#endif
|
||||||
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, CFReadStream body)
|
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, CFReadStream body)
|
||||||
{
|
{
|
||||||
if (request == null)
|
if (request is null)
|
||||||
throw new ArgumentNullException ("request");
|
throw new ArgumentNullException (nameof (request));
|
||||||
if (body == null)
|
if (body is null)
|
||||||
throw new ArgumentNullException ("body");
|
throw new ArgumentNullException (nameof (body));
|
||||||
|
|
||||||
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
|
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
|
||||||
return new CFHTTPStream (handle);
|
return new CFHTTPStream (handle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, NSInputStream body)
|
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, NSInputStream body)
|
||||||
{
|
{
|
||||||
if (request == null)
|
if (request is null)
|
||||||
throw new ArgumentNullException ("request");
|
throw new ArgumentNullException (nameof (request));
|
||||||
if (body == null)
|
if (body is null)
|
||||||
throw new ArgumentNullException ("body");
|
throw new ArgumentNullException (nameof (body));
|
||||||
|
|
||||||
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
|
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
|
||||||
return new CFHTTPStream (handle);
|
return new CFHTTPStream (handle, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -495,15 +495,15 @@ namespace CoreFoundation {
|
||||||
{
|
{
|
||||||
IntPtr read, write;
|
IntPtr read, write;
|
||||||
CFStreamCreateBoundPair (IntPtr.Zero, out read, out write, bufferSize);
|
CFStreamCreateBoundPair (IntPtr.Zero, out read, out write, bufferSize);
|
||||||
readStream = new CFReadStream (read);
|
readStream = new CFReadStream (read, true);
|
||||||
writeStream = new CFWriteStream (write);
|
writeStream = new CFWriteStream (write, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Stream API
|
#region Stream API
|
||||||
|
|
||||||
public abstract CFException GetError ();
|
public abstract CFException? GetError ();
|
||||||
|
|
||||||
protected void CheckError ()
|
protected void CheckError ()
|
||||||
{
|
{
|
||||||
|
@ -516,7 +516,7 @@ namespace CoreFoundation {
|
||||||
{
|
{
|
||||||
if (open || closed)
|
if (open || closed)
|
||||||
throw new InvalidOperationException ();
|
throw new InvalidOperationException ();
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
if (!DoOpen ()) {
|
if (!DoOpen ()) {
|
||||||
CheckError ();
|
CheckError ();
|
||||||
throw new InvalidOperationException ();
|
throw new InvalidOperationException ();
|
||||||
|
@ -530,8 +530,8 @@ namespace CoreFoundation {
|
||||||
{
|
{
|
||||||
if (!open)
|
if (!open)
|
||||||
return;
|
return;
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
if (loop != null) {
|
if (loop is not null) {
|
||||||
DoSetClient (null, (CFIndex) 0, IntPtr.Zero);
|
DoSetClient (null, (CFIndex) 0, IntPtr.Zero);
|
||||||
UnscheduleFromRunLoop (loop, loopMode);
|
UnscheduleFromRunLoop (loop, loopMode);
|
||||||
loop = null;
|
loop = null;
|
||||||
|
@ -549,7 +549,7 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
public CFStreamStatus GetStatus ()
|
public CFStreamStatus GetStatus ()
|
||||||
{
|
{
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
return DoGetStatus ();
|
return DoGetStatus ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,17 +557,17 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
internal IntPtr GetProperty (NSString name)
|
internal IntPtr GetProperty (NSString name)
|
||||||
{
|
{
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
return DoGetProperty (name);
|
return DoGetProperty (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IntPtr DoGetProperty (NSString name);
|
protected abstract IntPtr DoGetProperty (NSString name);
|
||||||
|
|
||||||
protected abstract bool DoSetProperty (NSString name, INativeObject value);
|
protected abstract bool DoSetProperty (NSString name, INativeObject? value);
|
||||||
|
|
||||||
internal void SetProperty (NSString name, INativeObject value)
|
internal void SetProperty (NSString name, INativeObject? value)
|
||||||
{
|
{
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
if (DoSetProperty (name, value))
|
if (DoSetProperty (name, value))
|
||||||
return;
|
return;
|
||||||
throw new InvalidOperationException (string.Format (
|
throw new InvalidOperationException (string.Format (
|
||||||
|
@ -596,11 +596,11 @@ namespace CoreFoundation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<StreamEventArgs> OpenCompletedEvent;
|
public event EventHandler<StreamEventArgs>? OpenCompletedEvent;
|
||||||
public event EventHandler<StreamEventArgs> HasBytesAvailableEvent;
|
public event EventHandler<StreamEventArgs>? HasBytesAvailableEvent;
|
||||||
public event EventHandler<StreamEventArgs> CanAcceptBytesEvent;
|
public event EventHandler<StreamEventArgs>? CanAcceptBytesEvent;
|
||||||
public event EventHandler<StreamEventArgs> ErrorEvent;
|
public event EventHandler<StreamEventArgs>? ErrorEvent;
|
||||||
public event EventHandler<StreamEventArgs> ClosedEvent;
|
public event EventHandler<StreamEventArgs>? ClosedEvent;
|
||||||
|
|
||||||
protected virtual void OnOpenCompleted (StreamEventArgs args)
|
protected virtual void OnOpenCompleted (StreamEventArgs args)
|
||||||
{
|
{
|
||||||
|
@ -639,9 +639,9 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected abstract void ScheduleWithRunLoop (CFRunLoop loop, NSString mode);
|
protected abstract void ScheduleWithRunLoop (CFRunLoop loop, NSString? mode);
|
||||||
|
|
||||||
protected abstract void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode);
|
protected abstract void UnscheduleFromRunLoop (CFRunLoop loop, NSString? mode);
|
||||||
|
|
||||||
protected delegate void CFStreamCallback (IntPtr s, nint type, IntPtr info);
|
protected delegate void CFStreamCallback (IntPtr s, nint type, IntPtr info);
|
||||||
|
|
||||||
|
@ -649,7 +649,7 @@ namespace CoreFoundation {
|
||||||
static void OnCallback (IntPtr s, nint type, IntPtr info)
|
static void OnCallback (IntPtr s, nint type, IntPtr info)
|
||||||
{
|
{
|
||||||
var stream = GCHandle.FromIntPtr (info).Target as CFStream;
|
var stream = GCHandle.FromIntPtr (info).Target as CFStream;
|
||||||
stream.OnCallback ((CFStreamEventType) (long) type);
|
stream?.OnCallback ((CFStreamEventType) (long) type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CFStreamCallback OnCallbackDelegate = OnCallback;
|
static CFStreamCallback OnCallbackDelegate = OnCallback;
|
||||||
|
@ -678,9 +678,9 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
public void EnableEvents (CFRunLoop runLoop, NSString runLoopMode)
|
public void EnableEvents (CFRunLoop runLoop, NSString runLoopMode)
|
||||||
{
|
{
|
||||||
if (open || closed || (loop != null))
|
if (open || closed || (loop is not null))
|
||||||
throw new InvalidOperationException ();
|
throw new InvalidOperationException ();
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
|
|
||||||
loop = runLoop;
|
loop = runLoop;
|
||||||
loopMode = runLoopMode;
|
loopMode = runLoopMode;
|
||||||
|
@ -699,7 +699,7 @@ namespace CoreFoundation {
|
||||||
var ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (CFStreamClientContext)));
|
var ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (CFStreamClientContext)));
|
||||||
try {
|
try {
|
||||||
Marshal.StructureToPtr (ctx, ptr, false);
|
Marshal.StructureToPtr (ctx, ptr, false);
|
||||||
if (!DoSetClient (OnCallbackDelegate, (nint) (long) args, ptr))
|
if (!DoSetClient (OnCallbackDelegate, (CFIndex) (long) args, ptr))
|
||||||
throw new InvalidOperationException ("Stream does not support async events.");
|
throw new InvalidOperationException ("Stream does not support async events.");
|
||||||
} finally {
|
} finally {
|
||||||
Marshal.FreeHGlobal (ptr);
|
Marshal.FreeHGlobal (ptr);
|
||||||
|
@ -708,46 +708,30 @@ namespace CoreFoundation {
|
||||||
ScheduleWithRunLoop (runLoop, runLoopMode);
|
ScheduleWithRunLoop (runLoop, runLoopMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes,
|
protected abstract bool DoSetClient (CFStreamCallback? callback, CFIndex eventTypes,
|
||||||
IntPtr context);
|
IntPtr context);
|
||||||
|
|
||||||
protected CFStream (IntPtr handle)
|
#if !XAMCORE_4_0
|
||||||
{
|
[Obsolete ("Call 'GetCheckedHandle ()' instead.")]
|
||||||
this.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void CheckHandle ()
|
protected void CheckHandle ()
|
||||||
{
|
{
|
||||||
if (handle == IntPtr.Zero)
|
GetCheckedHandle ();
|
||||||
throw new ObjectDisposedException (GetType ().Name);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
~CFStream ()
|
protected CFStream (IntPtr handle, bool owns)
|
||||||
|
: base (handle, owns)
|
||||||
{
|
{
|
||||||
Dispose (false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose ()
|
protected override void Dispose (bool disposing)
|
||||||
{
|
|
||||||
Dispose (true);
|
|
||||||
GC.SuppressFinalize (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntPtr Handle {
|
|
||||||
get { return handle; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose (bool disposing)
|
|
||||||
{
|
{
|
||||||
if (disposing) {
|
if (disposing) {
|
||||||
Close ();
|
Close ();
|
||||||
if (gch.IsAllocated)
|
if (gch.IsAllocated)
|
||||||
gch.Free ();
|
gch.Free ();
|
||||||
}
|
}
|
||||||
if (handle != IntPtr.Zero) {
|
base.Dispose (disposing);
|
||||||
CFObject.CFRelease (handle);
|
|
||||||
handle = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !NET
|
#if !NET
|
||||||
|
@ -779,10 +763,10 @@ namespace CoreFoundation {
|
||||||
#endif
|
#endif
|
||||||
public DispatchQueue ReadDispatchQueue {
|
public DispatchQueue ReadDispatchQueue {
|
||||||
get {
|
get {
|
||||||
return new DispatchQueue (CFReadStreamCopyDispatchQueue (handle));
|
return new DispatchQueue (CFReadStreamCopyDispatchQueue (Handle));
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
CFReadStreamSetDispatchQueue (handle, value == null ? IntPtr.Zero : value.Handle);
|
CFReadStreamSetDispatchQueue (Handle, value.GetHandle ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,10 +775,10 @@ namespace CoreFoundation {
|
||||||
#endif
|
#endif
|
||||||
public DispatchQueue WriteDispatchQueue {
|
public DispatchQueue WriteDispatchQueue {
|
||||||
get {
|
get {
|
||||||
return new DispatchQueue (CFWriteStreamCopyDispatchQueue (handle));
|
return new DispatchQueue (CFWriteStreamCopyDispatchQueue (Handle));
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
CFWriteStreamSetDispatchQueue (handle, value == null ? IntPtr.Zero : value.Handle);
|
CFWriteStreamSetDispatchQueue (Handle, value.GetHandle ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CoreFoundation;
|
using CoreFoundation;
|
||||||
|
@ -38,15 +40,15 @@ using CFIndex = System.nint;
|
||||||
namespace CoreFoundation {
|
namespace CoreFoundation {
|
||||||
|
|
||||||
public class CFWriteStream : CFStream {
|
public class CFWriteStream : CFStream {
|
||||||
internal CFWriteStream (IntPtr handle)
|
internal CFWriteStream (IntPtr handle, bool owns)
|
||||||
: base (handle)
|
: base (handle, owns)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
extern static /* CFErrorRef */ IntPtr CFWriteStreamCopyError (/* CFWriteStreamRef */ IntPtr stream);
|
extern static /* CFErrorRef */ IntPtr CFWriteStreamCopyError (/* CFWriteStreamRef */ IntPtr stream);
|
||||||
|
|
||||||
public override CFException GetError ()
|
public override CFException? GetError ()
|
||||||
{
|
{
|
||||||
var error = CFWriteStreamCopyError (Handle);
|
var error = CFWriteStreamCopyError (Handle);
|
||||||
if (error == IntPtr.Zero)
|
if (error == IntPtr.Zero)
|
||||||
|
@ -93,16 +95,16 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
public int Write (byte[] buffer)
|
public int Write (byte[] buffer)
|
||||||
{
|
{
|
||||||
if (buffer == null)
|
if (buffer is null)
|
||||||
throw new ArgumentNullException ("buffer");
|
throw new ArgumentNullException (nameof (buffer));
|
||||||
return Write (buffer, 0, buffer.Length);
|
return Write (buffer, 0, buffer.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe int Write (byte[] buffer, nint offset, nint count)
|
public unsafe int Write (byte[] buffer, nint offset, nint count)
|
||||||
{
|
{
|
||||||
if (buffer == null)
|
if (buffer is null)
|
||||||
throw new ArgumentNullException ("buffer");
|
throw new ArgumentNullException (nameof (buffer));
|
||||||
CheckHandle ();
|
GetCheckedHandle ();
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
throw new ArgumentException ();
|
throw new ArgumentException ();
|
||||||
if (count < 1)
|
if (count < 1)
|
||||||
|
@ -116,35 +118,35 @@ namespace CoreFoundation {
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
[return: MarshalAs (UnmanagedType.I1)]
|
[return: MarshalAs (UnmanagedType.I1)]
|
||||||
static extern /* Boolean */ bool CFWriteStreamSetClient (/* CFWriteStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents,
|
static extern /* Boolean */ bool CFWriteStreamSetClient (/* CFWriteStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents,
|
||||||
/* CFWriteStreamClientCallBack */ CFStreamCallback clientCB, /* CFStreamClientContext* */ IntPtr clientContext);
|
/* CFWriteStreamClientCallBack */ CFStreamCallback? clientCB, /* CFStreamClientContext* */ IntPtr clientContext);
|
||||||
|
|
||||||
protected override bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes,
|
protected override bool DoSetClient (CFStreamCallback? callback, CFIndex eventTypes,
|
||||||
IntPtr context)
|
IntPtr context)
|
||||||
{
|
{
|
||||||
return CFWriteStreamSetClient (Handle, eventTypes, callback, context);
|
return CFWriteStreamSetClient (Handle, (nint) eventTypes, callback, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
extern static void CFWriteStreamScheduleWithRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
extern static void CFWriteStreamScheduleWithRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
||||||
|
|
||||||
protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString mode)
|
protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString? mode)
|
||||||
{
|
{
|
||||||
if (loop == null)
|
if (loop is null)
|
||||||
throw new ArgumentNullException ("loop");
|
throw new ArgumentNullException (nameof (loop));
|
||||||
if (mode == null)
|
if (mode is null)
|
||||||
throw new ArgumentNullException ("mode");
|
throw new ArgumentNullException (nameof (mode));
|
||||||
CFWriteStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle);
|
CFWriteStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport (Constants.CoreFoundationLibrary)]
|
[DllImport (Constants.CoreFoundationLibrary)]
|
||||||
extern static void CFWriteStreamUnscheduleFromRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
extern static void CFWriteStreamUnscheduleFromRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
|
||||||
|
|
||||||
protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode)
|
protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString? mode)
|
||||||
{
|
{
|
||||||
if (loop == null)
|
if (loop is null)
|
||||||
throw new ArgumentNullException ("loop");
|
throw new ArgumentNullException (nameof (loop));
|
||||||
if (mode == null)
|
if (mode is null)
|
||||||
throw new ArgumentNullException ("mode");
|
throw new ArgumentNullException (nameof (mode));
|
||||||
CFWriteStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle);
|
CFWriteStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +155,8 @@ namespace CoreFoundation {
|
||||||
|
|
||||||
protected override IntPtr DoGetProperty (NSString name)
|
protected override IntPtr DoGetProperty (NSString name)
|
||||||
{
|
{
|
||||||
if (name == null)
|
if (name is null)
|
||||||
throw new ArgumentNullException ("name");
|
throw new ArgumentNullException (nameof (name));
|
||||||
return CFWriteStreamSetProperty (Handle, name.Handle);
|
return CFWriteStreamSetProperty (Handle, name.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +164,11 @@ namespace CoreFoundation {
|
||||||
[return: MarshalAs (UnmanagedType.I1)]
|
[return: MarshalAs (UnmanagedType.I1)]
|
||||||
extern static /* Boolean */ bool CFWriteStreamSetProperty (/* CFWriteStreamRef */ IntPtr stream, /* CFStringRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr value);
|
extern static /* Boolean */ bool CFWriteStreamSetProperty (/* CFWriteStreamRef */ IntPtr stream, /* CFStringRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr value);
|
||||||
|
|
||||||
protected override bool DoSetProperty (NSString name, INativeObject value)
|
protected override bool DoSetProperty (NSString name, INativeObject? value)
|
||||||
{
|
{
|
||||||
if (name == null)
|
if (name is null)
|
||||||
throw new ArgumentNullException ("name");
|
throw new ArgumentNullException (nameof (name));
|
||||||
return CFWriteStreamSetProperty (Handle, name.Handle, value == null ? IntPtr.Zero : value.Handle);
|
return CFWriteStreamSetProperty (Handle, name.Handle, value.GetHandle ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче