diff --git a/pom.xml b/pom.xml index 28a9d7010..209289028 100644 --- a/pom.xml +++ b/pom.xml @@ -61,13 +61,13 @@ com.github.jnr jffi - 1.2.17 + 1.2.18 compile com.github.jnr jffi - 1.2.16 + 1.2.18 runtime native @@ -169,7 +169,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.4.2 + 3.0.0-M2 diff --git a/src/main/java/jnr/ffi/Struct.java b/src/main/java/jnr/ffi/Struct.java index 38f0d3354..04cfe9ae0 100755 --- a/src/main/java/jnr/ffi/Struct.java +++ b/src/main/java/jnr/ffi/Struct.java @@ -783,7 +783,7 @@ public Boolean() { } public final boolean get() { - return (getMemory().getByte(offset()) & 0x1) != 0; + return getMemory().getByte(offset()) != 0; } public final void set(boolean value) { @@ -800,7 +800,7 @@ public WBOOL() { } public final boolean get() { - return (getMemory().getInt(offset()) & 0x1) != 0; + return getMemory().getInt(offset()) != 0; } public final void set(boolean value) { @@ -814,7 +814,7 @@ public BOOL16() { } public final boolean get() { - return (getMemory().getShort(offset()) & 0x1) != 0; + return getMemory().getShort(offset()) != 0; } public final void set(boolean value) { diff --git a/src/main/java/jnr/ffi/StructLayout.java b/src/main/java/jnr/ffi/StructLayout.java index a1b32cf0b..1dbe5329e 100644 --- a/src/main/java/jnr/ffi/StructLayout.java +++ b/src/main/java/jnr/ffi/StructLayout.java @@ -312,7 +312,7 @@ protected Boolean(Offset offset) { } public final boolean get(jnr.ffi.Pointer ptr) { - return (ptr.getByte(offset()) & 0x1) != 0; + return ptr.getByte(offset()) != 0; } public final void set(jnr.ffi.Pointer ptr, boolean value) { @@ -333,7 +333,7 @@ protected WBOOL(Offset offset) { } public final boolean get(jnr.ffi.Pointer ptr) { - return (ptr.getInt(offset()) & 0x1) != 0; + return ptr.getInt(offset()) != 0; } public final void set(jnr.ffi.Pointer ptr, boolean value) { @@ -341,6 +341,25 @@ public final void set(jnr.ffi.Pointer ptr, boolean value) { } } + public final class BOOL16 extends AbstractBoolean { + protected BOOL16() { + super(NativeType.SSHORT); + } + + protected BOOL16(Offset offset) { + super(NativeType.SSHORT, offset); + } + + public final boolean get(jnr.ffi.Pointer ptr) { + return ptr.getShort(offset()) != 0; + } + + public final void set(jnr.ffi.Pointer ptr, boolean value) { + ptr.putShort(offset(), (short) (value ? 1 : 0)); + } + } + + /** * Base class for all Number structure fields. */ diff --git a/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java b/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java index 3ca02c51c..d300192ce 100644 --- a/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java +++ b/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java @@ -20,6 +20,7 @@ import jnr.ffi.NativeType; import jnr.ffi.provider.SigType; +import org.objectweb.asm.Label; public final class NumberUtil { private NumberUtil() {} @@ -143,7 +144,7 @@ public static void widen(SkinnyMethodAdapter mv, Class from, Class to, NativeTyp public static void narrow(SkinnyMethodAdapter mv, Class from, Class to) { if (!from.equals(to)) { - if (byte.class == to || short.class == to || char.class == to || int.class == to || boolean.class == to) { + if (byte.class == to || short.class == to || char.class == to || int.class == to) { if (long.class == from) { mv.l2i(); } @@ -156,13 +157,29 @@ public static void narrow(SkinnyMethodAdapter mv, Class from, Class to) { } else if (char.class == to) { mv.i2c(); - - } else if (boolean.class == to) { - // Ensure only 0x0 and 0x1 values are used for boolean + } + } else if (boolean.class == to) { + Label label_false_branch = new Label(); + Label label_end = new Label(); + if (long.class == from) { + mv.lconst_0(); + mv.lcmp(); + mv.ifeq(label_false_branch); mv.iconst_1(); - mv.iand(); + mv.go_to(label_end); + mv.label(label_false_branch); + mv.iconst_0(); + mv.label(label_end); + } else { +// mv.iconst_0(); + mv.ifeq(label_false_branch); + mv.iconst_1(); + mv.go_to(label_end); + mv.label(label_false_branch); + mv.iconst_0(); + mv.label(label_end); } - } + } } } diff --git a/src/main/java/jnr/ffi/provider/jffi/X86MethodGenerator.java b/src/main/java/jnr/ffi/provider/jffi/X86MethodGenerator.java index d75416730..429eb9996 100644 --- a/src/main/java/jnr/ffi/provider/jffi/X86MethodGenerator.java +++ b/src/main/java/jnr/ffi/provider/jffi/X86MethodGenerator.java @@ -106,8 +106,8 @@ public void generate(AsmBuilder builder, String functionName, Function function, } Class nativeReturnType; - wrapperNeeded |= resultType.getFromNativeConverter() != null || !resultType.effectiveJavaType().isPrimitive(); - if (resultType.effectiveJavaType().isPrimitive()) { + wrapperNeeded |= resultType.getFromNativeConverter() != null || !resultType.effectiveJavaType().isPrimitive() || boolean.class.equals(resultType.effectiveJavaType()); + if (resultType.effectiveJavaType().isPrimitive() && !boolean.class.equals(resultType.effectiveJavaType())) { nativeReturnType = resultType.effectiveJavaType(); } else { nativeReturnType = getNativeClass(resultType.getNativeType()); diff --git a/src/test/java/jnr/ffi/NumberTest.java b/src/test/java/jnr/ffi/NumberTest.java index 10f1c506f..2b217bf87 100644 --- a/src/test/java/jnr/ffi/NumberTest.java +++ b/src/test/java/jnr/ffi/NumberTest.java @@ -67,16 +67,38 @@ public static interface TestLib { } static TestLib testlib; - public static interface TestBoolean { + + public static interface Test_Boolean { + + public Boolean ret_int8_t(byte l); + public Boolean ret_uint8_t(byte l); + public Boolean ret_int16_t(short l); + public Boolean ret_uint16_t(short l); + public Boolean ret_int32_t(int l); + public Boolean ret_uint32_t(int l); + public Boolean ret_int64_t(long l); + public Boolean ret_uint64_t(long l); + } + static Test_Boolean test_Boolean; + public static interface Test_boolean { + + public boolean ret_int8_t(byte l); + public boolean ret_uint8_t(byte l); + public boolean ret_int16_t(short l); + public boolean ret_uint16_t(short l); public boolean ret_int32_t(int l); + public boolean ret_uint32_t(int l); + public boolean ret_int64_t(long l); + public boolean ret_uint64_t(long l); } - static TestBoolean testboolean; + static Test_boolean test_boolean; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); - testboolean = TstUtil.loadTestLib(TestBoolean.class); + test_boolean = TstUtil.loadTestLib(Test_boolean.class); + test_Boolean = TstUtil.loadTestLib(Test_Boolean.class); } @AfterClass @@ -352,9 +374,67 @@ public long n(long i1, long i2) { } @Test public void testBooleanFromInt() throws Exception { - assertEquals(false, testboolean.ret_int32_t(0)); - assertEquals(true, testboolean.ret_int32_t(-1)); - assertEquals(true, testboolean.ret_int32_t(1)); - assertEquals(true, testboolean.ret_int32_t(2)); + assertEquals(false, test_boolean.ret_int32_t(0)); + assertEquals(true, test_boolean.ret_int32_t(-1)); + assertEquals(true, test_boolean.ret_int32_t(1)); + assertEquals(true, test_boolean.ret_int32_t(2)); + + int value = 0x00000001; + for (int i = 0; i < 32; i++) { + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_boolean.ret_int32_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_boolean.ret_uint32_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_Boolean.ret_int32_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_Boolean.ret_uint32_t(value)); + value <<= 1; + } } + + @Test public void testBooleanFromByte() throws Exception { + assertEquals(false, test_boolean.ret_int32_t(0)); + assertEquals(true, test_boolean.ret_int32_t(-1)); + assertEquals(true, test_boolean.ret_int32_t(1)); + assertEquals(true, test_boolean.ret_int32_t(2)); + + byte value = 0x01; + for (int i = 0; i < 8; i++) { + assertTrue(String.format("Must evaluate to true: 0x%02x", value), test_boolean.ret_int8_t((byte)value)); + assertTrue(String.format("Must evaluate to true: 0x%02x", value), test_boolean.ret_uint8_t((byte)value)); + assertTrue(String.format("Must evaluate to true: 0x%02x", value), test_Boolean.ret_int8_t((byte)value)); + assertTrue(String.format("Must evaluate to true: 0x%02x", value), test_Boolean.ret_uint8_t((byte)value)); + value <<= 1; + } + } + + @Test public void testBooleanFromShort() throws Exception { + assertEquals(false, test_boolean.ret_int32_t(0)); + assertEquals(true, test_boolean.ret_int32_t(-1)); + assertEquals(true, test_boolean.ret_int32_t(1)); + assertEquals(true, test_boolean.ret_int32_t(2)); + + short value = 0x0001; + for (int i = 0; i < 16; i++) { + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_boolean.ret_int16_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_boolean.ret_uint16_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_Boolean.ret_int16_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%04x", value), test_Boolean.ret_uint16_t(value)); + value <<= 1; + } + } + + @Test public void testBooleanFromLong() throws Exception { + assertEquals(false, test_boolean.ret_int64_t(0)); + assertEquals(true, test_boolean.ret_int64_t(-1)); + assertEquals(true, test_boolean.ret_int64_t(1)); + assertEquals(true, test_boolean.ret_int64_t(2)); + + long value = 0x0000000000000001; + for (int i = 0; i < 32; i++) { + assertTrue(String.format("Must evaluate to true: 0x%016x", value), test_boolean.ret_int64_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%016x", value), test_boolean.ret_uint64_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%016x", value), test_Boolean.ret_int64_t(value)); + assertTrue(String.format("Must evaluate to true: 0x%016x", value), test_Boolean.ret_uint64_t(value)); + value <<= 1; + } + } + }