|
JADE v6.1 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectcom.dautelle.util.Struct
This class represents a C/C++ struct
; it confers
interoperability between Java classes and C/C++ struct.
Unlike C/C++
, the storage layout of Java objects is not
determined by the compiler. The layout of objects in memory is deferred
to run time and determined by the interpreter (or just-in-time compiler).
This approach allows for dynamic loading and binding; but also makes
interfacing with C/C++
code difficult. Hence, this class for
which the memory layout is defined by the initialization order of the
Struct
's members
and follows the same alignment
rules as C/C++ structs
.
This class (as well as the Union
sub-class) facilitates:
Because of its one-to-one mapping, it is relatively easy to convert C
header files (e.g. OpenGL bindings) to Java Struct
/Union
using simple text macros. Here is an example of C struct:
struct Date { unsigned short year; unsigned char month; unsigned char day; }; struct Student { char name[64]; struct Date birth; float grades[10]; Student* next; };and here is the Java equivalent using this class:
public static class Date extends Struct { public final Unsigned16 year = new Unsigned16(); public final Unsigned8 month = new Unsigned8(); public final Unsigned8 day = new Unsigned8(); } public static class Student extends Struct { public final UTF8String name = new UTF8String(64); public final Date birth = (Date) new StructMember(Date.class).get(); public final Float32[] grades = (Float32[]) new ArrayMember(Float32.class, 10).get(); public final Reference32 next = new Reference32(Student.class); }Struct's members are directly accessible:
Student student = new Student(); student.name.set("John Doe"); // Null terminated (C compatible) int age = 2003 - student.birth.year.get(); student.grades[2].set(12.5f); student = (Student) student.next.get();
Applications may also work with the raw bytes
directly. The following illustrate how Struct
can be used to
decode/encode UDP messages directly:
class MyUdpMessage extends Struct { ... // UDP message fields. public MyUdpMessage(byte[] bytes) { super(ByteBuffer.wrap(bytes)); } } public void run() { byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); MyUdpMessage message = new MyUdpMessage(bytes); // packet and message are now two different views of the same data. while (true) { _socket.receive(packet); ... // Process message fields directly. packet.setLength(bytes.length); // Reset length to buffer's length. } }
It is relatively easy to map instances of this class to any physical address using JNI. Here is an example:
import java.nio.ByteBuffer; class Clock extends Struct { // Hardware clock mapped to memory. Unsigned16 seconds = new Unsigned16(5); // unsigned short seconds:5 Unsigned16 minutes = new Unsigned16(5); // unsigned short minutes:5 Unsigned16 hours = new Unsigned16(4); // unsigned short hours:4 Clock() { super(Clock.nativeBuffer()); } private static native ByteBuffer nativeBuffer(); }Below is the
nativeBuffer()
implementation
(Clock.c
):#include <jni.h> #include "Clock.h" // Generated using javah JNIEXPORT jobject JNICALL Java_Clock_nativeBuffer (JNIEnv *env, jclass) { return (*env)->NewDirectByteBuffer(env, clock_address, buffer_size) }
Finally, bit-fields are supported (see Clock
example above).
Bit-fields allocation order is defined by the Struct byteOrder()
return value (leftmost bit to rightmost bit if
BIG_ENDIAN
and rightmost bit to leftmost bit if
LITTLE_ENDIAN
).
Unless the Struct packing
directive is overriden,
bit-fields cannot straddle the storage-unit boundary as defined by their
base type (padding is inserted at the end of the first bit-field
and the second bit-field is put into the next storage unit).
This class is public domain (not copyrighted).
Nested Class Summary | |
class |
Struct.ArrayMember
This class represents an array member. |
class |
Struct.Bool
This class represents a 8 bits boolean with true represented
by 1 and false represented by 0 . |
class |
Struct.Enum16
This class represents a 16 bits Enum . |
class |
Struct.Enum32
This class represents a 32 bits Enum . |
class |
Struct.Enum64
This class represents a 64 bits Enum . |
class |
Struct.Enum8
This class represents a 8 bits Enum . |
class |
Struct.Float32
This class represents a 32 bits float (C/C++/Java float ). |
class |
Struct.Float64
This class represents a 64 bits float (C/C++/Java double ). |
protected class |
Struct.Member
This inner class represents the base class for all Struct
members. |
class |
Struct.Reference32
This class represents a 32 bits reference (C/C++ pointer) to a Struct object (other types may require a Struct
wrapper). |
class |
Struct.Reference64
This class represents a 64 bits reference (C/C++ pointer) to a Struct object (other types may require a Struct
wrapper). |
class |
Struct.Signed16
This class represents a 16 bits signed integer. |
class |
Struct.Signed32
This class represents a 32 bits signed integer. |
class |
Struct.Signed64
This class represents a 64 bits signed integer. |
class |
Struct.Signed8
This class represents a 8 bits signed integer. |
class |
Struct.StructMember
This class represents an inner struct member. |
class |
Struct.Unsigned16
This class represents a 16 bits unsigned integer. |
class |
Struct.Unsigned32
This class represents a 32 bits unsigned integer. |
class |
Struct.Unsigned8
This class represents a 8 bits unsigned integer. |
class |
Struct.UTF8String
This class represents a UTF-8 character string, null terminated (for C/C++ compatibility) |
Constructor Summary | |
Struct()
Default constructor. |
|
Struct(java.nio.ByteBuffer byteBuffer)
Creates a Struct backed by the specified ByteBuffer . |
Method Summary | |
long |
address()
Returns this Struct address. |
java.nio.ByteBuffer |
byteBuffer()
Returns the ByteBuffer backing this Struct . |
java.nio.ByteOrder |
byteOrder()
Returns the byte order for this Struct . |
static Struct |
copy(Struct src,
Struct dest)
Copies the content of the specified source Struct to the
specified destination Struct . |
boolean |
equals(java.lang.Object that)
Indicates if this Struct is equal to the specified object. |
int |
hashCode()
Returns a hash code value for this Struct . |
boolean |
isPacked()
Indicates if this Struct is packed. |
int |
size()
Returns the size in bytes of this Struct . |
java.lang.String |
toString()
Returns the String representation of this Struct
in the form of its constituing bytes (hexadecimal). |
Methods inherited from class java.lang.Object |
clone, finalize, getClass, notify, notifyAll, wait, wait, wait |
Constructor Detail |
public Struct()
Struct
created using this
constructor are backed by a direct buffer. Inner Struct
are
always backed by the buffer of their outer parent.
public Struct(java.nio.ByteBuffer byteBuffer)
Struct
backed by the specified ByteBuffer
.
The specified byte buffer can be mapped to memory for direct memory
access or can wrap a shared byte array for I/O purpose
(e.g. DatagramPacket
). The address of the first
field is always at position 0
in the specified buffer.
byteBuffer
- the byte buffer for this Struct
.Method Detail |
public final int size()
Struct
. The size includes
tail padding to satisfy the Struct
alignment requirement
(defined by the largest alignment of its members
).
sizeof(this)
.public final java.nio.ByteBuffer byteBuffer()
ByteBuffer
backing this Struct
.
Changes to the buffer's content are visible in the Struct
,
and vice versa.
The buffer limit is size()
and its position index is
undefined. Methods modifying the buffer position should either
synchronize on the buffer or work with a duplicate.
The buffer of an inner Struct
is a shared subsequence of
the buffer's content of its outer parent.
The buffer is direct if, and only if, this Struct
(or its outer Struct
) is backed by a direct buffer (see
Struct(ByteBuffer)
).
The position index of a Struct.Member
within the buffer is
given by Struct.Member.offset()
(the first field member
starting at 0
).
Struct
.public static Struct copy(Struct src, Struct dest)
Struct
to the
specified destination Struct
.
src
- the source Struct
.dest
- the destination Struct
.
dest
java.lang.IllegalArgumentException
- if dest
is not an instance
of src.getClass()
,public boolean equals(java.lang.Object that)
Struct
is equal to the specified object.
that
- the object to compare for equality.
true
if this struct and the specified object are
both struct of same class with same content;
false
otherwise.public final int hashCode()
Struct
.
Note: Because Struct
hash codes are content-dependent,
it is inadvisable to use Struct
as keys in hash maps
or similar data structures unless it is known that their
contents will not change.
public final long address()
Struct
address. This method allows for
Struct
to be referenced (e.g. pointer) from other Struct
.
java.lang.UnsupportedOperationException
- if the struct's buffer is not
a direct buffer.public java.lang.String toString()
String
representation of this Struct
in the form of its constituing bytes (hexadecimal). For example:public static class Student extends Struct { UTF8String name = new UTF8String(16); Unsigned16 year = new Unsigned16(); Float32 grade = new Float32(); } Student student = new Student(); student.name.set("John Doe"); student.year.set(2003); student.grade.set(12.5f); System.out.println(student); 4a 6f 68 6e 20 44 6f 65 00 00 00 00 00 00 00 00 07 d3 00 00 41 48 00 00
Struct
.public java.nio.ByteOrder byteOrder()
Struct
. The byte order is
inherited by inner structs. Sub-classes may change the byte order
by overriding this method. For example:public class TopStruct extends Struct { ... // Members initialization. public ByteOrder byteOrder() { // TopStruct and its inner structs use hardware byte order. return ByteOrder.nativeOrder(); } }}
BIG_ENDIAN
).public boolean isPacked()
Struct
is packed.
By default, Struct.Member
of a Struct
are aligned on the
boundary corresponding to the member's base type; padding is performed
if necessary. This directive is inherited by inner structs.
Sub-classes may change the packing directive by overriding this method.
For example:public class TopStruct extends Struct { ... // Members initialization. public boolean isPacked() { // TopStruct and its inner structs are packed. return true; } }}
true
if alignment requirements are ignored.
false
otherwise (default).
|
JADE v6.1 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |