mirror of
https://gitee.com/csharpui/CPF.git
synced 2025-04-05 17:37:51 +08:00
479 lines
13 KiB
C#
479 lines
13 KiB
C#
using CPF.Mac.ObjCRuntime;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace CPF.Mac.Foundation
|
|
{
|
|
[Register("NSData", true)]
|
|
public class NSData : NSObject, IEnumerable, IEnumerable<byte>
|
|
{
|
|
private class UnmanagedMemoryStreamWithRef : UnmanagedMemoryStream
|
|
{
|
|
private NSData source;
|
|
|
|
public unsafe UnmanagedMemoryStreamWithRef(NSData source)
|
|
: base((byte*)(void*)source.Bytes, (long)source.Length)
|
|
{
|
|
this.source = source;
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
source = null;
|
|
base.Dispose(disposing);
|
|
}
|
|
}
|
|
|
|
private class UnmanagedMemoryStreamWithMutableRef : UnmanagedMemoryStreamWithRef
|
|
{
|
|
private NSData source;
|
|
|
|
private IntPtr base_address;
|
|
|
|
public UnmanagedMemoryStreamWithMutableRef(NSData source)
|
|
: base(source)
|
|
{
|
|
base_address = source.Bytes;
|
|
this.source = source;
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
source = null;
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
private static void InvalidOperation()
|
|
{
|
|
throw new InvalidOperationException("The underlying NSMutableData changed while we were consuming data");
|
|
}
|
|
|
|
public override int Read([In] [Out] byte[] buffer, int offset, int count)
|
|
{
|
|
if (base_address != source.Bytes)
|
|
{
|
|
InvalidOperation();
|
|
}
|
|
return base.Read(buffer, offset, count);
|
|
}
|
|
|
|
public override int ReadByte()
|
|
{
|
|
if (base_address != source.Bytes)
|
|
{
|
|
InvalidOperation();
|
|
}
|
|
return base.ReadByte();
|
|
}
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
if (base_address != source.Bytes)
|
|
{
|
|
InvalidOperation();
|
|
}
|
|
base.Write(buffer, offset, count);
|
|
}
|
|
|
|
public override void WriteByte(byte value)
|
|
{
|
|
if (base_address != source.Bytes)
|
|
{
|
|
InvalidOperation();
|
|
}
|
|
base.WriteByte(value);
|
|
}
|
|
}
|
|
|
|
private static readonly IntPtr selBytesHandle = Selector.GetHandle("bytes");
|
|
|
|
private static readonly IntPtr selLengthHandle = Selector.GetHandle("length");
|
|
|
|
private static readonly IntPtr selSetLength_Handle = Selector.GetHandle("setLength:");
|
|
|
|
private static readonly IntPtr selDataWithContentsOfURL_Handle = Selector.GetHandle("dataWithContentsOfURL:");
|
|
|
|
private static readonly IntPtr selDataWithContentsOfURLOptionsError_Handle = Selector.GetHandle("dataWithContentsOfURL:options:error:");
|
|
|
|
private static readonly IntPtr selDataWithContentsOfFile_Handle = Selector.GetHandle("dataWithContentsOfFile:");
|
|
|
|
private static readonly IntPtr selDataWithContentsOfFileOptionsError_Handle = Selector.GetHandle("dataWithContentsOfFile:options:error:");
|
|
|
|
private static readonly IntPtr selDataWithData_Handle = Selector.GetHandle("dataWithData:");
|
|
|
|
private static readonly IntPtr selDataWithBytesLength_Handle = Selector.GetHandle("dataWithBytes:length:");
|
|
|
|
private static readonly IntPtr selWriteToFileOptionsError_Handle = Selector.GetHandle("writeToFile:options:error:");
|
|
|
|
private static readonly IntPtr selWriteToURLOptionsError_Handle = Selector.GetHandle("writeToURL:options:error:");
|
|
|
|
private static readonly IntPtr selRangeOfDataOptionsRange_Handle = Selector.GetHandle("rangeOfData:options:range:");
|
|
|
|
private static readonly IntPtr class_ptr = Class.GetHandle("NSData");
|
|
|
|
public virtual byte this[int idx]
|
|
{
|
|
get
|
|
{
|
|
if (idx < 0 || idx >= int.MaxValue || idx > (int)Length)
|
|
{
|
|
throw new ArgumentException("idx");
|
|
}
|
|
return Marshal.ReadByte(Bytes, idx);
|
|
}
|
|
set
|
|
{
|
|
throw new NotImplementedException("NSData arrays can not be modified, use an NSMUtableData instead");
|
|
}
|
|
}
|
|
|
|
public override IntPtr ClassHandle => class_ptr;
|
|
|
|
public virtual IntPtr Bytes
|
|
{
|
|
[Export("bytes")]
|
|
get
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.IntPtr_objc_msgSend(base.Handle, selBytesHandle);
|
|
}
|
|
return Messaging.IntPtr_objc_msgSendSuper(base.SuperHandle, selBytesHandle);
|
|
}
|
|
}
|
|
|
|
public virtual ulong Length
|
|
{
|
|
[Export("length")]
|
|
get
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.UInt64_objc_msgSend(base.Handle, selLengthHandle);
|
|
}
|
|
return Messaging.UInt64_objc_msgSendSuper(base.SuperHandle, selLengthHandle);
|
|
}
|
|
set
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
internal NSData(IntPtr handle, bool owns)
|
|
: base(handle)
|
|
{
|
|
if (!owns)
|
|
{
|
|
Release();
|
|
}
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
IntPtr source = Bytes;
|
|
int top = (int)Length;
|
|
for (int i = 0; i < top; i++)
|
|
{
|
|
yield return Marshal.ReadByte(source, i);
|
|
}
|
|
}
|
|
|
|
IEnumerator<byte> IEnumerable<byte>.GetEnumerator()
|
|
{
|
|
IntPtr source = Bytes;
|
|
int top = (int)Length;
|
|
for (int i = 0; i < top; i++)
|
|
{
|
|
yield return Marshal.ReadByte(source, i);
|
|
}
|
|
}
|
|
|
|
public static NSData FromString(string s)
|
|
{
|
|
if (s == null)
|
|
{
|
|
throw new ArgumentNullException("s");
|
|
}
|
|
return new NSString(s).Encode(NSStringEncoding.UTF8);
|
|
}
|
|
|
|
public unsafe static NSData FromArray(byte[] buffer)
|
|
{
|
|
if (buffer == null)
|
|
{
|
|
throw new ArgumentNullException("buffer");
|
|
}
|
|
if (buffer.Length == 0)
|
|
{
|
|
return FromBytes(IntPtr.Zero, 0uL);
|
|
}
|
|
fixed (byte* value = &buffer[0])
|
|
{
|
|
return FromBytes((IntPtr)(void*)value, (uint)buffer.Length);
|
|
}
|
|
}
|
|
|
|
public unsafe static NSData FromStream(Stream stream)
|
|
{
|
|
if (stream == null)
|
|
{
|
|
throw new ArgumentNullException("stream");
|
|
}
|
|
if (!stream.CanRead)
|
|
{
|
|
return null;
|
|
}
|
|
NSMutableData nSMutableData = null;
|
|
long capacity;
|
|
try
|
|
{
|
|
capacity = stream.Length;
|
|
}
|
|
catch
|
|
{
|
|
capacity = 8192L;
|
|
}
|
|
nSMutableData = NSMutableData.FromCapacity((ulong)capacity);
|
|
byte[] array = new byte[32768];
|
|
try
|
|
{
|
|
int num;
|
|
while ((num = stream.Read(array, 0, array.Length)) != 0)
|
|
{
|
|
try
|
|
{
|
|
fixed (byte* value = &array[0])
|
|
{
|
|
nSMutableData.AppendBytes((IntPtr)(void*)value, (uint)num);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
}
|
|
return nSMutableData;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public virtual Stream AsStream()
|
|
{
|
|
if (this is NSMutableData)
|
|
{
|
|
return new UnmanagedMemoryStreamWithMutableRef(this);
|
|
}
|
|
return new UnmanagedMemoryStreamWithRef(this);
|
|
}
|
|
|
|
public static NSData FromString(string s, NSStringEncoding encoding)
|
|
{
|
|
return new NSString(s).Encode(encoding);
|
|
}
|
|
|
|
public static implicit operator NSData(string s)
|
|
{
|
|
return new NSString(s).Encode(NSStringEncoding.UTF8);
|
|
}
|
|
|
|
public NSString ToString(NSStringEncoding encoding)
|
|
{
|
|
return NSString.FromData(this, encoding);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return ToString(NSStringEncoding.UTF8);
|
|
}
|
|
|
|
public unsafe bool Save(string file, bool auxiliaryFile, out NSError error)
|
|
{
|
|
IntPtr ptr = default(IntPtr);
|
|
IntPtr addr = (IntPtr)(void*)(&ptr);
|
|
bool result = _Save(file, (ulong)(auxiliaryFile ? 1 : 0), addr);
|
|
error = (NSError)Runtime.GetNSObject(ptr);
|
|
return result;
|
|
}
|
|
|
|
public unsafe bool Save(string file, NSDataWritingOptions options, out NSError error)
|
|
{
|
|
IntPtr ptr = default(IntPtr);
|
|
IntPtr addr = (IntPtr)(void*)(&ptr);
|
|
bool result = _Save(file, (ulong)options, addr);
|
|
error = (NSError)Runtime.GetNSObject(ptr);
|
|
return result;
|
|
}
|
|
|
|
public unsafe bool Save(NSUrl url, bool auxiliaryFile, out NSError error)
|
|
{
|
|
IntPtr ptr = default(IntPtr);
|
|
IntPtr addr = (IntPtr)(void*)(&ptr);
|
|
bool result = _Save(url, (ulong)(auxiliaryFile ? 1 : 0), addr);
|
|
error = (NSError)Runtime.GetNSObject(ptr);
|
|
return result;
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
[Export("init")]
|
|
public NSData()
|
|
: base(NSObjectFlag.Empty)
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
base.Handle = Messaging.IntPtr_objc_msgSend(base.Handle, Selector.Init);
|
|
}
|
|
else
|
|
{
|
|
base.Handle = Messaging.IntPtr_objc_msgSendSuper(base.SuperHandle, Selector.Init);
|
|
}
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
[Export("initWithCoder:")]
|
|
public NSData(NSCoder coder)
|
|
: base(NSObjectFlag.Empty)
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
base.Handle = Messaging.IntPtr_objc_msgSend_IntPtr(base.Handle, Selector.InitWithCoder, coder.Handle);
|
|
}
|
|
else
|
|
{
|
|
base.Handle = Messaging.IntPtr_objc_msgSendSuper_IntPtr(base.SuperHandle, Selector.InitWithCoder, coder.Handle);
|
|
}
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
public NSData(NSObjectFlag t)
|
|
: base(t)
|
|
{
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
public NSData(IntPtr handle)
|
|
: base(handle)
|
|
{
|
|
}
|
|
|
|
[Export("dataWithContentsOfURL:")]
|
|
public static NSData FromUrl(NSUrl url)
|
|
{
|
|
if (url == null)
|
|
{
|
|
throw new ArgumentNullException("url");
|
|
}
|
|
return (NSData)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(class_ptr, selDataWithContentsOfURL_Handle, url.Handle));
|
|
}
|
|
|
|
[Export("dataWithContentsOfURL:options:error:")]
|
|
public static NSData FromUrl(NSUrl url, NSDataReadingOptions mask, out NSError error)
|
|
{
|
|
if (url == null)
|
|
{
|
|
throw new ArgumentNullException("url");
|
|
}
|
|
IntPtr intPtr = Marshal.AllocHGlobal(4);
|
|
Marshal.WriteInt32(intPtr, 0);
|
|
NSData result = (NSData)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr_UInt64_IntPtr(class_ptr, selDataWithContentsOfURLOptionsError_Handle, url.Handle, (ulong)mask, intPtr));
|
|
IntPtr intPtr2 = Marshal.ReadIntPtr(intPtr);
|
|
error = ((intPtr2 != IntPtr.Zero) ? ((NSError)Runtime.GetNSObject(intPtr2)) : null);
|
|
Marshal.FreeHGlobal(intPtr);
|
|
return result;
|
|
}
|
|
|
|
[Export("dataWithContentsOfFile:")]
|
|
public static NSData FromFile(string path)
|
|
{
|
|
if (path == null)
|
|
{
|
|
throw new ArgumentNullException("path");
|
|
}
|
|
IntPtr intPtr = NSString.CreateNative(path);
|
|
NSData result = (NSData)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(class_ptr, selDataWithContentsOfFile_Handle, intPtr));
|
|
NSString.ReleaseNative(intPtr);
|
|
return result;
|
|
}
|
|
|
|
[Export("dataWithContentsOfFile:options:error:")]
|
|
public static NSData FromFile(string path, NSDataReadingOptions mask, out NSError error)
|
|
{
|
|
if (path == null)
|
|
{
|
|
throw new ArgumentNullException("path");
|
|
}
|
|
IntPtr intPtr = Marshal.AllocHGlobal(4);
|
|
Marshal.WriteInt32(intPtr, 0);
|
|
IntPtr intPtr2 = NSString.CreateNative(path);
|
|
NSData result = (NSData)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr_UInt64_IntPtr(class_ptr, selDataWithContentsOfFileOptionsError_Handle, intPtr2, (ulong)mask, intPtr));
|
|
NSString.ReleaseNative(intPtr2);
|
|
IntPtr intPtr3 = Marshal.ReadIntPtr(intPtr);
|
|
error = ((intPtr3 != IntPtr.Zero) ? ((NSError)Runtime.GetNSObject(intPtr3)) : null);
|
|
Marshal.FreeHGlobal(intPtr);
|
|
return result;
|
|
}
|
|
|
|
[Export("dataWithData:")]
|
|
public static NSData FromData(NSData source)
|
|
{
|
|
if (source == null)
|
|
{
|
|
throw new ArgumentNullException("source");
|
|
}
|
|
return (NSData)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(class_ptr, selDataWithData_Handle, source.Handle));
|
|
}
|
|
|
|
[Export("dataWithBytes:length:")]
|
|
public static NSData FromBytes(IntPtr bytes, ulong size)
|
|
{
|
|
return (NSData)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr_UInt64(class_ptr, selDataWithBytesLength_Handle, bytes, size));
|
|
}
|
|
|
|
[Export("writeToFile:options:error:")]
|
|
public virtual bool _Save(string file, ulong options, IntPtr addr)
|
|
{
|
|
if (file == null)
|
|
{
|
|
throw new ArgumentNullException("file");
|
|
}
|
|
IntPtr intPtr = NSString.CreateNative(file);
|
|
bool result = (!IsDirectBinding) ? Messaging.bool_objc_msgSendSuper_IntPtr_UInt64_IntPtr(base.SuperHandle, selWriteToFileOptionsError_Handle, intPtr, options, addr) : Messaging.bool_objc_msgSend_IntPtr_UInt64_IntPtr(base.Handle, selWriteToFileOptionsError_Handle, intPtr, options, addr);
|
|
NSString.ReleaseNative(intPtr);
|
|
return result;
|
|
}
|
|
|
|
[Export("writeToURL:options:error:")]
|
|
public virtual bool _Save(NSUrl url, ulong options, IntPtr addr)
|
|
{
|
|
if (url == null)
|
|
{
|
|
throw new ArgumentNullException("url");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.bool_objc_msgSend_IntPtr_UInt64_IntPtr(base.Handle, selWriteToURLOptionsError_Handle, url.Handle, options, addr);
|
|
}
|
|
return Messaging.bool_objc_msgSendSuper_IntPtr_UInt64_IntPtr(base.SuperHandle, selWriteToURLOptionsError_Handle, url.Handle, options, addr);
|
|
}
|
|
|
|
[Export("rangeOfData:options:range:")]
|
|
public virtual NSRange Find(NSData dataToFind, NSDataSearchOptions searchOptions, NSRange searchRange)
|
|
{
|
|
if (dataToFind == null)
|
|
{
|
|
throw new ArgumentNullException("dataToFind");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.NSRange_objc_msgSend_IntPtr_UInt64_NSRange(base.Handle, selRangeOfDataOptionsRange_Handle, dataToFind.Handle, (ulong)searchOptions, searchRange);
|
|
}
|
|
return Messaging.NSRange_objc_msgSendSuper_IntPtr_UInt64_NSRange(base.SuperHandle, selRangeOfDataOptionsRange_Handle, dataToFind.Handle, (ulong)searchOptions, searchRange);
|
|
}
|
|
}
|
|
}
|