Skip to content
24 changes: 16 additions & 8 deletions src/main/java/jnr/ffi/Struct.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand All @@ -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;
}
}

Expand All @@ -2211,7 +2213,7 @@ public Enum32(Class<E> 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));
Expand All @@ -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;
}
}

Expand All @@ -2230,10 +2238,10 @@ public Enum64(Class<E> 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());
Expand All @@ -2254,10 +2262,10 @@ public EnumLong(Class<E> 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());
Expand Down
124 changes: 124 additions & 0 deletions src/test/java/jnr/ffi/struct/EnumTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<TestEnum> b = new Enum8<TestEnum>(TestEnum.class);
public final Enum16<TestEnum> s = new Enum16<TestEnum>(TestEnum.class);
Expand Down Expand Up @@ -130,6 +185,36 @@ public LongAlign() {
}

}
public static class Enum8FieldStruct extends Struct {
public final Enum8<ByteNegativeEnum> value = new Enum8<ByteNegativeEnum>(ByteNegativeEnum.class);
public Enum8FieldStruct() {
super(runtime);
}
}
public static class Enum16FieldStruct extends Struct {
public final Enum16<ShortNegativeEnum> value = new Enum16<ShortNegativeEnum>(ShortNegativeEnum.class);
public Enum16FieldStruct() {
super(runtime);
}
}
public static class Enum32FieldStruct extends Struct {
public final Enum32<IntNegativeEnum> value = new Enum32<IntNegativeEnum>(IntNegativeEnum.class);
public Enum32FieldStruct() {
super(runtime);
}
}
public static class Enum64FieldStruct extends Struct {
public final Enum64<LongEnum> value = new Enum64<LongEnum>(LongEnum.class);
public Enum64FieldStruct() {
super(runtime);
}
}
public static class EnumLongFieldStruct extends Struct {
public final EnumLong<LongEnum> value = new EnumLong<LongEnum>(LongEnum.class);
public EnumLongFieldStruct() {
super(runtime);
}
}
@Test public void testInt8InitialValue() {
struct1 s = new struct1();
assertEquals("default value not zero", TestEnum.ZERO, s.b.get());
Expand Down Expand Up @@ -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());
}
}
}