From 760ccddc67b6dab89d0f6309ab165c857d43e6d0 Mon Sep 17 00:00:00 2001 From: Leonid Shalupov Date: Sat, 7 May 2022 18:11:05 +0200 Subject: [PATCH] fixes after review https://github.com/java-native-access/jna/pull/1433 --- .../sun/jna/platform/mac/CoreFoundation.java | 44 ++++++++++++-- .../jna/platform/mac/CoreFoundationTest.java | 60 +++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java b/contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java index 34c54fe78d..f9bb3c10ba 100644 --- a/contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java +++ b/contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java @@ -383,11 +383,23 @@ class CFDictionaryRef extends CFTypeRef { */ public static class ByReference extends PointerByReference { public ByReference() { - super(); + this(null); } - public ByReference(CoreFoundation.CFStringRef value) { - super(value.getPointer()); + public ByReference(CoreFoundation.CFDictionaryRef value) { + super(value != null ? value.getPointer() : null); + } + + @Override + public void setValue(Pointer value) { + if (value != null) { + CFTypeID typeId = INSTANCE.CFGetTypeID(value); + if (!DICTIONARY_TYPE_ID.equals(typeId)) { + throw new ClassCastException("Unable to cast to CFDictionary. Type ID: " + typeId); + } + } + + super.setValue(value); } public CoreFoundation.CFDictionaryRef getDictionaryRefValue() { @@ -489,10 +501,23 @@ class CFStringRef extends CFTypeRef { */ public static class ByReference extends PointerByReference { public ByReference() { + this(null); } public ByReference(CoreFoundation.CFStringRef value) { - super(value.getPointer()); + super(value != null ? value.getPointer() : null); + } + + @Override + public void setValue(Pointer value) { + if (value != null) { + CFTypeID typeId = INSTANCE.CFGetTypeID(value); + if (!STRING_TYPE_ID.equals(typeId)) { + throw new ClassCastException("Unable to cast to CFString. Type ID: " + typeId); + } + } + + super.setValue(value); } public CoreFoundation.CFStringRef getStringRefValue() { @@ -1066,6 +1091,17 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, CFIndex c */ CFTypeID CFGetTypeID(CFTypeRef theObject); + /** + * Returns the type of a {@code CFType} object presented as a pointer. + * Allows to inspect object type without creating a {@link CFTypeRef} wrapper. + * + * @param theObject + * The pointer to {@code CFData} object to examine. + * @return A value of type {@link CFTypeID} that identifies the opaque type of + * {@code cf}. + */ + CFTypeID CFGetTypeID(Pointer theObject); + /** * @return The type identifier for the {@code CFArray} opaque type. */ diff --git a/contrib/platform/test/com/sun/jna/platform/mac/CoreFoundationTest.java b/contrib/platform/test/com/sun/jna/platform/mac/CoreFoundationTest.java index 9459369038..a046717a57 100644 --- a/contrib/platform/test/com/sun/jna/platform/mac/CoreFoundationTest.java +++ b/contrib/platform/test/com/sun/jna/platform/mac/CoreFoundationTest.java @@ -28,6 +28,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -39,6 +40,7 @@ import java.util.Random; import com.sun.jna.platform.mac.CoreFoundation.CFDictionaryRef; +import org.junit.Assert; import org.junit.Test; import com.sun.jna.Memory; @@ -258,10 +260,35 @@ public void testCFStringRefByReference() { CFMutableDictionaryRef dict = CF.CFDictionaryCreateMutable(null, new CFIndex(2), null, null); dict.setValue(key, value); + // test getStringRefValue() CFStringRef.ByReference byRef = new CFStringRef.ByReference(); assertTrue(dict.getValueIfPresent(key, byRef)); assertTrue(CF.CFEqual(value, byRef.getStringRefValue())); + // test constructor() + assertNull(new CFStringRef.ByReference().getValue()); + + // test constructor(null) + assertNull(new CFStringRef.ByReference(null).getValue()); + + // test setValue(null) + assertNotNull(byRef.getStringRefValue()); + byRef.setValue(null); + assertNull(byRef.getStringRefValue()); + + // test setValue(CFStringRef), getValue() + byRef.setValue(value.getPointer()); + assertTrue(CF.CFEqual(value, byRef.getStringRefValue())); + assertEquals(value.getPointer(), byRef.getValue()); + + // test setValue(CFDictionaryRef) + try { + byRef.setValue(dict.getPointer()); + Assert.fail("must fail"); + } catch (ClassCastException cce) { + // as it should be + } + CF.CFRelease(key); CF.CFRelease(value); CF.CFRelease(dict); @@ -277,15 +304,48 @@ public void testCFDictionaryRefByReference() { CFMutableDictionaryRef dict = CF.CFDictionaryCreateMutable(null, new CFIndex(2), null, null); dict.setValue(key, value); + // test getDictionaryRefValue() CFDictionaryRef.ByReference byRef = new CFDictionaryRef.ByReference(); assertTrue(dict.getValueIfPresent(key, byRef)); assertTrue(CF.CFEqual(value, byRef.getDictionaryRefValue())); + // test constructor() + assertNull(new CFDictionaryRef.ByReference().getValue()); + + // test constructor(null) + assertNull(new CFDictionaryRef.ByReference(null).getValue()); + + // test setValue(null) + assertNotNull(byRef.getDictionaryRefValue()); + byRef.setValue(null); + assertNull(byRef.getDictionaryRefValue()); + + // test setValue(CFDictionaryRef), getValue() + byRef.setValue(value.getPointer()); + assertTrue(CF.CFEqual(value, byRef.getDictionaryRefValue())); + assertEquals(value.getPointer(), byRef.getValue()); + + // test setValue(CFStringRef) + try { + byRef.setValue(key.getPointer()); + Assert.fail("must fail"); + } catch (ClassCastException cce) { + // as it should be + } + CF.CFRelease(key); CF.CFRelease(value); CF.CFRelease(dict); } + @Test + public void testCFGetTypeID() { + CFStringRef s1 = CFStringRef.createCFString("s1"); + assertEquals(CF.CFStringGetTypeID(), CF.CFGetTypeID(s1.getPointer())); + assertEquals(CF.CFStringGetTypeID(), CF.CFGetTypeID(s1)); + s1.release(); + } + @Test public void testCFEqual() { CFStringRef s1 = CFStringRef.createCFString("s1");