diff --git a/src/main/java/jnr/ffi/annotations/Direct.java b/src/main/java/jnr/ffi/annotations/Direct.java
index 9d2ea8c27..5740546ec 100644
--- a/src/main/java/jnr/ffi/annotations/Direct.java
+++ b/src/main/java/jnr/ffi/annotations/Direct.java
@@ -19,13 +19,15 @@
package jnr.ffi.annotations;
+import jnr.ffi.struct.Struct;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Indicates that a {@link jnr.ffi.Struct}} parameter should be
+ * Indicates that a {@link Struct}} parameter should be
* backed by a persistent native memory block.
*
*
Without the {@code @Direct} annotation, the native code will allocate a
@@ -33,7 +35,7 @@
* the call.
*
*
By using {@code @Direct}, the native memory block is permanently associated
- * with the {@link jnr.ffi.Struct} instance, and will remain allocated
+ * with the {@link Struct} instance, and will remain allocated
* for as long as the {@code Struct} instance remains strongly referenced by java code.
*
*/
diff --git a/src/main/java/jnr/ffi/annotations/In.java b/src/main/java/jnr/ffi/annotations/In.java
index bc6f5c4d7..1a533f70d 100644
--- a/src/main/java/jnr/ffi/annotations/In.java
+++ b/src/main/java/jnr/ffi/annotations/In.java
@@ -18,6 +18,8 @@
package jnr.ffi.annotations;
+import jnr.ffi.struct.Struct;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -27,7 +29,7 @@
* Indicates that the parameter is an IN parameter.
*
*
When a java object is passed to a native function as a pointer
- * (for example {@link jnr.ffi.Pointer}, {@link jnr.ffi.Struct}, {@link java.nio.ByteBuffer}),
+ * (for example {@link jnr.ffi.Pointer}, {@link Struct}, {@link java.nio.ByteBuffer}),
* then a temporary native memory block is allocated, the java data is copied to
* the temporary memory and the address of the temporary memory is passed to the function.
* After the function returns, the java data is automatically updated from the
diff --git a/src/main/java/jnr/ffi/annotations/Out.java b/src/main/java/jnr/ffi/annotations/Out.java
index cb843fca7..085777c2c 100644
--- a/src/main/java/jnr/ffi/annotations/Out.java
+++ b/src/main/java/jnr/ffi/annotations/Out.java
@@ -18,6 +18,8 @@
package jnr.ffi.annotations;
+import jnr.ffi.struct.Struct;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -27,7 +29,7 @@
* Indicates that the parameter is an OUT parameter.
*
*
When a java object is passed to a native function as a pointer
- * (for example {@link jnr.ffi.Pointer}, {@link jnr.ffi.Struct}, {@link java.nio.ByteBuffer}),
+ * (for example {@link jnr.ffi.Pointer}, {@link Struct}, {@link java.nio.ByteBuffer}),
* then a temporary native memory block is allocated, the java data is copied to
* the temporary memory and the address of the temporary memory is passed to the function.
* After the function returns, the java data is automatically updated from the
diff --git a/src/main/java/jnr/ffi/provider/converters/StructArrayParameterConverter.java b/src/main/java/jnr/ffi/provider/converters/StructArrayParameterConverter.java
index d95cbd7ce..9f82568c5 100644
--- a/src/main/java/jnr/ffi/provider/converters/StructArrayParameterConverter.java
+++ b/src/main/java/jnr/ffi/provider/converters/StructArrayParameterConverter.java
@@ -19,8 +19,7 @@
package jnr.ffi.provider.converters;
import jnr.ffi.Pointer;
-import jnr.ffi.Struct;
-import jnr.ffi.annotations.LongLong;
+import jnr.ffi.struct.Struct;
import jnr.ffi.mapper.ToNativeContext;
import jnr.ffi.mapper.ToNativeConverter;
import jnr.ffi.provider.DelegatingMemoryIO;
diff --git a/src/main/java/jnr/ffi/provider/converters/StructByReferenceFromNativeConverter.java b/src/main/java/jnr/ffi/provider/converters/StructByReferenceFromNativeConverter.java
index 59b5d487a..16b3acdd1 100644
--- a/src/main/java/jnr/ffi/provider/converters/StructByReferenceFromNativeConverter.java
+++ b/src/main/java/jnr/ffi/provider/converters/StructByReferenceFromNativeConverter.java
@@ -19,7 +19,7 @@
package jnr.ffi.provider.converters;
import jnr.ffi.Pointer;
-import jnr.ffi.Struct;
+import jnr.ffi.struct.Struct;
import jnr.ffi.mapper.FromNativeContext;
import jnr.ffi.mapper.FromNativeConverter;
@@ -28,7 +28,7 @@
/**
- * Converts a native pointer result into a {@link jnr.ffi.Struct}
+ * Converts a native pointer result into a {@link Struct}
*/
public class StructByReferenceFromNativeConverter implements FromNativeConverter {
private final Constructor extends Struct> constructor;
diff --git a/src/main/java/jnr/ffi/provider/converters/StructByReferenceToNativeConverter.java b/src/main/java/jnr/ffi/provider/converters/StructByReferenceToNativeConverter.java
index 7d7baa992..c06dfbc3e 100644
--- a/src/main/java/jnr/ffi/provider/converters/StructByReferenceToNativeConverter.java
+++ b/src/main/java/jnr/ffi/provider/converters/StructByReferenceToNativeConverter.java
@@ -19,7 +19,7 @@
package jnr.ffi.provider.converters;
import jnr.ffi.Pointer;
-import jnr.ffi.Struct;
+import jnr.ffi.struct.Struct;
import jnr.ffi.mapper.ToNativeContext;
import jnr.ffi.mapper.ToNativeConverter;
import jnr.ffi.provider.ParameterFlags;
diff --git a/src/main/java/jnr/ffi/provider/jffi/AsmStructByReferenceFromNativeConverter.java b/src/main/java/jnr/ffi/provider/jffi/AsmStructByReferenceFromNativeConverter.java
index 6970a5cf8..d5a2ed284 100644
--- a/src/main/java/jnr/ffi/provider/jffi/AsmStructByReferenceFromNativeConverter.java
+++ b/src/main/java/jnr/ffi/provider/jffi/AsmStructByReferenceFromNativeConverter.java
@@ -20,7 +20,7 @@
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;
-import jnr.ffi.Struct;
+import jnr.ffi.struct.Struct;
import jnr.ffi.mapper.FromNativeContext;
import jnr.ffi.mapper.FromNativeConverter;
import org.objectweb.asm.ClassReader;
diff --git a/src/main/java/jnr/ffi/provider/jffi/ClosureTypeMapper.java b/src/main/java/jnr/ffi/provider/jffi/ClosureTypeMapper.java
index b647df006..891953312 100644
--- a/src/main/java/jnr/ffi/provider/jffi/ClosureTypeMapper.java
+++ b/src/main/java/jnr/ffi/provider/jffi/ClosureTypeMapper.java
@@ -18,12 +18,11 @@
package jnr.ffi.provider.jffi;
-import jnr.ffi.Struct;
+import jnr.ffi.struct.Struct;
import jnr.ffi.mapper.*;
import jnr.ffi.mapper.FromNativeType;
import jnr.ffi.mapper.ToNativeType;
import jnr.ffi.provider.converters.EnumConverter;
-import jnr.ffi.provider.ParameterFlags;
import jnr.ffi.provider.converters.StringResultConverter;
import jnr.ffi.provider.converters.StructByReferenceToNativeConverter;
diff --git a/src/main/java/jnr/ffi/provider/jffi/InvokerTypeMapper.java b/src/main/java/jnr/ffi/provider/jffi/InvokerTypeMapper.java
index 42c8cda0c..5cc5cbfb8 100644
--- a/src/main/java/jnr/ffi/provider/jffi/InvokerTypeMapper.java
+++ b/src/main/java/jnr/ffi/provider/jffi/InvokerTypeMapper.java
@@ -20,7 +20,7 @@
import jnr.ffi.NativeLong;
import jnr.ffi.Pointer;
-import jnr.ffi.Struct;
+import jnr.ffi.struct.Struct;
import jnr.ffi.annotations.Delegate;
import jnr.ffi.byref.ByReference;
import jnr.ffi.mapper.*;
diff --git a/src/main/java/jnr/ffi/provider/jffi/StructByReferenceResultConverterFactory.java b/src/main/java/jnr/ffi/provider/jffi/StructByReferenceResultConverterFactory.java
index aef263e14..9ddf4f2d9 100644
--- a/src/main/java/jnr/ffi/provider/jffi/StructByReferenceResultConverterFactory.java
+++ b/src/main/java/jnr/ffi/provider/jffi/StructByReferenceResultConverterFactory.java
@@ -22,6 +22,7 @@
import jnr.ffi.mapper.FromNativeContext;
import jnr.ffi.mapper.FromNativeConverter;
import jnr.ffi.provider.converters.StructByReferenceFromNativeConverter;
+import jnr.ffi.struct.Struct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/src/main/java/jnr/ffi/struct/AsciiString.java b/src/main/java/jnr/ffi/struct/AsciiString.java
new file mode 100644
index 000000000..23aa3e41d
--- /dev/null
+++ b/src/main/java/jnr/ffi/struct/AsciiString.java
@@ -0,0 +1,10 @@
+package jnr.ffi.struct;
+
+public class AsciiString extends UTFString {
+ private Struct struct;
+
+ public AsciiString(Struct struct, int size) {
+ super(struct, size, Struct.ASCII);
+ this.struct = struct;
+ }
+}
diff --git a/src/main/java/jnr/ffi/struct/Field.java b/src/main/java/jnr/ffi/struct/Field.java
new file mode 100644
index 000000000..51f7de36a
--- /dev/null
+++ b/src/main/java/jnr/ffi/struct/Field.java
@@ -0,0 +1,68 @@
+package jnr.ffi.struct;
+
+import jnr.ffi.NativeType;
+import jnr.ffi.Runtime;
+import jnr.ffi.Type;
+import jnr.ffi.TypeAlias;
+
+/**
+ * Structure field
+ */
+public abstract class Field {
+
+ private Struct.Info info;
+ private Offset offset;
+
+ protected Field(Struct struct, int size, int align, Offset offset) {
+ registerInStructure(struct, size, align, offset);
+ }
+
+ protected Field(Struct struct, int size, int align) {
+ this(struct, size, align, null);
+ }
+
+ protected Field(Struct struct, NativeType nativeType) {
+ this(struct, nativeType, null);
+ }
+
+ protected Field(Struct struct, NativeType nativeType, Offset offset) {
+ final Type type = struct.getRuntime().findType(nativeType);
+ registerInStructure(struct, type, offset);
+ }
+
+ protected Field(Struct struct, TypeAlias typeAlias) {
+ this(struct, typeAlias, null);
+ }
+
+ protected Field(Struct struct, TypeAlias typeAlias, Offset offset) {
+ Type type = struct.getRuntime().findType(typeAlias);
+ registerInStructure(struct, type, offset);
+ }
+
+ private void registerInStructure(Struct struct, Type type, Offset offset) {
+ registerInStructure(struct, type.size() * 8, type.alignment() * 8, offset);
+ }
+
+ public final jnr.ffi.Pointer getMemory() {
+ return info.getMemory();
+ }
+
+ public final Runtime getRuntime() {
+ return info.getRuntime();
+ }
+
+ protected long offset() {
+ return offset.intValue() + info.getOffset();
+ }
+
+ private void registerInStructure(Struct struct, int size, int alignment, Offset offset) {
+ info = struct.__info;
+ if (offset == null) {
+ int offsetAfterAllocation = struct.__info.addField(size, alignment);
+ this.offset = new Offset(offsetAfterAllocation);
+ } else {
+ struct.__info.addField(size, alignment, offset);
+ }
+
+ }
+}
diff --git a/src/main/java/jnr/ffi/struct/Offset.java b/src/main/java/jnr/ffi/struct/Offset.java
new file mode 100644
index 000000000..be4579a64
--- /dev/null
+++ b/src/main/java/jnr/ffi/struct/Offset.java
@@ -0,0 +1,24 @@
+package jnr.ffi.struct;
+
+public final class Offset extends Number {
+ private final int offset;
+ public Offset(int offset) {
+ this.offset = offset;
+ }
+ @Override
+ public int intValue() {
+ return offset;
+ }
+ @Override
+ public long longValue() {
+ return offset;
+ }
+ @Override
+ public float floatValue() {
+ return offset;
+ }
+ @Override
+ public double doubleValue() {
+ return offset;
+ }
+}
diff --git a/src/main/java/jnr/ffi/struct/StringField.java b/src/main/java/jnr/ffi/struct/StringField.java
new file mode 100644
index 000000000..4e2586de1
--- /dev/null
+++ b/src/main/java/jnr/ffi/struct/StringField.java
@@ -0,0 +1,38 @@
+package jnr.ffi.struct;
+
+import jnr.ffi.NativeType;
+
+import java.nio.charset.Charset;
+
+abstract public class StringField extends Field {
+ protected final Charset charset;
+ protected final int length;
+
+ protected StringField(Struct struct, NativeType nativeType, int length, Charset cs) {
+ super(struct, nativeType);
+ this.length = length;
+ this.charset = cs;
+ }
+ protected StringField(Struct struct, int size, int align, int length, Charset cs) {
+ super(struct, size, align);
+ this.length = length;
+ this.charset = cs;
+ }
+ protected StringField(Struct struct, int size, int align, Offset offset, int length, Charset cs) {
+ super(struct, size, align, offset);
+ this.length = length;
+ this.charset = cs;
+ }
+ public final int length() {
+ return length;
+ }
+
+ protected abstract jnr.ffi.Pointer getStringMemory();
+ public abstract java.lang.String get();
+ public abstract void set(java.lang.String value);
+
+ @Override
+ public final java.lang.String toString() {
+ return get();
+ }
+}
diff --git a/src/main/java/jnr/ffi/Struct.java b/src/main/java/jnr/ffi/struct/Struct.java
similarity index 92%
rename from src/main/java/jnr/ffi/Struct.java
rename to src/main/java/jnr/ffi/struct/Struct.java
index f235472cb..7c416899e 100755
--- a/src/main/java/jnr/ffi/Struct.java
+++ b/src/main/java/jnr/ffi/struct/Struct.java
@@ -25,8 +25,10 @@
* freely granted, provided that this notice is preserved.
*/
-package jnr.ffi;
+package jnr.ffi.struct;
+import jnr.ffi.*;
+import jnr.ffi.Runtime;
import jnr.ffi.provider.ParameterFlags;
import jnr.ffi.provider.jffi.ArrayMemoryIO;
import jnr.ffi.util.EnumMapper;
@@ -73,6 +75,10 @@ public final jnr.ffi.Pointer getMemory() {
return getMemory(ParameterFlags.TRANSIENT);
}
+ public final Runtime getRuntime() {
+ return runtime;
+ }
+
final boolean isDirect() {
return (enclosing != null && enclosing.__info.isDirect()) || (memory != null && memory.isDirect());
}
@@ -144,7 +150,7 @@ protected Struct(Runtime runtime, final boolean isUnion) {
}
public final Runtime getRuntime() {
- return __info.runtime;
+ return __info.getRuntime();
}
/**
@@ -233,29 +239,6 @@ public java.lang.String toString() {
return sb.toString();
}
- public static final class Offset extends java.lang.Number {
- private final int offset;
- public Offset(int offset) {
- this.offset = offset;
- }
- @Override
- public int intValue() {
- return offset;
- }
- @Override
- public long longValue() {
- return offset;
- }
- @Override
- public float floatValue() {
- return offset;
- }
- @Override
- public double doubleValue() {
- return offset;
- }
- }
-
public static final class Alignment extends Number {
private final int alignment;
@@ -284,32 +267,6 @@ public double doubleValue() {
}
}
- /**
- * Interface all Struct members must implement.
- */
- protected abstract class Member {
- /**
- * Gets the {@code Struct} this {@code Member} is a member of.
- *
- * @return a {@code Struct}.
- */
- abstract Struct struct();
-
- /**
- * Gets the memory object used to store this {@code Member}
- *
- * @return a {@code Pointer}
- */
- abstract jnr.ffi.Pointer getMemory();
-
- /**
- * Gets the offset within the structure for this field.
- *
- * @return the offset within the structure for this field.
- */
- abstract long offset();
- }
-
/**
* Starts an array construction session
*/
@@ -325,14 +282,14 @@ protected final void arrayEnd() {
}
/**
- * Creates an array of Member instances.
+ * Creates an array of Field instances.
*
- * @param The type of the Member subclass to create.
+ * @param The type of the Field subclass to create.
* @param array the array to store the instances in
* @return the array that was passed in
*/
@SuppressWarnings("unchecked")
- protected T[] array(T[] array) {
+ protected T[] array(T[] array) {
arrayBegin();
try {
Class> arrayClass = array.getClass().getComponentType();
@@ -673,10 +630,10 @@ protected final Pointer[] array(Pointer[] array) {
* @param stringLength length of each string in array
* @return the array that was passed in
*/
- protected UTF8String[] array(UTF8String[] array, int stringLength) {
+ protected jnr.ffi.struct.UTF8String[] array(jnr.ffi.struct.UTF8String[] array, int stringLength) {
arrayBegin();
for (int i = 0; i < array.length; i++) {
- array[i] = new UTF8String(stringLength);
+ array[i] = new jnr.ffi.struct.UTF8String(this, stringLength);
}
arrayEnd();
return array;
@@ -691,62 +648,16 @@ protected final T inner(T struct) {
return struct;
}
- /**
- * Base implementation of Member
- */
- protected abstract class AbstractMember extends Member {
- private final int offset;
- protected AbstractMember(int size) {
- this(size, size);
- }
- protected AbstractMember(int size, int align, Offset offset) {
- this.offset = __info.addField(size, align, offset);
- }
- protected AbstractMember(int size, int align) {
- this.offset = __info.addField(size, align);
- }
-
- protected AbstractMember(NativeType type) {
- final Type t = getRuntime().findType(type);
- this.offset = __info.addField(t.size() * 8, t.alignment() * 8);
- }
-
- protected AbstractMember(NativeType type, Offset offset) {
- final Type t = getRuntime().findType(type);
- this.offset = __info.addField(t.size() * 8, t.alignment() * 8, offset);
- }
-
- public final jnr.ffi.Pointer getMemory() {
- return __info.getMemory();
- }
-
- /**
- * Gets the Struct this Member is a member of.
- *
- * @return a Struct.
- */
- public final Struct struct() {
- return Struct.this;
- }
-
- /**
- * Gets the offset within the structure for this field.
- */
- public final long offset() {
- return offset + __info.getOffset();
- }
- }
-
/**
* Base class for Boolean fields
*/
- protected abstract class AbstractBoolean extends AbstractMember {
+ protected abstract class AbstractBoolean extends Field {
protected AbstractBoolean(NativeType type) {
- super(type);
+ super(Struct.this, type);
}
protected AbstractBoolean(NativeType type, Offset offset) {
- super(type, offset);
+ super(Struct.this, type, offset);
}
/**
@@ -861,53 +772,30 @@ public LONG(Offset offset) {
/**
* Base class for all Number structure fields.
*/
- public abstract class NumberField extends Member {
+ public abstract class NumberField extends Field {
/**
* Offset from the start of the Struct memory this field is located at.
*/
- private final int offset;
protected final Type type;
protected NumberField(NativeType type) {
+ super(Struct.this, type);
Type t = this.type = getRuntime().findType(type);
- this.offset = __info.addField(t.size() * 8, t.alignment() * 8);
}
protected NumberField(NativeType type, Offset offset) {
+ super(Struct.this, type, offset);
Type t = this.type = getRuntime().findType(type);
- this.offset = __info.addField(t.size() * 8, t.alignment() * 8, offset);
}
protected NumberField(TypeAlias type) {
+ super(Struct.this, type);
Type t = this.type = getRuntime().findType(type);
- this.offset = __info.addField(t.size() * 8, t.alignment() * 8);
}
protected NumberField(TypeAlias type, Offset offset) {
+ super(Struct.this, type, offset);
Type t = this.type = getRuntime().findType(type);
- this.offset = __info.addField(t.size() * 8, t.alignment() * 8, offset);
- }
-
-
- public final jnr.ffi.Pointer getMemory() {
- return __info.getMemory();
- }
-
-
- /**
- * Gets the Struct this Member is in.
- *
- * @return a Struct.
- */
- public final Struct struct() {
- return Struct.this;
- }
-
- /**
- * Gets the offset within the structure for this field.
- */
- public final long offset() {
- return offset + __info.getOffset();
}
/**
@@ -2280,70 +2168,41 @@ public Enum(Class enumClass) {
}
}
- abstract public class String extends AbstractMember {
- protected final Charset charset;
- protected final int length;
-
- protected String(int size, int align, int length, Charset cs) {
- super(size, align);
- this.length = length;
- this.charset = cs;
- }
- protected String(int size, int align, Offset offset, int length, Charset cs) {
- super(size, align, offset);
- this.length = length;
- this.charset = cs;
- }
- public final int length() {
- return length;
- }
-
- protected abstract jnr.ffi.Pointer getStringMemory();
- public abstract java.lang.String get();
- public abstract void set(java.lang.String value);
-
- @Override
- public final java.lang.String toString() {
- return get();
- }
- }
-
- public class UTFString extends String {
+ /**
+ * Use {@link jnr.ffi.struct.UTFString} instead
+ */
+ @Deprecated
+ public class UTFString extends jnr.ffi.struct.UTFString {
public UTFString(int length, Charset cs) {
- super(length * 8, 8, length, cs); // FIXME: This won't work for non-ASCII
-
- }
- protected jnr.ffi.Pointer getStringMemory() {
- return getMemory().slice(offset(), length());
- }
-
- public final java.lang.String get() {
- return getStringMemory().getString(0, length, charset);
- }
-
- public final void set(java.lang.String value) {
- getStringMemory().putString(0, value, length, charset);
+ super(Struct.this, length, cs);
}
}
- public class UTF8String extends UTFString {
+ /**
+ * Use {@link jnr.ffi.struct.UTF8String} instead
+ */
+ @Deprecated
+ public class UTF8String extends jnr.ffi.struct.UTF8String {
public UTF8String(int size) {
- super(size, UTF8);
+ super(Struct.this, size);
}
}
- public class AsciiString extends UTFString {
+ /**
+ * Use {@link jnr.ffi.struct.AsciiString} instead
+ */
+ @Deprecated
+ public class AsciiString extends jnr.ffi.struct.AsciiString {
public AsciiString(int size) {
- super(size, ASCII);
+ super(Struct.this, size);
}
}
- public class UTFStringRef extends String {
+ public class UTFStringRef extends StringField {
private jnr.ffi.Pointer valueHolder;
public UTFStringRef(int length, Charset cs) {
- super(getRuntime().findType(NativeType.ADDRESS).size() * 8, getRuntime().findType(NativeType.ADDRESS).alignment() * 8,
- length, cs);
+ super(Struct.this, NativeType.ADDRESS, length, cs);
}
public UTFStringRef(Charset cs) {
@@ -2394,22 +2253,22 @@ public AsciiStringRef() {
* Specialized padding fields for structs. Use this instead of arrays of other
* members for more efficient struct construction.
*/
- protected final class Padding extends AbstractMember {
+ protected final class Padding extends Field {
public Padding(Type type, int length) {
- super(type.size() * 8 * length, type.alignment() * 8);
+ super(Struct.this, type.size() * 8 * length, type.alignment() * 8);
}
public Padding(NativeType type, int length) {
- super(getRuntime().findType(type).size() * 8 * length, getRuntime().findType(type).alignment() * 8);
+ this(Struct.this.getRuntime().findType(type), length);
}
}
- public final class Function extends AbstractMember {
+ public final class Function extends Field {
private final Class extends T> closureClass;
private T instance;
public Function(Class extends T> closureClass) {
- super(NativeType.ADDRESS);
+ super(Struct.this, NativeType.ADDRESS);
this.closureClass = closureClass;
}
diff --git a/src/main/java/jnr/ffi/struct/UTF8String.java b/src/main/java/jnr/ffi/struct/UTF8String.java
new file mode 100644
index 000000000..e9d32d56f
--- /dev/null
+++ b/src/main/java/jnr/ffi/struct/UTF8String.java
@@ -0,0 +1,10 @@
+package jnr.ffi.struct;
+
+public class UTF8String extends UTFString {
+ private Struct struct;
+
+ public UTF8String(Struct struct, int size) {
+ super(struct, size, Struct.UTF8);
+ this.struct = struct;
+ }
+}
diff --git a/src/main/java/jnr/ffi/struct/UTFString.java b/src/main/java/jnr/ffi/struct/UTFString.java
new file mode 100644
index 000000000..8f128e896
--- /dev/null
+++ b/src/main/java/jnr/ffi/struct/UTFString.java
@@ -0,0 +1,21 @@
+package jnr.ffi.struct;
+
+import java.nio.charset.Charset;
+
+public class UTFString extends StringField {
+ public UTFString( Struct struct, int length, Charset cs) {
+ super(struct,length * 8, 8, length, cs); // FIXME: This won't work for non-ASCII
+
+ }
+ protected jnr.ffi.Pointer getStringMemory() {
+ return getMemory().slice(offset(), length());
+ }
+
+ public final java.lang.String get() {
+ return getStringMemory().getString(0, length, charset);
+ }
+
+ public final void set(java.lang.String value) {
+ getStringMemory().putString(0, value, length, charset);
+ }
+}
diff --git a/src/main/java/jnr/ffi/Union.java b/src/main/java/jnr/ffi/struct/Union.java
similarity index 95%
rename from src/main/java/jnr/ffi/Union.java
rename to src/main/java/jnr/ffi/struct/Union.java
index 693818d3c..03261a84c 100644
--- a/src/main/java/jnr/ffi/Union.java
+++ b/src/main/java/jnr/ffi/struct/Union.java
@@ -25,7 +25,9 @@
* freely granted, provided that this notice is preserved.
*/
-package jnr.ffi;
+package jnr.ffi.struct;
+
+import jnr.ffi.Runtime;
/**
* Represents a C union
diff --git a/src/test/java/jnr/ffi/DelegateTest.java b/src/test/java/jnr/ffi/DelegateTest.java
index 3575a1036..c34577828 100644
--- a/src/test/java/jnr/ffi/DelegateTest.java
+++ b/src/test/java/jnr/ffi/DelegateTest.java
@@ -20,6 +20,7 @@
import jnr.ffi.annotations.Delegate;
import jnr.ffi.annotations.LongLong;
+import jnr.ffi.struct.Struct;
import jnr.ffi.types.u_int32_t;
import org.junit.*;
diff --git a/src/test/java/jnr/ffi/PointerTest.java b/src/test/java/jnr/ffi/PointerTest.java
index eb98658b5..5866fc85c 100644
--- a/src/test/java/jnr/ffi/PointerTest.java
+++ b/src/test/java/jnr/ffi/PointerTest.java
@@ -19,6 +19,7 @@
package jnr.ffi;
import jnr.ffi.annotations.*;
+import jnr.ffi.struct.Struct;
import jnr.ffi.types.int32_t;
import jnr.ffi.types.int8_t;
import jnr.ffi.types.size_t;
diff --git a/src/test/java/jnr/ffi/struct/AsciiStringFieldTest.java b/src/test/java/jnr/ffi/struct/AsciiStringFieldTest.java
index ea5b8042f..de78e2c16 100644
--- a/src/test/java/jnr/ffi/struct/AsciiStringFieldTest.java
+++ b/src/test/java/jnr/ffi/struct/AsciiStringFieldTest.java
@@ -18,8 +18,6 @@
package jnr.ffi.struct;
-import jnr.ffi.Library;
-import jnr.ffi.Struct;
import jnr.ffi.annotations.In;
import jnr.ffi.annotations.Out;
import jnr.ffi.annotations.Pinned;
@@ -41,7 +39,7 @@ public class AsciiStringFieldTest {
public AsciiStringFieldTest() {
}
public class StringFieldStruct extends Struct {
- public final String string = new AsciiString(32);
+ public final StringField string = new jnr.ffi.struct.AsciiString(this, 32);
public StringFieldStruct() {
super(runtime);
diff --git a/src/test/java/jnr/ffi/struct/FieldTest.java b/src/test/java/jnr/ffi/struct/FieldTest.java
new file mode 100644
index 000000000..e21e4afe0
--- /dev/null
+++ b/src/test/java/jnr/ffi/struct/FieldTest.java
@@ -0,0 +1,71 @@
+package jnr.ffi.struct;
+
+import jnr.ffi.NativeType;
+import jnr.ffi.Runtime;
+import jnr.ffi.TstUtil;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class FieldTest {
+
+ static class CustomChar extends Field {
+
+ CustomChar(Struct struct) {
+ super(struct, NativeType.SCHAR);
+ }
+
+ public final byte get() {
+ return getMemory().getByte(offset());
+ }
+
+ public final void set(byte value) {
+ getMemory().putByte(offset(), value);
+ }
+ }
+
+ static class CustomStruct extends Struct {
+
+ CustomStruct(Runtime runtime) {
+ super(runtime);
+ }
+
+ CustomChar customChar = new CustomChar(this);
+ CharStruct innerStruct = inner(new CharStruct(getRuntime()));
+ }
+
+ static class CharStruct extends Struct {
+
+ CharStruct(Runtime runtime) {
+ super(runtime);
+ }
+
+ CustomChar customChar = new CustomChar(this);
+ }
+
+ public static interface TestLib {
+ byte struct_field_Signed8(CustomStruct s);
+ byte struct_field_Signed8(CharStruct s);
+ }
+
+ static TestLib testlib;
+ static Runtime runtime;
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ testlib = TstUtil.loadTestLib(TestLib.class);
+ runtime = Runtime.getRuntime(testlib);
+ }
+
+ @Test
+ public void byteField() {
+ final byte MAGIC = (byte) 0xbe;
+ CharStruct s = new CharStruct(runtime);
+ s.customChar.set(MAGIC);
+
+ assertEquals("byte field not set", MAGIC, testlib.struct_field_Signed8(s));
+ s.customChar.set((byte) 0);
+ assertEquals("byte field not cleared", (byte) 0, testlib.struct_field_Signed8(s));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/jnr/ffi/struct/UTF8StringFieldTest.java b/src/test/java/jnr/ffi/struct/UTF8StringFieldTest.java
index 9aecd7a8a..91d5bcb11 100644
--- a/src/test/java/jnr/ffi/struct/UTF8StringFieldTest.java
+++ b/src/test/java/jnr/ffi/struct/UTF8StringFieldTest.java
@@ -18,9 +18,7 @@
package jnr.ffi.struct;
-import jnr.ffi.Struct;
import jnr.ffi.TstUtil;
-import jnr.ffi.Library;
import jnr.ffi.Runtime;
import jnr.ffi.annotations.In;
import jnr.ffi.annotations.Out;
@@ -42,7 +40,7 @@ public UTF8StringFieldTest() {
}
public static class StringFieldStruct extends Struct {
- public final UTF8String string = new UTF8String(32);
+ public final jnr.ffi.struct.UTF8String string = new jnr.ffi.struct.UTF8String(this, 32);
public StringFieldStruct() {
super(runtime);
@@ -89,7 +87,7 @@ public void tearDown() {
public static final class SockaddrUnix extends Struct {
private final Signed8 sun_len = new Signed8();
private final Signed8 sun_family = new Signed8();
- private final UTF8String sun_path = new UTF8String(100);
+ private final jnr.ffi.struct.UTF8String sun_path = new jnr.ffi.struct.UTF8String(this, 100);
public SockaddrUnix() {
super(runtime);
diff --git a/src/test/java/jnr/ffi/struct/UnionTest.java b/src/test/java/jnr/ffi/struct/UnionTest.java
index f26b364d1..d4a95e635 100644
--- a/src/test/java/jnr/ffi/struct/UnionTest.java
+++ b/src/test/java/jnr/ffi/struct/UnionTest.java
@@ -21,9 +21,7 @@
import java.nio.ByteOrder;
import jnr.ffi.Runtime;
-import jnr.ffi.Struct;
import jnr.ffi.TstUtil;
-import jnr.ffi.Union;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;