Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mappings for CoreFoundation, IOKit, DiskArbitration #1131

Merged
merged 31 commits into from
Sep 19, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e8e3e59
Add mappings for Core Foundation framework
dbwiddis Aug 31, 2019
4c72791
Add mappings for IOKit
dbwiddis Sep 2, 2019
6940d75
Add mappings for DiskArbitration
dbwiddis Sep 2, 2019
b1cb0a5
Don't persist CFAllocatorRef
dbwiddis Sep 2, 2019
cd00036
Better type mappings
dbwiddis Sep 3, 2019
7c3db24
Fix Boolean, CFIndex, and Pointer typing
dbwiddis Sep 4, 2019
0515f66
Refactor Release to CFTypeRef class
dbwiddis Sep 4, 2019
667e2f9
Eliminate CoreFoundationUtil
dbwiddis Sep 4, 2019
bd59283
CoreFoundation type fixes
dbwiddis Sep 7, 2019
a216ab5
IOKit Object classes
dbwiddis Sep 8, 2019
b478d79
Convenience methods for IOObject#release and IOIterator#next
dbwiddis Sep 8, 2019
772e6b8
Merge branch 'master' of https://github.com/java-native-access/jna in…
dbwiddis Sep 9, 2019
b666a93
MachPort does not extend IOObject and master port does not get released
dbwiddis Sep 9, 2019
0db5ae2
Function mapper for properly typed mach ports
dbwiddis Sep 10, 2019
a51ab2a
Consistent IOObject hierarchy
dbwiddis Sep 11, 2019
7947561
Allow MachPorts to be deallocated
dbwiddis Sep 11, 2019
56c4b2e
Add CFIndex extending NativeLong
dbwiddis Sep 12, 2019
52ec379
Add IOKitUtil class
dbwiddis Sep 12, 2019
6ce42cc
Merge branch 'master' of https://github.com/java-native-access/jna in…
dbwiddis Sep 14, 2019
6c9a8c0
Properly type mach_port_t and friends
dbwiddis Sep 15, 2019
06c3257
Mach ports back to 32-bit ints
dbwiddis Sep 17, 2019
1ab47ac
Simplify tests and enable null return util
dbwiddis Sep 17, 2019
b0b3c0c
Merge branch 'master' of https://github.com/java-native-access/jna in…
dbwiddis Sep 18, 2019
8b49dea
Move registry getters to IORegistryEntry class
dbwiddis Sep 18, 2019
1c2f213
CoreFoundation convenience methods
dbwiddis Sep 18, 2019
46e9ec4
IOKit convenience methods
dbwiddis Sep 18, 2019
a9db43b
TypeID checking
dbwiddis Sep 18, 2019
3528421
Return primitive types from convenience methods
dbwiddis Sep 18, 2019
7fae6ab
IOReturn exception handling
dbwiddis Sep 18, 2019
9628162
Fix tests
dbwiddis Sep 18, 2019
fb21633
Checkstyle doesn't like trailing spaces
dbwiddis Sep 19, 2019
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
75 changes: 67 additions & 8 deletions contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ public interface CoreFoundation extends Library {
* Foundation objects.
*/
class CFTypeRef extends PointerType {
public CFTypeRef() {
super();
}

public CFTypeRef(Pointer p) {
super(p);
}
}

/**
Expand All @@ -84,6 +91,13 @@ class CFAllocatorRef extends CFTypeRef {
* A reference to a {@code CFNumber} object.
*/
class CFNumberRef extends CFTypeRef {
public CFNumberRef() {
super();
}

public CFNumberRef(Pointer p) {
super(p);
}
}

/**
Expand All @@ -102,6 +116,13 @@ enum CFNumberType {
* A reference to a {@code CFBoolean} object.
*/
class CFBooleanRef extends CFTypeRef {
public CFBooleanRef() {
super();
}

public CFBooleanRef(Pointer p) {
super(p);
}
}

/**
Expand All @@ -112,24 +133,52 @@ class CFBooleanRef extends CFTypeRef {
* parameter, you can pass in a {@link #CFArrayRef}.
*/
class CFArrayRef extends CFTypeRef {
public CFArrayRef() {
super();
}

public CFArrayRef(Pointer p) {
super(p);
}
}

/**
* A reference to an immutable {@code CFData} object.
*/
class CFDataRef extends CFTypeRef {
public CFDataRef() {
super();
}

public CFDataRef(Pointer p) {
super(p);
}
}

/**
* A reference to an immutable {@code CFDictionary} object.
*/
class CFDictionaryRef extends CFTypeRef {
public CFDictionaryRef() {
super();
}

public CFDictionaryRef(Pointer p) {
super(p);
}
}

/**
* A reference to a mutable {@code CFDictionary} object.
*/
class CFMutableDictionaryRef extends CFDictionaryRef {
public CFMutableDictionaryRef() {
super();
}

public CFMutableDictionaryRef(Pointer p) {
super(p);
}
}

/**
Expand All @@ -138,6 +187,14 @@ class CFMutableDictionaryRef extends CFDictionaryRef {
* the characteristics and behavior of {@code CFString} objects.
*/
class CFStringRef extends CFTypeRef {
public CFStringRef() {
super();
}

public CFStringRef(Pointer p) {
super(p);
}

/**
* Convenience function which calls {@link #CFStringCreateWithCharacters} to
* create a new {@code CFString} from the given Java {@link java.lang.String}
Expand Down Expand Up @@ -394,7 +451,7 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* {@link #CFDictionaryGetValueIfPresent} to distinguish between a value
* that is not found, and a {@code null} value.
*/
CFTypeRef CFDictionaryGetValue(CFTypeRef theDict, CFStringRef key);
Pointer CFDictionaryGetValue(CFTypeRef theDict, PointerType key);
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns a boolean value that indicates whether a given value for a given key
Expand All @@ -420,7 +477,7 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* was present).
* @return {@code true} if a matching key was found, otherwise {@code false}.
*/
boolean CFDictionaryGetValueIfPresent(CFDictionaryRef theDict, CFStringRef key, PointerType value);
boolean CFDictionaryGetValueIfPresent(CFDictionaryRef theDict, PointerType key, PointerByReference value);
matthiasblaesing marked this conversation as resolved.
Show resolved Hide resolved

/**
* Sets the value corresponding to a given key.
Expand All @@ -447,7 +504,7 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* released. {@code value} must be of the type expected by the retain
* and release callbacks.
*/
void CFDictionarySetValue(CFMutableDictionaryRef theDict, CFTypeRef key, CFTypeRef value);
void CFDictionarySetValue(CFMutableDictionaryRef theDict, PointerType key, PointerType value);
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved

/**
* Copies the character contents of a string to a local C string buffer after
Expand Down Expand Up @@ -503,7 +560,7 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* @return A constant that indicates the data type of the value contained in
* number. See {@link CFNumberType} for a list of possible values.
*/
int CFNumberGetType(CFTypeRef number);
int CFNumberGetType(CFNumberRef number);

/**
* Obtains the value of a {@code CFNumber} object cast to a specified type.
Expand All @@ -515,8 +572,10 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* {@link CFNumberType} for a list of possible values.
* @param On
* return, contains the value of {@code number}.
* @return {@code true} if the operation was successful, otherwise
* {@code false}.
*/
void CFNumberGetValue(CFTypeRef number, int theType, ByReference valuePtr);
boolean CFNumberGetValue(CFNumberRef number, int theType, ByReference valuePtr);

/**
* Returns the number (in terms of UTF-16 code pairs) of Unicode characters in a
Expand All @@ -527,7 +586,7 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* @return The number (in terms of UTF-16 code pairs) of characters stored in
* {@code theString}.
*/
long CFStringGetLength(CFTypeRef theString);
long CFStringGetLength(CFStringRef theString);

/**
* Returns the maximum number of bytes a string of a specified length (in
Expand Down Expand Up @@ -560,7 +619,7 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* The {@code CFData} object to examine.
* @return An index that specifies the number of bytes in {@code theData}.
*/
long CFDataGetLength(CFTypeRef theData);
long CFDataGetLength(CFDataRef theData);

/**
* Returns a read-only pointer to the bytes of a {@code CFData} object.
Expand All @@ -569,5 +628,5 @@ CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef alloc, int capac
* The {@code CFData} object to examine.
* @return A read-only pointer to the bytes associated with {@code theData}.
*/
PointerByReference CFDataGetBytePtr(CFTypeRef theData);
PointerByReference CFDataGetBytePtr(CFDataRef theData);
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
import java.util.Collection;

import com.sun.jna.Memory;
import com.sun.jna.platform.mac.CoreFoundation.CFBooleanRef;
import com.sun.jna.platform.mac.CoreFoundation.CFNumberRef;
import com.sun.jna.platform.mac.CoreFoundation.CFNumberType;
import com.sun.jna.platform.mac.CoreFoundation.CFStringRef;
import com.sun.jna.platform.mac.CoreFoundation.CFTypeRef;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
Expand All @@ -45,62 +48,72 @@ private CoreFoundationUtil() {
}

/**
* Convert a reference to a Core Foundations LongLong into its {@code long}
* Convert a reference to a Core Foundations LongLong into its {@code long}.
* <p>
* This method assumes a 64-bit number is stored and does not do type checking.
* If the argument type differs from the return type, and the conversion is
* lossy or the return value is out of range, then this function passes back an
* approximate value.
*
* @param theLong
* The pointer to a 64-bit integer
* @return The corresponding {@code long}
*/
public static long cfPointerToLong(CFTypeRef theLong) {
public static long cfPointerToLong(CFNumberRef theLong) {
LongByReference lbr = new LongByReference();
CF.CFNumberGetValue(theLong, CFNumberType.kCFNumberLongLongType.ordinal(), lbr);
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved
return lbr.getValue();
}

/**
* Convert a reference to a Core Foundations Int into its {@code int}
* <p>
* This method assumes a 32-bit number is stored and does not do type checking.
* If the argument type differs from the return type, and the conversion is
* lossy or the return value is out of range, then this function passes back an
* approximate value.
*
* @param p
* @param theInt
* The pointer to an integer
* @return The corresponding {@code int}
*/
public static int cfPointerToInt(CFTypeRef p) {
public static int cfPointerToInt(CFNumberRef theInt) {
IntByReference ibr = new IntByReference();
CF.CFNumberGetValue(p, CFNumberType.kCFNumberIntType.ordinal(), ibr);
CF.CFNumberGetValue(theInt, CFNumberType.kCFNumberIntType.ordinal(), ibr);
return ibr.getValue();
}

/**
* Convert a reference to a Core Foundations Boolean into its {@code boolean}
*
* @param cfBoolean
* @param theBoolean
* The pointer to a boolean
* @return The corresponding {@code boolean}
*/
public static boolean cfPointerToBoolean(CFTypeRef cfBoolean) {
return CF.CFBooleanGetValue(cfBoolean);
public static boolean cfPointerToBoolean(CFBooleanRef theBoolean) {
return CF.CFBooleanGetValue(theBoolean);
}

/**
* Convert a reference to a Core Foundations String into its
* {@link java.lang.String}
*
* @param cfTypeRef
* @param theString
* The pointer to a CFString
* @return The corresponding {@link java.lang.String}
*/
public static String cfPointerToString(CFTypeRef cfTypeRef) {
if (cfTypeRef == null) {
public static String cfPointerToString(CFStringRef theString) {
if (theString == null) {
return "null";
}
long length = CF.CFStringGetLength(cfTypeRef);
long length = CF.CFStringGetLength(theString);
long maxSize = CF.CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
if (maxSize == CoreFoundation.kCFNotFound) {
maxSize = 4 * (length + 1);
}
Memory buf = new Memory(maxSize);
CF.CFStringGetCString(cfTypeRef, buf, maxSize, kCFStringEncodingUTF8);
return buf.getString(0);
CF.CFStringGetCString(theString, buf, maxSize, kCFStringEncodingUTF8);
return buf.getString(0, "UTF8");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.mac.CoreFoundation.CFAllocatorRef;
import com.sun.jna.platform.mac.CoreFoundation.CFArrayRef;
import com.sun.jna.platform.mac.CoreFoundation.CFDataRef;
Expand All @@ -57,18 +58,18 @@ public class CoreFoundationTest {

@Test
public void testCFStringRef() {
String awesome = "JNA is awesome";
String awesome = "ǝɯosǝʍɐ sı ∀Nſ"; // Unicode
CFStringRef cfAwesome = CFStringRef.toCFString(awesome);
assertEquals(awesome.length(), CF.CFStringGetLength(cfAwesome));
assertEquals(awesome, CoreFoundationUtil.cfPointerToString(cfAwesome));

Memory mem = new Memory(awesome.length() + 1);
Memory mem = new Memory(awesome.getBytes().length + 1);
matthiasblaesing marked this conversation as resolved.
Show resolved Hide resolved
mem.clear();
assertTrue(CF.CFStringGetCString(cfAwesome, mem, mem.size(), CoreFoundation.kCFStringEncodingUTF8));
byte[] awesomeBytes = mem.getByteArray(0, (int) mem.size() - 1);
char[] awesomeArr = awesome.toCharArray();
byte[] awesomeArr = awesome.getBytes();
for (int i = 0; i < awesomeArr.length; i++) {
assertEquals((byte) awesomeArr[i], awesomeBytes[i]);
assertEquals(awesomeArr[i], awesomeBytes[i]);
}
matthiasblaesing marked this conversation as resolved.
Show resolved Hide resolved
// Essentially a toString, can't rely on format but should contain the string
CFStringRef desc = CF.CFCopyDescription(cfAwesome);
Expand All @@ -89,10 +90,10 @@ public void testCFNumberRef() {
IntByReference one = new IntByReference(1);
CFNumberRef cfZero = CF.CFNumberCreate(null, CFNumberType.kCFNumberIntType.ordinal(), zero);
CFNumberRef cfOne = CF.CFNumberCreate(null, CFNumberType.kCFNumberIntType.ordinal(), one);

assertEquals(0, CoreFoundationUtil.cfPointerToInt(cfZero));
assertEquals(1, CoreFoundationUtil.cfPointerToInt(cfOne));
assertEquals(false, CoreFoundationUtil.cfPointerToBoolean(cfZero));
assertEquals(true, CoreFoundationUtil.cfPointerToBoolean(cfOne));

release(cfZero);
release(cfOne);
}
Expand Down Expand Up @@ -138,7 +139,8 @@ public void testCFArray() {

assertEquals(refArray.length, CF.CFArrayGetCount(cfPtrArray));
for (int i = 0; i < refArray.length; i++) {
CFTypeRef numRef = CF.CFArrayGetValueAtIndex(cfPtrArray, i);
CFTypeRef result = CF.CFArrayGetValueAtIndex(cfPtrArray, i);
CFNumberRef numRef = new CFNumberRef(result.getPointer());
assertEquals(i, CoreFoundationUtil.cfPointerToInt(numRef));
}

Expand Down Expand Up @@ -168,28 +170,42 @@ public void testCFData() {
public void testCFDictionary() {
CFAllocatorRef alloc = CF.CFAllocatorGetDefault();
CFMutableDictionaryRef dict = CF.CFDictionaryCreateMutable(alloc, 2, null, null);
CFStringRef oneKey = CFStringRef.toCFString("one");
CFStringRef oneStr = CFStringRef.toCFString("one");

// Key does not exist, returns null
assertFalse(CF.CFDictionaryGetValueIfPresent(dict, oneKey, null));
CFTypeRef cfNull = CF.CFDictionaryGetValue(dict, oneKey);
assertFalse(CF.CFDictionaryGetValueIfPresent(dict, oneStr, null));
Pointer cfNull = CF.CFDictionaryGetValue(dict, oneStr);
assertNull(cfNull);

// Store and retrieve null value
CF.CFDictionarySetValue(dict, oneKey, null);
assertTrue(CF.CFDictionaryGetValueIfPresent(dict, oneKey, null));
CFTypeRef cfNullValue = CF.CFDictionaryGetValue(dict, oneKey);
CF.CFDictionarySetValue(dict, oneStr, null);
assertTrue(CF.CFDictionaryGetValueIfPresent(dict, oneStr, null));
Pointer cfNullValue = CF.CFDictionaryGetValue(dict, oneStr);
assertNull(cfNullValue);

// Store (replace the null) and retrieve integer value
IntByReference one = new IntByReference(1);
CFNumberRef cfOne = CF.CFNumberCreate(null, CFNumberType.kCFNumberIntType.ordinal(), one);
CF.CFDictionarySetValue(dict, oneKey, cfOne);
assertTrue(CF.CFDictionaryGetValueIfPresent(dict, oneKey, null));
CFTypeRef cfValue = CF.CFDictionaryGetValue(dict, oneKey);
assertEquals(1, CoreFoundationUtil.cfPointerToInt(cfValue));

release(oneKey);
CF.CFDictionarySetValue(dict, oneStr, cfOne);

assertTrue(CF.CFDictionaryGetValueIfPresent(dict, oneStr, null));
Pointer result = CF.CFDictionaryGetValue(dict, oneStr);
CFNumberRef numRef = new CFNumberRef(result);
assertEquals(1, CoreFoundationUtil.cfPointerToInt(numRef));

PointerByReference resultPtr = new PointerByReference();
assertTrue(CF.CFDictionaryGetValueIfPresent(dict, oneStr, resultPtr));
numRef = new CFNumberRef(resultPtr.getValue());
assertEquals(1, CoreFoundationUtil.cfPointerToInt(numRef));

// Test non-CF type as key
IntByReference onePtr = new IntByReference(1);
CF.CFDictionarySetValue(dict, onePtr, oneStr);
result = CF.CFDictionaryGetValue(dict, onePtr);
CFStringRef strRef = new CFStringRef(result);
assertEquals("one", CoreFoundationUtil.cfPointerToString(strRef));

release(oneStr);
release(cfOne);
release(dict);
}
Expand Down
Loading