Class Struct
- java.lang.Object
-
- javolution37.javolution.io.Struct
-
- Direct Known Subclasses:
- Union
public class Struct extends java.lang.ObjectThis 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 withC/C++code difficult. Hence, this class for which the memory layout is defined by the initialization order of theStruct'smembersand follows the same alignment rules asC/C++ structs.This class (as well as the
Unionsub-class) facilitates:- Memory sharing between Java applications and native libraries.
- Direct encoding/decoding of streams for which the structure is defined by legacy C/C++ code.
- Serialization/deserialization of Java objects (complete control, e.g. no class header)
- Mapping of Java objects to physical addresses (with JNI).
Because of its one-to-one mapping, it is relatively easy to convert C header files (e.g. OpenGL bindings) to Java
Struct/Unionusing simple text macros. Here is an example of C struct:and here is the Java equivalent using this class:struct Date { unsigned short year; unsigned byte month; unsigned byte day; }; struct Student { char name[64]; struct Date birth; float grades[10]; Student* next; };Struct's members are directly accessible: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 = inner(new Date()); public final Float32[] grades = array(new Float32[10]); public final Reference32<Student> next = new Reference32<Student>(); }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.next.get();Applications may also work with the raw
bytesdirectly. The following illustrate howStructcan be used to decode/encode UDP messages directly:class UdpMessage extends Struct { Unsigned16 xxx = new Unsigned16(); ... } public void run() { byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); UdpMessage message = new UdpMessage(); message.setByteBuffer(ByteBuffer.wrap(bytes), 0); // packet and message are now two different views of the same data. while (isListening) { multicastSocket.receive(packet); int xxx = message.xxx.get(); ... // Process message fields directly. } }It is relatively easy to map instances of this class to any physical address using JNI. Here is an example:
Below is theimport 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() { setByteBuffer(Clock.nativeBuffer(), 0); } private static native ByteBuffer nativeBuffer(); }nativeBuffer()implementation (Clock.c):#include#include "Clock.h" // Generated using javah JNIEXPORT jobject JNICALL Java_Clock_nativeBuffer (JNIEnv *env, jclass) { return (*env)->NewDirectByteBuffer(env, clock_address, buffer_size) } Bit-fields are supported (see
Clockexample above). Bit-fields allocation order is defined by the StructbyteOrder()return value (leftmost bit to rightmost bit ifBIG_ENDIANand rightmost bit to leftmost bit ifLITTLE_ENDIAN). Unless the Structpackingdirective 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).Finally, it is possible to change the
ByteBufferand/or the Structpositionin itsByteBufferto allow for a singleStructobject to encode/decode multiple memory mapped instances.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class and Description classStruct.BoolThis class represents a 8 bits boolean withtruerepresented by1andfalserepresented by0.classStruct.Enum16This class represents a 16 bitsEnum.classStruct.Enum32This class represents a 32 bitsEnum.classStruct.Enum64This class represents a 64 bitsEnum.classStruct.Enum8This class represents a 8 bitsEnum.classStruct.Float32This class represents a 32 bits float (C/C++/Javafloat).classStruct.Float64This class represents a 64 bits float (C/C++/Javadouble).classStruct.Reference32<S extends Struct>classStruct.Reference64<S extends Struct>classStruct.Signed16This class represents a 16 bits signed integer.classStruct.Signed32This class represents a 32 bits signed integer.classStruct.Signed64This class represents a 64 bits signed integer.classStruct.Signed8This class represents a 8 bits signed integer.classStruct.Unsigned16This class represents a 16 bits unsigned integer.classStruct.Unsigned32This class represents a 32 bits unsigned integer.classStruct.Unsigned8This class represents a 8 bits unsigned integer.classStruct.Utf8StringThis class represents a UTF-8 character string, null terminated (for C/C++ compatibility)
-
Constructor Summary
Constructors Constructor and Description Struct()Default constructor.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method and Description longaddress()Returns this struct address.java.nio.ByteOrderbyteOrder()Returns the byte order for this struct (configurable).java.nio.ByteBuffergetByteBuffer()Returns the byte buffer for this struct.intgetByteBufferPosition()Returns the absolute position of this struct within its associatedbyte buffer.booleanisPacked()Indicates if this struct is packed (configurable).booleanisUnion()Indicates if this struct's members are mapped to the same location in memory (defaultfalse).intread(java.io.InputStream in)Reads this struct from the specified input stream (convenience method when using Stream I/O).StructsetByteBuffer(java.nio.ByteBuffer byteBuffer, int position)Sets the current byte buffer for this struct.StructsetByteBufferPosition(int position)Sets the position of this struct within its byte buffer.intsize()Returns the size in bytes of this struct.java.lang.StringtoString()Returns theStringrepresentation of this struct in the form of its constituing bytes (hexadecimal).voidwrite(java.io.OutputStream out)Writes this struct to the specified output stream (convenience method when using Stream I/O).
-
-
-
Method Detail
-
size
public final int size()
Returns the size in bytes of this struct. The size includes tail padding to satisfy the struct alignment requirement (defined by the largest alignment of itsmembers).- Returns:
- the C/C++
sizeof(this).
-
getByteBuffer
public final java.nio.ByteBuffer getByteBuffer()
Returns the byte buffer for this struct. This method will allocate a new direct buffer if none has been set.Changes to the buffer's content are visible in this struct, and vice versa.
The buffer of an inner struct is the same as its parent struct.
The position of a
struct's memberwithin the byte buffer is given bymember.position()- Returns:
- the current byte buffer or a new direct buffer if none set.
- See Also:
setByteBuffer(java.nio.ByteBuffer, int)
-
setByteBuffer
public final Struct setByteBuffer(java.nio.ByteBuffer byteBuffer, int position)
Sets the current byte buffer for this struct. 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).- Parameters:
byteBuffer- the new byte buffer.position- the position of this struct in the specified byte buffer.- Returns:
this- Throws:
java.lang.IllegalArgumentException- if the specified byteBuffer has a different byte order than this struct.java.lang.UnsupportedOperationException- if this struct is an inner struct.- See Also:
byteOrder()
-
setByteBufferPosition
public final Struct setByteBufferPosition(int position)
Sets the position of this struct within its byte buffer.- Parameters:
position- the position of this struct in its byte buffer.- Returns:
this- Throws:
java.lang.UnsupportedOperationException- if this struct is an inner struct.
-
getByteBufferPosition
public final int getByteBufferPosition()
Returns the absolute position of this struct within its associatedbyte buffer.- Returns:
- the absolute position of this struct in the byte buffer.
-
read
public int read(java.io.InputStream in) throws java.io.IOExceptionReads this struct from the specified input stream (convenience method when using Stream I/O). For better performance, use of Block I/O (e.g.java.nio.channels.*) is recommended.- Parameters:
in- the input stream being read from.- Returns:
- the number of bytes read (typically the
sizeof this struct. - Throws:
java.io.IOException- if an I/O error occurs.
-
write
public void write(java.io.OutputStream out) throws java.io.IOExceptionWrites this struct to the specified output stream (convenience method when using Stream I/O). For better performance, use of Block I/O (e.g.java.nio.channels.*) is recommended.- Parameters:
out- the output stream to write to.- Throws:
java.io.IOException- if an I/O error occurs.
-
address
public final long address()
Returns this struct address. This method allows for structs to be referenced (e.g. pointer) from other structs.- Returns:
- the struct memory address.
- Throws:
java.lang.UnsupportedOperationException- if the struct buffer is not a direct buffer.- See Also:
Struct.Reference32,Struct.Reference64
-
toString
public java.lang.String toString()
Returns theStringrepresentation 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- Overrides:
toStringin classjava.lang.Object- Returns:
- a hexadecimal representation of the bytes content for this struct.
-
isUnion
public boolean isUnion()
Indicates if this struct's members are mapped to the same location in memory (defaultfalse). This method is useful for applications extendingStructwith new member types in order to create unions from these new structs. For example:public abstract class FortranStruct extends Struct { public class FortranString extends Member {...} protected FortranString[] array(FortranString[] array, int stringLength) { ... } } public abstract class FortranUnion extends FortranStruct { // Inherits new members and methods. public final isUnion() { return true; } }- Returns:
trueif this struct's members are mapped to to the same location in memory;falseotherwise.- See Also:
Union
-
byteOrder
public java.nio.ByteOrder byteOrder()
Returns the byte order for this struct (configurable). 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(); } }}- Returns:
- the byte order when reading/writing multibyte values
(default: network byte order,
BIG_ENDIAN).
-
isPacked
public boolean isPacked()
Indicates if this struct is packed (configurable). By default,membersof a struct are aligned on the boundary corresponding to the member 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; } }}- Returns:
trueif alignment requirements are ignored.falseotherwise (default).
-
-
DMelt 3.0 © DataMelt by jWork.ORG