Source Code Cross Referenced for Struct.java in  » Science » javolution-5.2 » javolution » io » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » javolution 5.2 » javolution.io 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
0003:         * Copyright (C) 2006 - Javolution (http://javolution.org/)
0004:         * All rights reserved.
0005:         * 
0006:         * Permission to use, copy, modify, and distribute this software is
0007:         * freely granted, provided that this notice is preserved.
0008:         */
0009:        package javolution.io;
0010:
0011:        import j2me.lang.UnsupportedOperationException;
0012:        import j2me.nio.ByteBuffer;
0013:        import j2me.nio.ByteOrder;
0014:        import j2me.util.List;
0015:        import javolution.JavolutionError;
0016:        import javolution.lang.Configurable;
0017:        import javolution.lang.Enum;
0018:        import javolution.lang.MathLib;
0019:        import javolution.lang.Reflection;
0020:
0021:        import java.io.IOException;
0022:        import java.io.InputStream;
0023:        import java.io.OutputStream;
0024:
0025:        /**
0026:         * <p> This class represents a <code>C/C++ struct</code>; it confers
0027:         *     interoperability between Java classes and C/C++ struct.</p>
0028:         * <p> Unlike <code>C/C++</code>, the storage layout of Java objects is not
0029:         *     determined by the compiler. The layout of objects in memory is deferred
0030:         *     to run time and determined by the interpreter (or just-in-time compiler).
0031:         *     This approach allows for dynamic loading and binding; but also makes
0032:         *     interfacing with <code>C/C++</code> code difficult. Hence, this class for
0033:         *     which the memory layout is defined by the initialization order of the
0034:         *     {@link Struct}'s {@link Member members} and follows the same alignment
0035:         *      rules as <code>C/C++ structs</code>.</p>
0036:         * <p> This class (as well as the {@link Union} sub-class) facilitates:
0037:         *     <ul>
0038:         *     <li> Memory sharing between Java applications and native libraries.</li>
0039:         *     <li> Direct encoding/decoding of streams for which the structure
0040:         *          is defined by legacy C/C++ code.</li>
0041:         *     <li> Serialization/deserialization of Java objects (complete control,
0042:         *          e.g. no class header)</li>
0043:         *     <li> Mapping of Java objects to physical addresses (with JNI).</li>
0044:         *     </ul></p>
0045:         * <p> Because of its one-to-one mapping, it is relatively easy to convert C 
0046:         *     header files (e.g. OpenGL bindings) to Java {@link Struct}/{@link Union}
0047:         *     using simple text macros. Here is an example of C struct:<code><pre>
0048:         *     struct Date {
0049:         *         unsigned short year;
0050:         *         unsigned byte month;
0051:         *         unsigned byte day;
0052:         *     };
0053:         *     struct Student {
0054:         *         char        name[64];
0055:         *         struct Date birth;
0056:         *         float       grades[10];
0057:         *         Student*    next;
0058:         *     };</pre></code>
0059:         *     and here is the Java equivalent using this class:[code]
0060:         *     public static class Date extends Struct {
0061:         *         public final Unsigned16 year = new Unsigned16();
0062:         *         public final Unsigned8 month = new Unsigned8();
0063:         *         public final Unsigned8 day   = new Unsigned8();
0064:         *     }
0065:         *     public static class Student extends Struct {
0066:         *         public final Utf8String  name   = new UTF8String(64);
0067:         *         public final Date        birth  = inner(new Date());
0068:         *         public final Float32[]   grades = array(new Float32[10]);
0069:         *         public final Reference32<Student> next =  new Reference32<Student>();
0070:         *     }[/code]
0071:         *     Struct's members are directly accessible:[code]
0072:         *     Student student = new Student();
0073:         *     student.name.set("John Doe"); // Null terminated (C compatible)
0074:         *     int age = 2003 - student.birth.year.get();
0075:         *     student.grades[2].set(12.5f);
0076:         *     student = student.next.get();[/code]</p>
0077:         * <p> Applications may also work with the raw {@link #getByteBuffer() bytes}
0078:         *     directly. The following illustrate how {@link Struct} can be used to 
0079:         *     decode/encode UDP messages directly:[code]
0080:         *     class UDPMessage extends Struct {
0081:         *          Unsigned16 xxx = new Unsigned16();
0082:         *          ... 
0083:         *     }
0084:         *     public void run() {
0085:         *         byte[] bytes = new byte[1024];
0086:         *         DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
0087:         *         UDPMessage message = new UDPMessage();
0088:         *         message.setByteBuffer(ByteBuffer.wrap(bytes), 0);
0089:         *         // packet and message are now two different views of the same data. 
0090:         *         while (isListening) {
0091:         *             multicastSocket.receive(packet);
0092:         *             int xxx = message.xxx.get();
0093:         *             ... // Process message fields directly.
0094:         *         }
0095:         *     }[/code]</p> 
0096:         * <p> It is relatively easy to map instances of this class to any physical
0097:         *     address using
0098:         *     <a href="http://java.sun.com/docs/books/tutorial/native1.1/index.html">
0099:         *     JNI</a>. Here is an example:[code]
0100:         *     import java.nio.ByteBuffer;
0101:         *     class Clock extends Struct { // Hardware clock mapped to memory.
0102:         *         Unsigned16 seconds  = new Unsigned16(5); // unsigned short seconds:5
0103:         *         Unsigned16 minutes  = new Unsigned16(5); // unsigned short minutes:5
0104:         *         Unsigned16 hours    = new Unsigned16(4); // unsigned short hours:4
0105:         *         Clock() {
0106:         *             setByteBuffer(Clock.nativeBuffer(), 0);
0107:         *         }
0108:         *         private static native ByteBuffer nativeBuffer();
0109:         *     }[/code]
0110:         *     Below is the <code>nativeBuffer()</code> implementation
0111:         *     (<code>Clock.c</code>):[code]
0112:         *     #include <jni.h>
0113:         *     #include "Clock.h" // Generated using javah
0114:         *     JNIEXPORT jobject JNICALL Java_Clock_nativeBuffer (JNIEnv *env, jclass) {
0115:         *         return (*env)->NewDirectByteBuffer(env, clock_address, buffer_size)
0116:         *     }[/code]</p>
0117:         * <p> Bit-fields are supported (see <code>Clock</code> example above).
0118:         *     Bit-fields allocation order is defined by the Struct {@link #byteOrder}
0119:         *     return value (leftmost bit to rightmost bit if
0120:         *     <code>BIG_ENDIAN</code> and rightmost bit to leftmost bit if
0121:         *      <code>LITTLE_ENDIAN</code>).
0122:         *     Unless the Struct {@link #isPacked packing} directive is overriden,
0123:         *     bit-fields cannot straddle the storage-unit boundary as defined by their
0124:         *     base type (padding is inserted at the end of the first bit-field
0125:         *     and the second bit-field is put into the next storage unit).</p>
0126:         * <p> Finally, it is possible to change the {@link #setByteBuffer ByteBuffer} 
0127:         *     and/or the Struct {@link #setByteBufferPosition position} in its 
0128:         *     <code>ByteBuffer</code> to allow for a single {@link Struct} object to
0129:         *     encode/decode multiple memory mapped instances.</p>
0130:         *     
0131:         * <p><i>Note: Because Struct/Union are basically wrappers around 
0132:         *             <code>java.nio.ByteBuffer</code>, tutorials/usages for 
0133:         *             the Java NIO package are directly applicable to Struct.</i></p>
0134:         * 
0135:         * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
0136:         * @version 5.1, July 17, 2007
0137:         */
0138:        public class Struct {
0139:
0140:            /**
0141:             * Configurable holding the maximum alignment in bytes 
0142:             * (default <code>4</code>).
0143:             */
0144:            public static final Configurable/*<Integer>*/MAXIMUM_ALIGNMENT = new Configurable(
0145:                    new Integer(4));
0146:
0147:            /**
0148:             * Holds the outer struct if any.
0149:             */
0150:            private Struct _outer;
0151:
0152:            /**
0153:             * Holds the byte buffer backing the struct (top struct).
0154:             */
0155:            private ByteBuffer _byteBuffer;
0156:
0157:            /**
0158:             * Holds the offset of this struct relative to the outer struct or
0159:             * to the byte buffer if there is no outer.
0160:             */
0161:            private int _outerOffset;
0162:
0163:            /**
0164:             * Holds the number of bits currently used (for size calculation).
0165:             */
0166:            private int _bitsUsed;
0167:
0168:            /**
0169:             * Holds this struct alignment (largest alignment of its members).
0170:             */
0171:            private int _alignment = 1;
0172:
0173:            /**
0174:             * Holds the current bit index position (during construction).
0175:             */
0176:            private int _bitIndex;
0177:
0178:            /**
0179:             * Indicates if the index has to be reset for each new field.
0180:             */
0181:            private boolean _resetIndex;
0182:
0183:            /**
0184:             * Holds bytes array for Stream I/O when byteBuffer has no intrinsic array.
0185:             */
0186:            private byte[] _bytes;
0187:
0188:            /**
0189:             * Default constructor.
0190:             */
0191:            public Struct() {
0192:                _resetIndex = isUnion();
0193:            }
0194:
0195:            /**
0196:             * Returns the size in bytes of this struct. The size includes
0197:             * tail padding to satisfy the struct alignment requirement
0198:             * (defined by the largest alignment of its {@link Member members}).
0199:             *
0200:             * @return the C/C++ <code>sizeof(this)</code>.
0201:             */
0202:            public final int size() {
0203:                int nbrOfBytes = (_bitsUsed + 7) >> 3;
0204:                return ((nbrOfBytes % _alignment) == 0) ? nbrOfBytes : // Already aligned or packed.
0205:                        nbrOfBytes + _alignment - (nbrOfBytes % _alignment); // Tail padding.
0206:            }
0207:
0208:            /**
0209:             * Returns the byte buffer for this struct. This method will allocate 
0210:             * a new <b>direct</b> buffer if none has been set.
0211:             *
0212:             * <p> Changes to the buffer's content are visible in this struct,
0213:             *     and vice versa.</p>
0214:             * <p> The buffer of an inner struct is the same as its parent struct.</p>
0215:             * <p> The position of a {@link Struct.Member struct's member} within the 
0216:             *     byte buffer is given by {@link Struct.Member#position
0217:             *     member.position()}</p>
0218:             *
0219:             * @return the current byte buffer or a new direct buffer if none set.
0220:             * @see #setByteBuffer
0221:             */
0222:            public final ByteBuffer getByteBuffer() {
0223:                if (_outer != null)
0224:                    return _outer.getByteBuffer();
0225:                return (_byteBuffer != null) ? _byteBuffer : newBuffer();
0226:            }
0227:
0228:            private synchronized ByteBuffer newBuffer() {
0229:                if (_byteBuffer != null)
0230:                    return _byteBuffer; // Synchronized check.
0231:                int size = size();
0232:                // Covers misaligned 64 bits access when packed.
0233:                int capacity = isPacked() ? (((size & 0x7) == 0) ? size : size
0234:                        + 8 - (size & 0x7)) : size;
0235:                ByteBuffer bf = ByteBuffer.allocateDirect(capacity);
0236:                bf.order(byteOrder());
0237:                setByteBuffer(bf, 0);
0238:                return _byteBuffer;
0239:            }
0240:
0241:            /**
0242:             * Sets the current byte buffer for this struct.
0243:             * The specified byte buffer can be mapped to memory for direct memory
0244:             * access or can wrap a shared byte array for I/O purpose 
0245:             * (e.g. <code>DatagramPacket</code>).
0246:             *
0247:             * @param byteBuffer the new byte buffer.
0248:             * @param position the position of this struct in the specified byte buffer.
0249:             * @return <code>this</code>
0250:             * @throws IllegalArgumentException if the specified byteBuffer has a 
0251:             *         different byte order than this struct. 
0252:             * @throws UnsupportedOperationException if this struct is an inner struct.
0253:             * @see #byteOrder() 
0254:             */
0255:            public final Struct setByteBuffer(ByteBuffer byteBuffer,
0256:                    int position) {
0257:                if (byteBuffer.order() != byteOrder())
0258:                    throw new IllegalArgumentException(
0259:                            "The byte order of the specified byte buffer"
0260:                                    + " is different from this struct byte order");
0261:                if (_outer != null)
0262:                    throw new UnsupportedOperationException(
0263:                            "Inner struct byte buffer is inherited from outer");
0264:                _byteBuffer = byteBuffer;
0265:                _outerOffset = position;
0266:                return this ;
0267:            }
0268:
0269:            /**
0270:             * Sets the position of this struct within its byte buffer.
0271:             *
0272:             * @param position the position of this struct in its byte buffer.
0273:             * @return <code>this</code>
0274:             * @throws UnsupportedOperationException if this struct is an inner struct.
0275:             */
0276:            public final Struct setByteBufferPosition(int position) {
0277:                return setByteBuffer(this .getByteBuffer(), position);
0278:            }
0279:
0280:            /**
0281:             * Returns the absolute position of this struct within its associated 
0282:             * {@link #getByteBuffer byte buffer}.
0283:             *
0284:             * @return the absolute position of this struct in the byte buffer. 
0285:             */
0286:            public final int getByteBufferPosition() {
0287:                return (_outer != null) ? _outer.getByteBufferPosition()
0288:                        + _outerOffset : _outerOffset;
0289:            }
0290:
0291:            /**
0292:             * Reads this struct from the specified input stream  
0293:             * (convenience method when using Stream I/O). For better performance,
0294:             * use of Block I/O (e.g. <code>java.nio.channels.*</code>) is recommended.
0295:             *
0296:             * @param in the input stream being read from.
0297:             * @return the number of bytes read (typically the {@link #size() size}
0298:             *         of this struct.
0299:             * @throws IOException if an I/O error occurs.
0300:             */
0301:            public int read(InputStream in) throws IOException {
0302:                ByteBuffer buffer = getByteBuffer();
0303:                if (buffer.hasArray()) {
0304:                    int offset = buffer.arrayOffset() + getByteBufferPosition();
0305:                    return in.read(buffer.array(), offset, size());
0306:                } else {
0307:                    synchronized (buffer) {
0308:                        if (_bytes == null) {
0309:                            _bytes = new byte[size()];
0310:                        }
0311:                        int bytesRead = in.read(_bytes);
0312:                        buffer.position(getByteBufferPosition());
0313:                        buffer.put(_bytes);
0314:                        return bytesRead;
0315:                    }
0316:                }
0317:            }
0318:
0319:            /**
0320:             * Writes this struct to the specified output stream  
0321:             * (convenience method when using Stream I/O). For better performance,
0322:             * use of Block I/O (e.g. <code>java.nio.channels.*</code>) is recommended.
0323:             *
0324:             * @param out the output stream to write to.
0325:             * @throws IOException if an I/O error occurs.
0326:             */
0327:            public void write(OutputStream out) throws IOException {
0328:                ByteBuffer buffer = getByteBuffer();
0329:                if (buffer.hasArray()) {
0330:                    int offset = buffer.arrayOffset() + getByteBufferPosition();
0331:                    out.write(buffer.array(), offset, size());
0332:                } else {
0333:                    synchronized (buffer) {
0334:                        if (_bytes == null) {
0335:                            _bytes = new byte[size()];
0336:                        }
0337:                        buffer.position(getByteBufferPosition());
0338:                        buffer.get(_bytes);
0339:                        out.write(_bytes);
0340:                    }
0341:                }
0342:            }
0343:
0344:            /**
0345:             * Returns this struct address. This method allows for structs 
0346:             * to be referenced (e.g. pointer) from other structs.
0347:             *
0348:             * @return the struct memory address.
0349:             * @throws UnsupportedOperationException if the struct buffer is not 
0350:             *         a direct buffer.
0351:             * @see    Reference32
0352:             * @see    Reference64
0353:             */
0354:            public final long address() {
0355:                ByteBuffer this Buffer = this .getByteBuffer();
0356:                if (ADDRESS_METHOD != null) {
0357:                    Long start = (Long) ADDRESS_METHOD.invoke(this Buffer);
0358:                    return start.longValue() + getByteBufferPosition();
0359:                } else {
0360:                    throw new UnsupportedOperationException(
0361:                            "Operation not supported for "
0362:                                    + this Buffer.getClass());
0363:                }
0364:            }
0365:
0366:            private static final Reflection.Method ADDRESS_METHOD = Reflection
0367:                    .getMethod("sun.nio.ch.DirectBuffer.address()");
0368:
0369:            /**
0370:             * Returns the <code>String</code> representation of this struct
0371:             * in the form of its constituing bytes (hexadecimal). For example:[code]
0372:             *     public static class Student extends Struct {
0373:             *         Utf8String name  = new Utf8String(16);
0374:             *         Unsigned16 year  = new Unsigned16();
0375:             *         Float32    grade = new Float32();
0376:             *     }
0377:             *     Student student = new Student();
0378:             *     student.name.set("John Doe");
0379:             *     student.year.set(2003);
0380:             *     student.grade.set(12.5f);
0381:             *     System.out.println(student);
0382:             *
0383:             *     4A 6F 68 6E 20 44 6F 65 00 00 00 00 00 00 00 00
0384:             *     07 D3 00 00 41 48 00 00[/code]
0385:             *
0386:             * @return a hexadecimal representation of the bytes content for this 
0387:             *         struct.
0388:             */
0389:            public String toString() {
0390:                final int size = size();
0391:                StringBuffer sb = new StringBuffer(size * 3);
0392:                final ByteBuffer buffer = getByteBuffer();
0393:                final int start = getByteBufferPosition();
0394:                for (int i = 0; i < size; i++) {
0395:                    int b = buffer.get(start + i) & 0xFF;
0396:                    sb.append(HEXA[b >> 4]);
0397:                    sb.append(HEXA[b & 0xF]);
0398:                    sb.append(((i & 0xF) == 0xF) ? '\n' : ' ');
0399:                }
0400:                return sb.toString();
0401:            }
0402:
0403:            private static final char[] HEXA = { '0', '1', '2', '3', '4', '5',
0404:                    '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0405:
0406:            ///////////////////
0407:            // CONFIGURATION //
0408:            ///////////////////
0409:
0410:            /**
0411:             * Indicates if this struct's members are mapped to the same location
0412:             * in memory (default <code>false</code>). This method is useful for
0413:             * applications extending {@link Struct} with new member types in order to 
0414:             * create unions from these new structs. For example:[code]
0415:             * public abstract class FortranStruct extends Struct {
0416:             *     public class FortranString extends Member {...}
0417:             *     protected FortranString[] array(FortranString[] array, int stringLength) { ... }
0418:             * }
0419:             * public abstract class FortranUnion extends FortranStruct {
0420:             *     // Inherits new members and methods.
0421:             *     public final isUnion() {
0422:             *         return true;
0423:             *     }
0424:             * }[/code]
0425:             *
0426:             * @return <code>true</code> if this struct's members are mapped to 
0427:             *         to the same location in memory; <code>false</code> 
0428:             *         otherwise.
0429:             * @see Union
0430:             */
0431:            public boolean isUnion() {
0432:                return false;
0433:            }
0434:
0435:            /**
0436:             * Returns the byte order for this struct (configurable). 
0437:             * The byte order is inherited by inner structs. Sub-classes may change 
0438:             * the byte order by overriding this method. For example:[code]
0439:             * public class TopStruct extends Struct {
0440:             *     ... // Members initialization.
0441:             *     public ByteOrder byteOrder() {
0442:             *         // TopStruct and its inner structs use hardware byte order.
0443:             *         return ByteOrder.nativeOrder();
0444:             *    }
0445:             * }}[/code]</p></p>
0446:             *
0447:             * @return the byte order when reading/writing multibyte values
0448:             *         (default: network byte order, <code>BIG_ENDIAN</code>).
0449:             */
0450:            public ByteOrder byteOrder() {
0451:                return (_outer != null) ? _outer.byteOrder()
0452:                        : ByteOrder.BIG_ENDIAN;
0453:            }
0454:
0455:            /**
0456:             * Indicates if this struct is packed (configurable).
0457:             * By default, {@link Member members} of a struct are aligned on the
0458:             * boundary corresponding to the member base type; padding is performed
0459:             * if necessary. This directive is inherited by inner structs.
0460:             * Sub-classes may change the packing directive by overriding this method.
0461:             * For example:[code]
0462:             * public class TopStruct extends Struct {
0463:             *     ... // Members initialization.
0464:             *     public boolean isPacked() {
0465:             *         // TopStruct and its inner structs are packed.
0466:             *         return true;
0467:             *     }
0468:             * }}[/code]
0469:             *
0470:             * @return <code>true</code> if alignment requirements are ignored.
0471:             *         <code>false</code> otherwise (default).
0472:             */
0473:            public boolean isPacked() {
0474:                return (_outer != null) ? _outer.isPacked() : false;
0475:            }
0476:
0477:            /**
0478:             * Defines the specified struct as inner of this struct.
0479:             *
0480:             * @param struct the inner struct.
0481:             * @return the specified struct. 
0482:             * @throws IllegalArgumentException if the specified struct is already 
0483:             *         an inner struct.
0484:             */
0485:            protected/* <S extends Struct> S*/Struct inner(/*S*/Struct struct) {
0486:                if (struct._outer != null)
0487:                    throw new IllegalArgumentException(
0488:                            "struct: Already an inner struct");
0489:                struct._outer = this ;
0490:                final int bitSize = struct.size() << 3;
0491:                updateIndexes(struct._alignment, bitSize, bitSize);
0492:                struct._outerOffset = (_bitIndex - bitSize) >> 3;
0493:                return (/*S*/Struct) struct;
0494:            }
0495:
0496:            /**
0497:             * Defines the specified array of structs as inner structs. 
0498:             * The array is populated if necessary using the struct component
0499:             * default constructor (which must be public).
0500:             *
0501:             * @param structs the struct array.
0502:             * @return the specified struct array. 
0503:             * @throws IllegalArgumentException if the specified array contains 
0504:             *         inner structs.
0505:             */
0506:            protected/* <S extends Struct> S*/Struct[] array(
0507:                    /*S*/Struct[] structs) {
0508:                Class structClass = null;
0509:                boolean resetIndexSaved = _resetIndex;
0510:                if (_resetIndex) {
0511:                    _bitIndex = 0;
0512:                    _resetIndex = false; // Ensures the array elements are sequential.
0513:                }
0514:                for (int i = 0; i < structs.length;) {
0515:                    /*S*/Struct struct = structs[i];
0516:                    if (struct == null) {
0517:                        try {
0518:                            if (structClass == null) {
0519:                                String arrayName = structs.getClass().getName();
0520:                                String structName = arrayName.substring(2,
0521:                                        arrayName.length() - 1);
0522:                                structClass = Reflection.getClass(structName);
0523:                                if (structClass == null)
0524:                                    throw new JavolutionError("Struct class: "
0525:                                            + structName + " not found");
0526:                            }
0527:                            struct = (/*S*/Struct) structClass.newInstance();
0528:                        } catch (Exception e) {
0529:                            throw new JavolutionError(e);
0530:                        }
0531:                    }
0532:                    structs[i++] = inner(struct);
0533:                }
0534:                _resetIndex = resetIndexSaved;
0535:                return (/*S*/Struct[]) structs;
0536:            }
0537:
0538:            /**
0539:             * Defines the specified two-dimensional array of structs as inner
0540:             * structs. The array is populated if necessary using the struct component 
0541:             * default constructor (which must be public).
0542:             *
0543:             * @param structs the two dimensional struct array.
0544:             * @return the specified struct array. 
0545:             * @throws IllegalArgumentException if the specified array contains 
0546:             *         inner structs.
0547:             */
0548:            protected/* <S extends Struct> S*/Struct[][] array(
0549:            /*S*/Struct[][] structs) {
0550:                boolean resetIndexSaved = _resetIndex;
0551:                if (_resetIndex) {
0552:                    _bitIndex = 0;
0553:                    _resetIndex = false; // Ensures the array elements are sequential.
0554:                }
0555:                for (int i = 0; i < structs.length; i++) {
0556:                    array(structs[i]);
0557:                }
0558:                _resetIndex = resetIndexSaved;
0559:                return (/*S*/Struct[][]) structs;
0560:            }
0561:
0562:            /**
0563:             * Defines the specified three dimensional array of structs as inner 
0564:             * structs. The array is populated if necessary using the struct component 
0565:             * default constructor (which must be public).
0566:             *
0567:             * @param structs the three dimensional struct array.
0568:             * @return the specified struct array.
0569:             * @throws IllegalArgumentException if the specified array contains 
0570:             *         inner structs.
0571:             */
0572:            protected/* <S extends Struct> S*/Struct[][][] array(
0573:            /*S*/Struct[][][] structs) {
0574:                boolean resetIndexSaved = _resetIndex;
0575:                if (_resetIndex) {
0576:                    _bitIndex = 0;
0577:                    _resetIndex = false; // Ensures the array elements are sequential.
0578:                }
0579:                for (int i = 0; i < structs.length; i++) {
0580:                    array(structs[i]);
0581:                }
0582:                _resetIndex = resetIndexSaved;
0583:                return (/*S*/Struct[][][]) structs;
0584:            }
0585:
0586:            /**
0587:             * Defines the specified array member. For predefined members, 
0588:             * the array is populated when empty; custom members should use 
0589:             * literal (populated) arrays.
0590:             *
0591:             * @param  arrayMember the array member.
0592:             * @return the specified array member.
0593:             * @throws UnsupportedOperationException if the specified array 
0594:             *         is empty and the member type is unknown. 
0595:             */
0596:            protected/* <M extends Member> M*/Member[] array(
0597:            /*M*/Member[] arrayMember) {
0598:                boolean resetIndexSaved = _resetIndex;
0599:                if (_resetIndex) {
0600:                    _bitIndex = 0;
0601:                    _resetIndex = false; // Ensures the array elements are sequential.
0602:                }
0603:                if (BOOL.isInstance(arrayMember)) {
0604:                    for (int i = 0; i < arrayMember.length;)
0605:                        arrayMember[i++] = (/*M*/Member) this .new Bool();
0606:                } else if (SIGNED_8.isInstance(arrayMember)) {
0607:                    for (int i = 0; i < arrayMember.length;)
0608:                        arrayMember[i++] = (/*M*/Member) this .new Signed8();
0609:                } else if (UNSIGNED_8.isInstance(arrayMember)) {
0610:                    for (int i = 0; i < arrayMember.length;)
0611:                        arrayMember[i++] = (/*M*/Member) this .new Unsigned8();
0612:                } else if (SIGNED_16.isInstance(arrayMember)) {
0613:                    for (int i = 0; i < arrayMember.length;)
0614:                        arrayMember[i++] = (/*M*/Member) this .new Signed16();
0615:                } else if (UNSIGNED_16.isInstance(arrayMember)) {
0616:                    for (int i = 0; i < arrayMember.length;)
0617:                        arrayMember[i++] = (/*M*/Member) this .new Unsigned16();
0618:                } else if (SIGNED_32.isInstance(arrayMember)) {
0619:                    for (int i = 0; i < arrayMember.length;)
0620:                        arrayMember[i++] = (/*M*/Member) this .new Signed32();
0621:                } else if (UNSIGNED_32.isInstance(arrayMember)) {
0622:                    for (int i = 0; i < arrayMember.length;)
0623:                        arrayMember[i++] = (/*M*/Member) this .new Unsigned32();
0624:                } else if (SIGNED_64.isInstance(arrayMember)) {
0625:                    for (int i = 0; i < arrayMember.length;)
0626:                        arrayMember[i++] = (/*M*/Member) this .new Signed64();
0627:                } else if (FLOAT_32.isInstance(arrayMember)) {
0628:                    for (int i = 0; i < arrayMember.length;)
0629:                        arrayMember[i++] = (/*M*/Member) this .new Float32();
0630:                } else if (FLOAT_64.isInstance(arrayMember)) {
0631:                    for (int i = 0; i < arrayMember.length;)
0632:                        arrayMember[i++] = (/*M*/Member) this .new Float64();
0633:                } else {
0634:                    throw new UnsupportedOperationException(
0635:                            "Cannot create member elements, the arrayMember should "
0636:                                    + "contain the member instances instead of null");
0637:                }
0638:                _resetIndex = resetIndexSaved;
0639:                return (/*M*/Member[]) arrayMember;
0640:            }
0641:
0642:            private static final Class BOOL = new Bool[0].getClass();
0643:
0644:            private static final Class SIGNED_8 = new Signed8[0].getClass();
0645:
0646:            private static final Class UNSIGNED_8 = new Unsigned8[0].getClass();
0647:
0648:            private static final Class SIGNED_16 = new Signed16[0].getClass();
0649:
0650:            private static final Class UNSIGNED_16 = new Unsigned16[0]
0651:                    .getClass();
0652:
0653:            private static final Class SIGNED_32 = new Signed32[0].getClass();
0654:
0655:            private static final Class UNSIGNED_32 = new Unsigned32[0]
0656:                    .getClass();
0657:
0658:            private static final Class SIGNED_64 = new Signed64[0].getClass();
0659:
0660:            private static final Class FLOAT_32 = new Float32[0].getClass();
0661:
0662:            private static final Class FLOAT_64 = new Float64[0].getClass();
0663:
0664:            /**
0665:             * Defines the specified two-dimensional array member. For predefined
0666:             * members, the array is populated when empty; custom members should use 
0667:             * literal (populated) arrays.
0668:             *
0669:             * @param  arrayMember the two-dimensional array member.
0670:             * @return the specified array member.
0671:             * @throws UnsupportedOperationException if the specified array 
0672:             *         is empty and the member type is unknown. 
0673:             */
0674:            protected/* <M extends Member> M*/Member[][] array(
0675:            /*M*/Member[][] arrayMember) {
0676:                boolean resetIndexSaved = _resetIndex;
0677:                if (_resetIndex) {
0678:                    _bitIndex = 0;
0679:                    _resetIndex = false; // Ensures the array elements are sequential.
0680:                }
0681:                for (int i = 0; i < arrayMember.length; i++) {
0682:                    array(arrayMember[i]);
0683:                }
0684:                _resetIndex = resetIndexSaved;
0685:                return (/*M*/Member[][]) arrayMember;
0686:            }
0687:
0688:            /**
0689:             * Defines the specified three-dimensional array member. For predefined
0690:             * members, the array is populated when empty; custom members should use 
0691:             * literal (populated) arrays.
0692:             *
0693:             * @param  arrayMember the three-dimensional array member.
0694:             * @return the specified array member.
0695:             * @throws UnsupportedOperationException if the specified array 
0696:             *         is empty and the member type is unknown. 
0697:             */
0698:            protected/* <M extends Member> M*/Member[][][] array(
0699:            /*M*/Member[][][] arrayMember) {
0700:                boolean resetIndexSaved = _resetIndex;
0701:                if (_resetIndex) {
0702:                    _bitIndex = 0;
0703:                    _resetIndex = false; // Ensures the array elements are sequential.
0704:                }
0705:                for (int i = 0; i < arrayMember.length; i++) {
0706:                    array(arrayMember[i]);
0707:                }
0708:                _resetIndex = resetIndexSaved;
0709:                return (/*M*/Member[][][]) arrayMember;
0710:            }
0711:
0712:            /**
0713:             * Defines the specified array of UTF-8 strings, all strings having the 
0714:             * specified length (convenience method).
0715:             *
0716:             * @param  array the string array.
0717:             * @param stringLength the length of the string elements.
0718:             * @return the specified string array.
0719:             */
0720:            protected UTF8String[] array(UTF8String[] array, int stringLength) {
0721:                for (int i = 0; i < array.length; i++) {
0722:                    array[i] = new UTF8String(stringLength);
0723:                }
0724:                return array;
0725:            }
0726:
0727:            /**
0728:             * Updates this struct indexes after adding a member with the 
0729:             * specified constraints.
0730:             *
0731:             * @param  alignment  the desired alignment in bytes.
0732:             * @param  nbrOfBits  the size in bits.
0733:             * @param  capacity   the word size maximum capacity in bits
0734:             *                    (equal to nbrOfBits for non-bitfields).
0735:             * @return offset the offset of the member.
0736:             * @throws IllegalArgumentException if
0737:             *         <code>nbrOfBits &gt; capacity</code>
0738:             */
0739:            private int updateIndexes(int alignment, int nbrOfBits, int capacity) {
0740:                if (nbrOfBits > capacity) {
0741:                    throw new IllegalArgumentException("nbrOfBits: "
0742:                            + nbrOfBits + " exceeds capacity: " + capacity);
0743:                }
0744:
0745:                // Resets index if union.
0746:                if (_resetIndex) {
0747:                    _bitIndex = 0;
0748:                }
0749:
0750:                // Caculates offset based on alignment constraints.
0751:                alignment = isPacked() ? 1 : alignment;
0752:                int offset = (_bitIndex / (alignment << 3)) * alignment;
0753:
0754:                // Calculates bits already used from the offset position.
0755:                int usedBits = _bitIndex - (offset << 3);
0756:
0757:                // Checks if bits can be adjacents. 
0758:                // A bit size of 0 forces realignment, ref. C/C++ Standard.
0759:                if ((capacity < usedBits + nbrOfBits)
0760:                        || ((nbrOfBits == 0) && (usedBits != 0))) {
0761:                    // Padding to next alignment boundary.
0762:                    offset += alignment;
0763:                    _bitIndex = (offset << 3) + nbrOfBits;
0764:                } else { // Adjacent bits.
0765:                    _bitIndex += nbrOfBits;
0766:                }
0767:
0768:                // Updates bits used (for size calculation).
0769:                if (_bitsUsed < _bitIndex) {
0770:                    _bitsUsed = _bitIndex;
0771:                }
0772:
0773:                // Updates Struct's alignment.
0774:                if (_alignment < alignment) {
0775:                    _alignment = MathLib.min(alignment,
0776:                            ((Integer) MAXIMUM_ALIGNMENT.get()).intValue());
0777:                }
0778:                return offset;
0779:            }
0780:
0781:            /////////////
0782:            // MEMBERS //
0783:            /////////////
0784:
0785:            /**
0786:             * This inner class represents the base class for all {@link Struct}
0787:             * members. It allows applications to define additional member types.
0788:             * For example:[code]
0789:             *    public class MyStruct extends Struct {
0790:             *        BitSet bits = new BitSet(256);
0791:             *        ...
0792:             *        public BitSet extends Member {
0793:             *            public BitSet(int nbrBits) {
0794:             *                super(1, (nbrBits+7)>>3);
0795:             *            }
0796:             *            public boolean get(int i) { ... }
0797:             *            public void set(int i, boolean value) { ...}
0798:             *        }
0799:             *    }[/code]
0800:             */
0801:            protected class Member {
0802:
0803:                /**
0804:                 * Holds the relative offset of this member within its struct.
0805:                 */
0806:                private final int _offset;
0807:
0808:                /**
0809:                 * Base constructor for custom member types.
0810:                 *
0811:                 * @param  alignment the desired alignment in bytes.
0812:                 * @param  size the size of this member in bytes.
0813:                 */
0814:                protected Member(int alignment, int size) {
0815:                    final int nbrOfBits = size << 3;
0816:                    _offset = updateIndexes(alignment, nbrOfBits, nbrOfBits);
0817:                }
0818:
0819:                /**
0820:                 * Base constructor for predefined member types with bit fields.
0821:                 *
0822:                 * @param  alignment  the desired alignment in bytes.
0823:                 * @param  nbrOfBits  the size in bits.
0824:                 * @param  capacity   the word size maximum capacity in bits
0825:                 *                    (equal to nbrOfBits for non-bitfields).
0826:                 */
0827:                Member(int alignment, int nbrOfBits, int capacity) {
0828:                    _offset = updateIndexes(alignment, nbrOfBits, capacity);
0829:                }
0830:
0831:                /**
0832:                 * Returns the outer {@link Struct struct} container.
0833:                 *
0834:                 * @return the outer struct.
0835:                 */
0836:                public final Struct struct() {
0837:                    return Struct.this ;
0838:                }
0839:
0840:                /**
0841:                 * Returns the relative offset of this member within its struct.
0842:                 *
0843:                 * @return the relative offset in bytes.
0844:                 */
0845:                public final int offset() {
0846:                    return _offset;
0847:                }
0848:
0849:                /**
0850:                 * Returns the absolute position of this member in the 
0851:                 * byte buffer.
0852:                 *
0853:                 * @return the byte buffer position.
0854:                 */
0855:                public final int position() {
0856:                    return getByteBufferPosition() + _offset;
0857:                }
0858:            }
0859:
0860:            ///////////////////////
0861:            // PREDEFINED FIELDS //
0862:            ///////////////////////
0863:
0864:            /**
0865:             * This class represents a UTF-8 character string, null terminated
0866:             * (for C/C++ compatibility)
0867:             */
0868:            public class UTF8String extends Member {
0869:                private final UTF8ByteBufferWriter _writer = new UTF8ByteBufferWriter();
0870:
0871:                private final UTF8ByteBufferReader _reader = new UTF8ByteBufferReader();
0872:
0873:                private final char[] _chars;
0874:
0875:                private final int _length;
0876:
0877:                public UTF8String(int length) {
0878:                    super (1, length);
0879:                    _length = length; // Takes into account 0 terminator.
0880:                    _chars = new char[length];
0881:                }
0882:
0883:                public void set(String string) {
0884:                    final ByteBuffer buffer = getByteBuffer();
0885:                    synchronized (buffer) {
0886:                        try {
0887:                            buffer.position(position());
0888:                            _writer.setOutput(buffer);
0889:                            if (string.length() < _length) {
0890:                                _writer.write(string);
0891:                                _writer.write(0); // Marks end of string.
0892:                            } else if (string.length() > _length) { // Truncates.
0893:                                _writer.write(string.substring(0, _length));
0894:                            } else { // Exact same length.
0895:                                _writer.write(string);
0896:                            }
0897:                        } catch (IOException e) {
0898:                            throw new JavolutionError(e);
0899:                        } finally {
0900:                            _writer.reset();
0901:                        }
0902:                    }
0903:                }
0904:
0905:                public String get() {
0906:                    final ByteBuffer buffer = getByteBuffer();
0907:                    synchronized (buffer) {
0908:                        try {
0909:                            buffer.position(position());
0910:                            _reader.setInput(buffer);
0911:                            for (int i = 0; i < _length;) {
0912:                                char c = (char) _reader.read();
0913:                                if (c == 0) { // Null terminator.
0914:                                    return new String(_chars, 0, i);
0915:                                } else {
0916:                                    _chars[i++] = c;
0917:                                }
0918:                            }
0919:                            return new String(_chars, 0, _length);
0920:                        } catch (IOException e) {
0921:                            throw new JavolutionError(e);
0922:                        } finally {
0923:                            _reader.reset();
0924:                        }
0925:                    }
0926:                }
0927:            }
0928:
0929:            /**
0930:             * This class represents a 8 bits boolean with <code>true</code> represented
0931:             * by <code>1</code> and <code>false</code> represented by <code>0</code>.
0932:             */
0933:            public class Bool extends Member {
0934:                private final int _mask;
0935:
0936:                private final int _shift;
0937:
0938:                public Bool() {
0939:                    this (8);
0940:                }
0941:
0942:                public Bool(int nbrOfBits) {
0943:                    super (1, nbrOfBits, 8);
0944:                    final int startBit = offset() << 3;
0945:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 8
0946:                            - _bitIndex + startBit : _bitIndex - startBit
0947:                            - nbrOfBits;
0948:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
0949:                }
0950:
0951:                public boolean get() {
0952:                    return (getByteBuffer().get(position()) & _mask) != 0;
0953:                }
0954:
0955:                public void set(boolean value) {
0956:                    if (_mask == 0xFF) { // Non bit-field.
0957:                        getByteBuffer().put(position(), (byte) (value ? 1 : 0));
0958:                    } else { // Bit-field.
0959:                        int prevCleared = getByteBuffer().get(position())
0960:                                & (~_mask);
0961:                        if (value) {
0962:                            getByteBuffer().put(position(),
0963:                                    (byte) (prevCleared | (1 << _shift)));
0964:                        } else {
0965:                            getByteBuffer().put(position(),
0966:                                    (byte) (prevCleared));
0967:                        }
0968:                    }
0969:                }
0970:            }
0971:
0972:            /**
0973:             * This class represents a 8 bits signed integer.
0974:             */
0975:            public class Signed8 extends Member {
0976:                private final int _mask;
0977:
0978:                private final int _shift;
0979:
0980:                private final int _signShift;
0981:
0982:                public Signed8() {
0983:                    this (8);
0984:                }
0985:
0986:                public Signed8(int nbrOfBits) {
0987:                    super (1, nbrOfBits, 8);
0988:                    final int startBit = offset() << 3;
0989:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 8
0990:                            - _bitIndex + startBit : _bitIndex - startBit
0991:                            - nbrOfBits;
0992:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
0993:                    _signShift = 32 - _shift - nbrOfBits;
0994:                }
0995:
0996:                public byte get() {
0997:                    if (_mask == 0xFF) { // Non bit-field.
0998:                        return getByteBuffer().get(position());
0999:                    } else { // Bit-field.
1000:                        int value = getByteBuffer().get(position());
1001:                        value &= _mask;
1002:                        value <<= _signShift;
1003:                        value >>= _signShift + _shift; // Keeps sign.
1004:                        return (byte) value;
1005:                    }
1006:                }
1007:
1008:                public void set(byte value) {
1009:                    if (_mask == 0xFF) { // Non bit-field.
1010:                        getByteBuffer().put(position(), value);
1011:                    } else { // Bit-field.
1012:                        value <<= _shift;
1013:                        value &= _mask;
1014:                        int orMask = getByteBuffer().get(position()) & (~_mask);
1015:                        getByteBuffer()
1016:                                .put(position(), (byte) (orMask | value));
1017:                    }
1018:                }
1019:            }
1020:
1021:            /**
1022:             * This class represents a 8 bits unsigned integer.
1023:             */
1024:            public class Unsigned8 extends Member {
1025:                private final int _shift;
1026:
1027:                private final int _mask;
1028:
1029:                public Unsigned8() {
1030:                    this (8);
1031:                }
1032:
1033:                public Unsigned8(int nbrOfBits) {
1034:                    super (1, nbrOfBits, 8);
1035:                    final int startBit = offset() << 3;
1036:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 8
1037:                            - _bitIndex + startBit : _bitIndex - startBit
1038:                            - nbrOfBits;
1039:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
1040:                }
1041:
1042:                public short get() {
1043:                    int value = getByteBuffer().get(position());
1044:                    return (short) ((value & _mask) >>> _shift);
1045:                }
1046:
1047:                public void set(short value) {
1048:                    if (_mask == 0xFF) { // Non bit-field.
1049:                        getByteBuffer().put(position(), (byte) value);
1050:                    } else { // Bit-field.
1051:                        value <<= _shift;
1052:                        value &= _mask;
1053:                        int orMask = getByteBuffer().get(position()) & (~_mask);
1054:                        getByteBuffer()
1055:                                .put(position(), (byte) (orMask | value));
1056:                    }
1057:                }
1058:            }
1059:
1060:            /**
1061:             * This class represents a 16 bits signed integer.
1062:             */
1063:            public class Signed16 extends Member {
1064:                private final int _mask;
1065:
1066:                private final int _shift;
1067:
1068:                private final int _signShift;
1069:
1070:                public Signed16() {
1071:                    this (16);
1072:                }
1073:
1074:                public Signed16(int nbrOfBits) {
1075:                    super (2, nbrOfBits, 16);
1076:                    final int startBit = offset() << 3;
1077:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 16
1078:                            - _bitIndex + startBit : _bitIndex - startBit
1079:                            - nbrOfBits;
1080:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
1081:                    _signShift = 32 - _shift - nbrOfBits;
1082:                }
1083:
1084:                public short get() {
1085:                    if (_mask == 0xFFFF) { // Non bit-field.
1086:                        return getByteBuffer().getShort(position());
1087:                    } else { // Bit-field.
1088:                        int value = getByteBuffer().getShort(position());
1089:                        value &= _mask;
1090:                        value <<= _signShift;
1091:                        value >>= _signShift + _shift; // Keeps sign.
1092:                        return (short) value;
1093:                    }
1094:                }
1095:
1096:                public void set(short value) {
1097:                    if (_mask == 0xFFFF) { // Non bit-field.
1098:                        getByteBuffer().putShort(position(), value);
1099:                    } else { // Bit-field.
1100:                        value <<= _shift;
1101:                        value &= _mask;
1102:                        int orMask = getByteBuffer().getShort(position())
1103:                                & (~_mask);
1104:                        getByteBuffer().putShort(position(),
1105:                                (short) (orMask | value));
1106:                    }
1107:                }
1108:            }
1109:
1110:            /**
1111:             * This class represents a 16 bits unsigned integer.
1112:             */
1113:            public class Unsigned16 extends Member {
1114:                private final int _shift;
1115:
1116:                private final int _mask;
1117:
1118:                public Unsigned16() {
1119:                    this (16);
1120:                }
1121:
1122:                public Unsigned16(int nbrOfBits) {
1123:                    super (2, nbrOfBits, 16);
1124:                    final int startBit = offset() << 3;
1125:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 16
1126:                            - _bitIndex + startBit : _bitIndex - startBit
1127:                            - nbrOfBits;
1128:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
1129:                }
1130:
1131:                public int get() {
1132:                    int value = getByteBuffer().getShort(position());
1133:                    return (value & _mask) >>> _shift;
1134:                }
1135:
1136:                public void set(int value) {
1137:                    if (_mask == 0xFFFF) { // Non bit-field.
1138:                        getByteBuffer().putShort(position(), (short) value);
1139:                    } else { // Bit-field.
1140:                        value <<= _shift;
1141:                        value &= _mask;
1142:                        int orMask = getByteBuffer().getShort(position())
1143:                                & (~_mask);
1144:                        getByteBuffer().putShort(position(),
1145:                                (short) (orMask | value));
1146:                    }
1147:                }
1148:            }
1149:
1150:            /**
1151:             * This class represents a 32 bits signed integer.
1152:             */
1153:            public class Signed32 extends Member {
1154:                private final int _mask;
1155:
1156:                private final int _shift;
1157:
1158:                private final int _signShift;
1159:
1160:                public Signed32() {
1161:                    this (32);
1162:                }
1163:
1164:                public Signed32(int nbrOfBits) {
1165:                    super (4, nbrOfBits, 32);
1166:                    final int startBit = offset() << 3;
1167:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 32
1168:                            - _bitIndex + startBit : _bitIndex - startBit
1169:                            - nbrOfBits;
1170:                    _mask = (nbrOfBits == 32) ? 0xFFFFFFFF
1171:                            : ((1 << nbrOfBits) - 1) << _shift;
1172:                    _signShift = 32 - _shift - nbrOfBits;
1173:                }
1174:
1175:                public int get() {
1176:                    if (_mask == 0xFFFFFFFF) { // Non bit-field.
1177:                        return getByteBuffer().getInt(position());
1178:                    } else { // Bit-field.
1179:                        int value = getByteBuffer().getInt(position());
1180:                        value &= _mask;
1181:                        value <<= _signShift;
1182:                        value >>= _signShift + _shift; // Keeps sign.
1183:                        return value;
1184:                    }
1185:                }
1186:
1187:                public void set(int value) {
1188:                    if (_mask == 0xFFFFFFFF) { // Non bit-field.
1189:                        getByteBuffer().putInt(position(), value);
1190:                    } else { // Bit-field.
1191:                        value <<= _shift;
1192:                        value &= _mask;
1193:                        int orMask = getByteBuffer().getInt(position())
1194:                                & (~_mask);
1195:                        getByteBuffer().putInt(position(), orMask | value);
1196:                    }
1197:                }
1198:            }
1199:
1200:            /**
1201:             * This class represents a 32 bits unsigned integer.
1202:             */
1203:            public class Unsigned32 extends Member {
1204:                private final int _shift;
1205:
1206:                private final long _mask;
1207:
1208:                public Unsigned32() {
1209:                    this (32);
1210:                }
1211:
1212:                public Unsigned32(int nbrOfBits) {
1213:                    super (4, nbrOfBits, 32);
1214:                    final int startBit = offset() << 3;
1215:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 32
1216:                            - _bitIndex + startBit : _bitIndex - startBit
1217:                            - nbrOfBits;
1218:                    _mask = (nbrOfBits == 32) ? 0xFFFFFFFFl
1219:                            : ((1l << nbrOfBits) - 1l) << _shift;
1220:                }
1221:
1222:                public long get() {
1223:                    int value = getByteBuffer().getInt(position());
1224:                    return (value & _mask) >>> _shift;
1225:                }
1226:
1227:                public void set(long value) {
1228:                    if (_mask == 0xFFFFFFFF) { // Non bit-field.
1229:                        getByteBuffer().putInt(position(), (int) value);
1230:                    } else { // Bit-field.
1231:                        value <<= _shift;
1232:                        value &= _mask;
1233:                        int orMask = getByteBuffer().getInt(position())
1234:                                & (~(int) _mask);
1235:                        getByteBuffer().putInt(position(),
1236:                                (int) (orMask | value));
1237:                    }
1238:                }
1239:            }
1240:
1241:            /**
1242:             * This class represents a 64 bits signed integer.
1243:             */
1244:            public class Signed64 extends Member {
1245:                private final long _mask;
1246:
1247:                private final int _shift;
1248:
1249:                private final int _signShift;
1250:
1251:                public Signed64() {
1252:                    this (64);
1253:                }
1254:
1255:                public Signed64(int nbrOfBits) {
1256:                    super (8, nbrOfBits, 64);
1257:                    final int startBit = offset() << 3;
1258:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 64
1259:                            - _bitIndex + startBit : _bitIndex - startBit
1260:                            - nbrOfBits;
1261:                    _mask = (nbrOfBits == 64) ? 0xFFFFFFFFFFFFFFFFl
1262:                            : ((1l << nbrOfBits) - 1l) << _shift;
1263:                    _signShift = 64 - _shift - nbrOfBits;
1264:                }
1265:
1266:                public long get() {
1267:                    if (_mask == 0xFFFFFFFFFFFFFFFFl) { // Non bit-field.
1268:                        return getByteBuffer().getLong(position());
1269:                    } else { // Bit-field.
1270:                        long value = getByteBuffer().getLong(position());
1271:                        value &= _mask;
1272:                        value <<= _signShift;
1273:                        value >>= _signShift + _shift; // Keeps sign.
1274:                        return value;
1275:                    }
1276:                }
1277:
1278:                public void set(long value) {
1279:                    if (_mask == 0xFFFFFFFFFFFFFFFFl) { // Non bit-field.
1280:                        getByteBuffer().putLong(position(), value);
1281:                    } else { // Bit-field.
1282:                        value <<= _shift;
1283:                        value &= _mask;
1284:                        long orMask = getByteBuffer().getLong(position())
1285:                                & (~_mask);
1286:                        getByteBuffer().putLong(position(), orMask | value);
1287:                    }
1288:                }
1289:            }
1290:
1291:            /**
1292:             * This class represents a 32 bits float (C/C++/Java <code>float</code>).
1293:             */
1294:            public class Float32 extends Member {
1295:                public Float32() {
1296:                    super (4, 4);
1297:                }
1298:                /*@JVM-1.1+@
1299:                 public void set(float value) {
1300:                 getByteBuffer().putFloat(position(), value);
1301:                 }
1302:
1303:                 public float get() {
1304:                 return getByteBuffer().getFloat(position());
1305:                 }
1306:                 /**/
1307:            }
1308:
1309:            /**
1310:             * This class represents a 64 bits float (C/C++/Java <code>double</code>).
1311:             */
1312:            public class Float64 extends Member {
1313:                public Float64() {
1314:                    super (8, 8);
1315:                }
1316:                /*@JVM-1.1+@
1317:                 public void set(double value) {
1318:                 getByteBuffer().putDouble(position(), value);
1319:                 }
1320:                 public double get() {
1321:                 return getByteBuffer().getDouble(position());
1322:                 }
1323:                 /**/
1324:            }
1325:
1326:            /**
1327:             * <p> This class represents a 32 bits reference (C/C++ pointer) to 
1328:             *     a {@link Struct} object (other types may require a {@link Struct}
1329:             *     wrapper).</p>
1330:             * <p> Note: For references which can be externally modified, an application
1331:             *           may want to check the {@link #isUpToDate up-to-date} status of
1332:             *           the reference. For out-of-date references, a {@link Struct}
1333:             *           can be created at the address specified by {@link #value} 
1334:             *           (using JNI) and the reference {@link #set set} accordingly.</p>
1335:             */
1336:            public class Reference32/*<S extends Struct>*/extends Member {
1337:
1338:                private/*S*/Struct _struct;
1339:
1340:                public Reference32() {
1341:                    super (4, 4);
1342:                }
1343:
1344:                public void set(/*S*/Struct struct) {
1345:                    if (struct != null) {
1346:                        getByteBuffer().putInt(position(),
1347:                                (int) struct.address());
1348:                    } else {
1349:                        getByteBuffer().putInt(position(), 0);
1350:                    }
1351:                    _struct = struct;
1352:                }
1353:
1354:                public/*S*/Struct get() {
1355:                    return _struct;
1356:                }
1357:
1358:                public int value() {
1359:                    return getByteBuffer().getInt(position());
1360:                }
1361:
1362:                public boolean isUpToDate() {
1363:                    if (_struct != null) {
1364:                        return getByteBuffer().getInt(position()) == (int) _struct
1365:                                .address();
1366:                    } else {
1367:                        return getByteBuffer().getInt(position()) == 0;
1368:                    }
1369:                }
1370:            }
1371:
1372:            /**
1373:             * <p> This class represents a 64 bits reference (C/C++ pointer) to 
1374:             *     a {@link Struct} object (other types may require a {@link Struct}
1375:             *     wrapper).</p>
1376:             * <p> Note: For references which can be externally modified, an application
1377:             *           may want to check the {@link #isUpToDate up-to-date} status of
1378:             *           the reference. For out-of-date references, a new {@link Struct}
1379:             *           can be created at the address specified by {@link #value} 
1380:             *           (using JNI) and then {@link #set set} to the reference.</p>
1381:             */
1382:            public class Reference64/*<S extends Struct>*/extends Member {
1383:                private/*S*/Struct _struct;
1384:
1385:                public Reference64() {
1386:                    super (8, 8);
1387:                }
1388:
1389:                public void set(/*S*/Struct struct) {
1390:                    if (struct != null) {
1391:                        getByteBuffer().putLong(position(), struct.address());
1392:                    } else if (struct == null) {
1393:                        getByteBuffer().putLong(position(), 0L);
1394:                    }
1395:                    _struct = struct;
1396:                }
1397:
1398:                public/*S*/Struct get() {
1399:                    return _struct;
1400:                }
1401:
1402:                public long value() {
1403:                    return getByteBuffer().getLong(position());
1404:                }
1405:
1406:                public boolean isUpToDate() {
1407:                    if (_struct != null) {
1408:                        return getByteBuffer().getLong(position()) == _struct
1409:                                .address();
1410:                    } else {
1411:                        return getByteBuffer().getLong(position()) == 0L;
1412:                    }
1413:                }
1414:            }
1415:
1416:            /**
1417:             * This class represents a 8 bits {@link Enum}.
1418:             */
1419:            public class Enum8 extends Member {
1420:                private final int _mask;
1421:
1422:                private final int _shift;
1423:
1424:                private final int _signShift;
1425:
1426:                private final List _enumValues;
1427:
1428:                public Enum8(List enumValues) {
1429:                    this (enumValues, 8);
1430:                }
1431:
1432:                public Enum8(List enumValues, int nbrOfBits) {
1433:                    super (1, nbrOfBits, 8);
1434:                    _enumValues = enumValues;
1435:                    final int startBit = offset() << 3;
1436:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 8
1437:                            - _bitIndex + startBit : _bitIndex - startBit
1438:                            - nbrOfBits;
1439:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
1440:                    _signShift = 32 - _shift - nbrOfBits;
1441:                }
1442:
1443:                public Enum get() {
1444:                    if (_mask == 0xFF) { // Non bit-field.
1445:                        return (Enum) _enumValues.get(getByteBuffer().get(
1446:                                position()));
1447:                    } else { // Bit-field.
1448:                        int value = getByteBuffer().get(position());
1449:                        value &= _mask;
1450:                        value <<= _signShift;
1451:                        value >>= _signShift + _shift; // Keeps sign.
1452:                        return (Enum) _enumValues.get(value);
1453:                    }
1454:                }
1455:
1456:                public void set(Enum e) {
1457:                    int index = e.ordinal();
1458:                    if (_enumValues.get(index) != e) {
1459:                        throw new IllegalArgumentException(
1460:                                "enum: "
1461:                                        + e
1462:                                        + ", ordinal value does not reflect enum values position");
1463:                    }
1464:                    byte value = (byte) index;
1465:                    if (_mask == 0xFF) { // Non bit-field.
1466:                        getByteBuffer().put(position(), value);
1467:                    } else { // Bit-field.
1468:                        value <<= _shift;
1469:                        value &= _mask;
1470:                        int orMask = getByteBuffer().get(position()) & (~_mask);
1471:                        getByteBuffer()
1472:                                .put(position(), (byte) (orMask | value));
1473:                    }
1474:                }
1475:            }
1476:
1477:            /**
1478:             * This class represents a 16 bits {@link Enum}.
1479:             */
1480:            public class Enum16 extends Member {
1481:                private final int _mask;
1482:
1483:                private final int _shift;
1484:
1485:                private final int _signShift;
1486:
1487:                private final List _enumValues;
1488:
1489:                public Enum16(List enumValues) {
1490:                    this (enumValues, 16);
1491:                }
1492:
1493:                public Enum16(List enumValues, int nbrOfBits) {
1494:                    super (2, nbrOfBits, 16);
1495:                    _enumValues = enumValues;
1496:                    final int startBit = offset() << 3;
1497:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 16
1498:                            - _bitIndex + startBit : _bitIndex - startBit
1499:                            - nbrOfBits;
1500:                    _mask = ((1 << nbrOfBits) - 1) << _shift;
1501:                    _signShift = 32 - _shift - nbrOfBits;
1502:                }
1503:
1504:                public Enum get() {
1505:                    if (_mask == 0xFFFF) { // Non bit-field.
1506:                        return (Enum) _enumValues.get(getByteBuffer().getShort(
1507:                                position()));
1508:                    } else { // Bit-field.
1509:                        int value = getByteBuffer().getShort(position());
1510:                        value &= _mask;
1511:                        value <<= _signShift;
1512:                        value >>= _signShift + _shift; // Keeps sign.
1513:                        return (Enum) _enumValues.get(value);
1514:                    }
1515:                }
1516:
1517:                public void set(Enum e) {
1518:                    int index = e.ordinal();
1519:                    if (_enumValues.get(index) != e) {
1520:                        throw new IllegalArgumentException(
1521:                                "enum: "
1522:                                        + e
1523:                                        + ", ordinal value does not reflect enum values position");
1524:                    }
1525:                    short value = (short) index;
1526:                    if (_mask == 0xFFFF) { // Non bit-field.
1527:                        getByteBuffer().putShort(position(), value);
1528:                    } else { // Bit-field.
1529:                        value <<= _shift;
1530:                        value &= _mask;
1531:                        int orMask = getByteBuffer().getShort(position())
1532:                                & (~_mask);
1533:                        getByteBuffer().putShort(position(),
1534:                                (short) (orMask | value));
1535:                    }
1536:                }
1537:            }
1538:
1539:            /**
1540:             * This class represents a 32 bits {@link Enum}.
1541:             */
1542:            public class Enum32 extends Member {
1543:                private final int _mask;
1544:
1545:                private final int _shift;
1546:
1547:                private final int _signShift;
1548:
1549:                private final List _enumValues;
1550:
1551:                public Enum32(List enumValues) {
1552:                    this (enumValues, 32);
1553:                }
1554:
1555:                public Enum32(List enumValues, int nbrOfBits) {
1556:                    super (4, nbrOfBits, 32);
1557:                    _enumValues = enumValues;
1558:                    final int startBit = offset() << 3;
1559:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 32
1560:                            - _bitIndex + startBit : _bitIndex - startBit
1561:                            - nbrOfBits;
1562:                    _mask = (nbrOfBits == 32) ? 0xFFFFFFFF
1563:                            : ((1 << nbrOfBits) - 1) << _shift;
1564:                    _signShift = 32 - _shift - nbrOfBits;
1565:                }
1566:
1567:                public Enum get() {
1568:                    if (_mask == 0xFFFFFFFF) { // Non bit-field.
1569:                        return (Enum) _enumValues.get(getByteBuffer().getInt(
1570:                                position()));
1571:                    } else { // Bit-field.
1572:                        int value = getByteBuffer().getInt(position());
1573:                        value &= _mask;
1574:                        value <<= _signShift;
1575:                        value >>= _signShift + _shift; // Keeps sign.
1576:                        return (Enum) _enumValues.get(value);
1577:                    }
1578:                }
1579:
1580:                public void set(Enum e) {
1581:                    int index = e.ordinal();
1582:                    if (_enumValues.get(index) != e) {
1583:                        throw new IllegalArgumentException(
1584:                                "enum: "
1585:                                        + e
1586:                                        + ", ordinal value does not reflect enum values position");
1587:                    }
1588:                    int value = index;
1589:                    if (_mask == 0xFFFFFFFF) { // Non bit-field.
1590:                        getByteBuffer().putInt(position(), value);
1591:                    } else { // Bit-field.
1592:                        value <<= _shift;
1593:                        value &= _mask;
1594:                        int orMask = getByteBuffer().getInt(position())
1595:                                & (~_mask);
1596:                        getByteBuffer().putInt(position(), orMask | value);
1597:                    }
1598:                }
1599:            }
1600:
1601:            /**
1602:             * This class represents a 64 bits {@link Enum}.
1603:             */
1604:            public class Enum64 extends Member {
1605:                private final long _mask;
1606:
1607:                private final int _shift;
1608:
1609:                private final int _signShift;
1610:
1611:                private final List _enumValues;
1612:
1613:                public Enum64(List enumValues) {
1614:                    this (enumValues, 64);
1615:                }
1616:
1617:                public Enum64(List enumValues, int nbrOfBits) {
1618:                    super (8, nbrOfBits, 64);
1619:                    _enumValues = enumValues;
1620:                    final int startBit = offset() << 3;
1621:                    _shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? 64
1622:                            - _bitIndex + startBit : _bitIndex - startBit
1623:                            - nbrOfBits;
1624:                    _mask = (nbrOfBits == 64) ? 0xFFFFFFFFFFFFFFFFl
1625:                            : ((1l << nbrOfBits) - 1l) << _shift;
1626:                    _signShift = 64 - _shift - nbrOfBits;
1627:                }
1628:
1629:                public Enum get() {
1630:                    if (_mask == 0xFFFFFFFFFFFFFFFFl) { // Non bit-field.
1631:                        return (Enum) _enumValues.get((int) getByteBuffer()
1632:                                .getLong(position()));
1633:                    } else { // Bit-field.
1634:                        long value = getByteBuffer().getLong(position());
1635:                        value &= _mask;
1636:                        value <<= _signShift;
1637:                        value >>= _signShift + _shift; // Keeps sign.
1638:                        return (Enum) _enumValues.get((int) value);
1639:                    }
1640:                }
1641:
1642:                public void set(Enum e) {
1643:                    int index = e.ordinal();
1644:                    if (_enumValues.get(index) != e) {
1645:                        throw new IllegalArgumentException(
1646:                                "enum: "
1647:                                        + e
1648:                                        + ", ordinal value does not reflect enum values position");
1649:                    }
1650:                    long value = index;
1651:                    if (_mask == 0xFFFFFFFFFFFFFFFFl) { // Non bit-field.
1652:                        getByteBuffer().putLong(position(), value);
1653:                    } else { // Bit-field.
1654:                        value <<= _shift;
1655:                        value &= _mask;
1656:                        long orMask = getByteBuffer().getLong(position())
1657:                                & (~_mask);
1658:                        getByteBuffer().putLong(position(), orMask | value);
1659:                    }
1660:                }
1661:            }
1662:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.