Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;

namespace CoreBluetooth.Foundation
{
internal class NSMutableDictionary : IDisposable
{
public SafeNSMutableDictionaryHandle Handle { get; private set; }

public NSMutableDictionary()
{
Handle = NativeMethods.ns_mutable_dictionary_new();
}

public IntPtr GetValue(SafeNSObjectHandle key)
{
ExceptionUtils.ThrowObjectDisposedExceptionIf(Handle.IsInvalid, this);
if (key.IsInvalid)
throw new ArgumentNullException(nameof(key));

return NativeMethods.ns_mutable_dictionary_get_value(Handle, key);
}

public bool TryGetValue(SafeNSObjectHandle key, out IntPtr value)
{
value = GetValue(key);
return value != IntPtr.Zero;
}

public void SetValue(SafeNSObjectHandle key, SafeNSObjectHandle value)
{
ExceptionUtils.ThrowObjectDisposedExceptionIf(Handle.IsInvalid, this);
if (key.IsInvalid)
throw new ArgumentNullException(nameof(key));

NativeMethods.ns_mutable_dictionary_set_value(Handle, key, value);
}

public void SetValue(string key, SafeNSObjectHandle value)
{
using var nsString = new NSString(key);
SetValue(nsString.Handle, value);
}

public void Dispose()
{
if (Handle != null && !Handle.IsInvalid)
Handle.Dispose();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,14 @@ internal static class NativeMethods

[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
internal static extern void ns_string_get_cstring_and_length(SafeNSStringHandle handle, out IntPtr ptr, out int length);

[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
internal static extern SafeNSMutableDictionaryHandle ns_mutable_dictionary_new();

[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr ns_mutable_dictionary_get_value(SafeNSMutableDictionaryHandle handle, SafeNSObjectHandle key);

[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
internal static extern void ns_mutable_dictionary_set_value(SafeNSMutableDictionaryHandle handle, SafeNSObjectHandle key, SafeNSObjectHandle value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace CoreBluetooth.Foundation
{
internal class SafeNSMutableDictionaryHandle : SafeNSObjectHandle
{
public SafeNSMutableDictionaryHandle() : base() { }
public SafeNSMutableDictionaryHandle(IntPtr handle) : base(handle) { }
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using CoreBluetooth.Foundation;
using NUnit.Framework;

namespace CoreBluetoothTests.Foundation
{
public class NSMutableDictionaryTests
{
[Test]
public void New()
{
using var nsDictionary = new NSMutableDictionary();
Assert.That(nsDictionary.Handle, Is.Not.Null);
Assert.That(nsDictionary.Handle.IsInvalid, Is.False);
}

[Test]
public void SetAndGetStringValue()
{
using var nsDictionary = new NSMutableDictionary();
using var key = new NSString("hoge");
using var value = new NSString("fuga");
nsDictionary.SetValue(key.Handle, value.Handle);

using var key2 = new NSString("hoge");
using var nSString = new NSString(nsDictionary.GetValue(key2.Handle));
Assert.That(nSString.ToString(), Is.EqualTo("fuga"));
}

[Test]
public void ReturnZeroPointerIfNotFound()
{
using var nsDictionary = new NSMutableDictionary();
using var notFoundKey = new NSString("dummy");
var gotPtr = nsDictionary.GetValue(notFoundKey.Handle);
Assert.That(gotPtr, Is.EqualTo(System.IntPtr.Zero));
}

[Test]
public void TryGetValue()
{
using var nsDictionary = new NSMutableDictionary();
using var key = new NSString("hoge");
using var value = new NSString("fuga");
nsDictionary.SetValue(key.Handle, value.Handle);

using var key2 = new NSString("hoge");
Assert.That(nsDictionary.TryGetValue(key2.Handle, out var gotPtr), Is.True);
using var nSString = new NSString(gotPtr);
Assert.That(nSString.ToString(), Is.EqualTo("fuga"));

using var notFoundKey = new NSString("dummy");
Assert.That(nsDictionary.TryGetValue(notFoundKey.Handle, out gotPtr), Is.False);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,34 @@ public func ns_string_get_cstring_and_length(_ handle: UnsafeRawPointer, _ ptr:
length.pointee = 0
}
}

@_cdecl("ns_mutable_dictionary_new")
public func ns_mutable_dictionary_new() -> UnsafeMutableRawPointer {
let instance = NSMutableDictionary()
return Unmanaged.passRetained(instance).toOpaque()
}

@_cdecl("ns_mutable_dictionary_get_value")
public func ns_mutable_dictionary_get_value(_ handle: UnsafeRawPointer, _ keyPtr: UnsafeRawPointer) -> UnsafeMutableRawPointer? {
let instance = Unmanaged<NSMutableDictionary>.fromOpaque(handle).takeUnretainedValue()

let key = Unmanaged<NSObject>.fromOpaque(keyPtr).takeUnretainedValue()
if let value = instance[key] as? NSObject {
return Unmanaged.passRetained(value).toOpaque()
}

return nil
}

@_cdecl("ns_mutable_dictionary_set_value")
public func ns_mutable_dictionary_set_value(_ handle: UnsafeRawPointer, _ keyPtr: UnsafeRawPointer, _ valuePtr: UnsafeRawPointer?) {
let instance = Unmanaged<NSMutableDictionary>.fromOpaque(handle).takeUnretainedValue()

let key = Unmanaged<NSObject>.fromOpaque(keyPtr).takeUnretainedValue()
if let valuePtr = valuePtr {
let value = Unmanaged<NSObject>.fromOpaque(valuePtr).takeUnretainedValue()
instance[key] = value
} else {
instance[key] = nil
}
}