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

Fix number to boolean conversion #138

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
Expand Up @@ -506,6 +506,9 @@ public final Object invoke(Runtime runtime, Function function, HeapInvocationBuf
static class BooleanInvoker extends BaseInvoker {
static FunctionInvoker INSTANCE = new BooleanInvoker();
public final Object invoke(Runtime runtime, Function function, HeapInvocationBuffer buffer) {
if (function.getReturnType().size() == 8) {
return invoker.invokeLong(function, buffer) != 0;
}
return invoker.invokeInt(function, buffer) != 0;
}
}
Expand Down
44 changes: 31 additions & 13 deletions src/main/java/jnr/ffi/provider/jffi/NumberUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import jnr.ffi.NativeType;
import jnr.ffi.provider.SigType;
import org.objectweb.asm.Label;

public final class NumberUtil {
private NumberUtil() {}
Expand Down Expand Up @@ -144,23 +145,40 @@ 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 (long.class == from) {
mv.l2i();
}
if (boolean.class == to) {
if (long.class == from) {
mv.lconst_0();
mv.lcmp();

} else {
/* Equivalent to
return result == 0 ? true : false;
*/
Label zero = new Label();
Label ret = new Label();
mv.iconst_0();
mv.if_icmpeq(zero);
mv.iconst_1();
mv.go_to(ret);
mv.label(zero);
mv.iconst_0();
mv.label(ret);
}
} else {
if (long.class == from) {
mv.l2i();
}

if (byte.class == to) {
mv.i2b();
if (byte.class == to) {
mv.i2b();

} else if (short.class == to) {
mv.i2s();
} else if (short.class == to) {
mv.i2s();

} else if (char.class == to) {
mv.i2c();
} else if (char.class == to) {
mv.i2c();

} else if (boolean.class == to) {
// Ensure only 0x0 and 0x1 values are used for boolean
mv.iconst_1();
mv.iand();
}
}
}
}
Expand Down
28 changes: 20 additions & 8 deletions src/test/java/jnr/ffi/NumberTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,25 @@

package jnr.ffi;

import jnr.ffi.annotations.LongLong;
import jnr.ffi.types.int32_t;
import jnr.ffi.types.pid_t;
import jnr.ffi.types.u_int32_t;
import org.junit.*;

import java.util.Random;

import jnr.ffi.annotations.LongLong;
import jnr.ffi.types.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

/**
*
* @author wayne
*/
public class NumberTest {

public static final long LONG_WITH_ONLY_THIRD_WORD_NOT_ZERO = 0xFF00000000L;

public NumberTest() {
}

Expand Down Expand Up @@ -70,6 +72,7 @@ public static interface TestLib {
public static interface TestBoolean {

public boolean ret_int32_t(int l);
public @LongLong boolean ret_int64_t(@LongLong long l);
}
static TestBoolean testboolean;

Expand Down Expand Up @@ -357,4 +360,13 @@ public long n(long i1, long i2) {
assertEquals(true, testboolean.ret_int32_t(1));
assertEquals(true, testboolean.ret_int32_t(2));
}

@Test public void testBooleanFromLong() throws Exception {
assertEquals(false, testboolean.ret_int64_t(0));
assertEquals(true, testboolean.ret_int64_t(-1));
assertEquals(true, testboolean.ret_int64_t(-5));
assertEquals(true, testboolean.ret_int64_t(1));
assertEquals(true, testboolean.ret_int64_t(2));
assertEquals(true, testboolean.ret_int64_t(LONG_WITH_ONLY_THIRD_WORD_NOT_ZERO));
}
}