diff --git a/src/main/java/jnr/ffi/Struct.java b/src/main/java/jnr/ffi/Struct.java index f235472cb..9bc60a563 100755 --- a/src/main/java/jnr/ffi/Struct.java +++ b/src/main/java/jnr/ffi/Struct.java @@ -2183,7 +2183,8 @@ public void set(java.lang.Number value) { */ @Override public final int intValue() { - return getMemory().getByte(offset()); + short value = getMemory().getByte(offset()); + return value < 0 ? (short) ((value & 0x7F) + 0x80) : value; } } @@ -2202,7 +2203,8 @@ public void set(java.lang.Number value) { } @Override public final int intValue() { - return getMemory().getShort(offset()); + int value = getMemory().getShort(offset()); + return value < 0 ? (value & 0x7FFF) + 0x8000 : value; } } @@ -2211,7 +2213,7 @@ public Enum32(Class enumClass) { super(NativeType.SINT, enumClass); } public final E get() { - return enumClass.cast(EnumMapper.getInstance(enumClass).valueOf(intValue())); + return enumClass.cast(EnumMapper.getInstance(enumClass).valueOf(longValue())); } public final void set(E value) { getMemory().putInt(offset(), EnumMapper.getInstance(enumClass).intValue(value)); @@ -2221,7 +2223,13 @@ public void set(java.lang.Number value) { } @Override public final int intValue() { - return getMemory().getInt(offset()); + return (int) longValue(); + } + + @Override + public long longValue() { + long value = getMemory().getInt(offset()); + return value < 0 ? (long)((value & 0x7FFFFFFFL) + 0x80000000L) : value; } } @@ -2230,10 +2238,10 @@ public Enum64(Class enumClass) { super(NativeType.SLONGLONG, enumClass); } public final E get() { - return enumClass.cast(EnumMapper.getInstance(enumClass).valueOf(intValue())); + return enumClass.cast(EnumMapper.getInstance(enumClass).valueOf(longValue())); } public final void set(E value) { - getMemory().putLongLong(offset(), EnumMapper.getInstance(enumClass).intValue(value)); + getMemory().putLongLong(offset(), EnumMapper.getInstance(enumClass).longValue(value)); } public void set(java.lang.Number value) { getMemory().putLongLong(offset(), value.longValue()); @@ -2254,10 +2262,10 @@ public EnumLong(Class enumClass) { } public final E get() { - return enumClass.cast(EnumMapper.getInstance(enumClass).valueOf(intValue())); + return enumClass.cast(EnumMapper.getInstance(enumClass).valueOf(longValue())); } public final void set(E value) { - getMemory().putNativeLong(offset(), EnumMapper.getInstance(enumClass).intValue(value)); + set(EnumMapper.getInstance(enumClass).longValue(value)); } public void set(java.lang.Number value) { getMemory().putNativeLong(offset(), value.longValue()); diff --git a/src/test/java/jnr/ffi/struct/EnumTest.java b/src/test/java/jnr/ffi/struct/EnumTest.java index a361bd96d..ef0b182e6 100644 --- a/src/test/java/jnr/ffi/struct/EnumTest.java +++ b/src/test/java/jnr/ffi/struct/EnumTest.java @@ -41,6 +41,61 @@ public enum TestEnum { B, MAGIC } + + public enum ByteNegativeEnum + implements EnumMapper.IntegerEnum { + NEGATIVE(0xF0); + + final int value; + + ByteNegativeEnum(int value) {this.value = value;} + + @Override + public int intValue() { + return value; + } + } + + public enum ShortNegativeEnum + implements EnumMapper.IntegerEnum { + NEGATIVE(0xF000); + + final int value; + + ShortNegativeEnum(int value) {this.value = value;} + + @Override + public int intValue() { + return value; + } + } + + public enum IntNegativeEnum { + NEGATIVE(0xF00000L); + + final long value; + + IntNegativeEnum(long value) {this.value = value;} + + public long longValue() { + return value; + } + } + + public enum LongEnum { + BIGGER_THAN_INT(0xFF00000000000000L); + + private final long value; + + LongEnum(long value) { + this.value = value; + } + + public long longValue() { + return value; + } + } + public class struct1 extends Struct { public final Enum8 b = new Enum8(TestEnum.class); public final Enum16 s = new Enum16(TestEnum.class); @@ -130,6 +185,36 @@ public LongAlign() { } } + public static class Enum8FieldStruct extends Struct { + public final Enum8 value = new Enum8(ByteNegativeEnum.class); + public Enum8FieldStruct() { + super(runtime); + } + } + public static class Enum16FieldStruct extends Struct { + public final Enum16 value = new Enum16(ShortNegativeEnum.class); + public Enum16FieldStruct() { + super(runtime); + } + } + public static class Enum32FieldStruct extends Struct { + public final Enum32 value = new Enum32(IntNegativeEnum.class); + public Enum32FieldStruct() { + super(runtime); + } + } + public static class Enum64FieldStruct extends Struct { + public final Enum64 value = new Enum64(LongEnum.class); + public Enum64FieldStruct() { + super(runtime); + } + } + public static class EnumLongFieldStruct extends Struct { + public final EnumLong value = new EnumLong(LongEnum.class); + public EnumLongFieldStruct() { + super(runtime); + } + } @Test public void testInt8InitialValue() { struct1 s = new struct1(); assertEquals("default value not zero", TestEnum.ZERO, s.b.get()); @@ -212,4 +297,43 @@ public void alignSignedLongField() { assertEquals("native long field not aligned", MAGIC, testlib.struct_align_SignedLong(s)); } + + @Test + public void byteEnumFieldWithNegativeValue() + { + Enum8FieldStruct struct = new Enum8FieldStruct(); + struct.value.set(ByteNegativeEnum.NEGATIVE); + assertEquals("negative Enum8 value conversation failed", ByteNegativeEnum.NEGATIVE, struct.value.get()); + } + + @Test + public void shortEnumFieldWithNegativeValue() + { + Enum16FieldStruct struct = new Enum16FieldStruct(); + struct.value.set(ShortNegativeEnum.NEGATIVE); + assertEquals("negative Enum16 value conversation failed", ShortNegativeEnum.NEGATIVE, struct.value.get()); + } + + @Test + public void intEnumFieldWithNegativeValue() + { + Enum32FieldStruct struct = new Enum32FieldStruct(); + struct.value.set(IntNegativeEnum.NEGATIVE); + assertEquals("negative Enum32 value conversation failed", IntNegativeEnum.NEGATIVE, struct.value.get()); + } + + @Test + public void longLongEnumField(){ + Enum64FieldStruct struct = new Enum64FieldStruct(); + struct.value.set(LongEnum.BIGGER_THAN_INT); + assertEquals("long Enum64 value conversation failed", LongEnum.BIGGER_THAN_INT, struct.value.get()); + } + @Test + public void longEnumFieldX64(){ + if (runtime.longSize() == 8) { + EnumLongFieldStruct struct = new EnumLongFieldStruct(); + struct.value.set(LongEnum.BIGGER_THAN_INT); + assertEquals("long EnumLong value conversation failed", LongEnum.BIGGER_THAN_INT, struct.value.get()); + } + } }