1 jls.loader.provide('jls.lang.Struct');
  2 
  3 jls.loader.require('jls.lang.ByteBuffer');
  4 
  5 jls.lang.Struct = jls.lang.Class.create( /** @lends jls.lang.Struct.prototype */
  6 {
  7     /**
  8      * Creates a structure.
  9      * 
 10      * @param {Array} structDef The structure definition.
 11      * @param {jls.lang.ByteBuffer} [buffer] The buffer to use for this structure.
 12      * @constructs
 13      * @class This class represents a structure. A structure specifies the format of a record,
 14      * including the names and types of its members, and the order in which they are stored.
 15      */
 16     initialize : function(structDef, buffer) {
 17         structDef = structDef || [];
 18         this._struct = {};
 19         var position = 0;
 20         for (var i = 0; i < structDef.length; i++) {
 21             var def = structDef[i];
 22             if (! (def.type in jls.lang.Struct.TYPE_SIZE)) {
 23                 throw new jls.lang.Exception('Invalid type ' + def.type);
 24             }
 25             var size = jls.lang.Struct.TYPE_SIZE[def.type];
 26             var length = ('length' in def) ? def.length : 1;
 27             this._struct[def.name] = {
 28                 position: position,
 29                 type: def.type,
 30                 length: length
 31             };
 32             position += size * length;
 33             //jls.logger.warn('Struct() ' + def.name + ', ' + def.type + ', ' + size + ', ' + position);
 34         }
 35         this._size = position;
 36         if (buffer) {
 37             if (buffer.remaining() < this._size) {
 38                 throw new jls.lang.Exception('Remaining buffer size too small (' + buffer.remaining() + '<' + this._size + ')');
 39             }
 40             this._buffer = buffer.slice();
 41         } else {
 42             this._buffer = jls.lang.ByteBuffer.allocate(this._size);
 43         }
 44     },
 45     /**
 46      * Returns the buffer.
 47      *
 48      * @returns {jls.lang.ByteBuffer} The buffer.
 49      */
 50     buffer : function() {
 51         return this._buffer;
 52     },
 53     clear : function() {
 54         this._buffer.clear();
 55         this._buffer.setLimit(this._size);
 56     },
 57     /**
 58      * Returns the size of the struct.
 59      *
 60      * @returns {Number} The size.
 61      */
 62     size : function() {
 63         return this._size;
 64     },
 65     has : function(name) {
 66         return (typeof name == 'string') && (name in this._struct);
 67     },
 68     /**
 69      * Gets a field in this structure.
 70      *
 71      * @param {String} name The field name.
 72      * @param {Number} [index] The index of the value to get.
 73      * @returns {Number|String} The field value.
 74      */
 75     get : function(name, index) {
 76         if (! (name in this._struct)) {
 77             throw new jls.lang.Exception('Invalid name ' + name);
 78         }
 79         var d = this._struct[name];
 80         this._buffer.setPosition(d.position);
 81         switch (d.type) {
 82         case 'SignedByte':
 83             return this._buffer.getByte(true);
 84         case 'UnsignedByte':
 85             return this._buffer.getByte(false);
 86         case 'SignedShort':
 87             return this._buffer.getShort(true);
 88         case 'UnsignedShort':
 89             return this._buffer.getShort(false);
 90         case 'SignedInt':
 91             return this._buffer.getInt(true);
 92         case 'UnsignedInt':
 93             return this._buffer.getInt(false);
 94         case 'SignedLong':
 95             return this._buffer.getLong(true);
 96         case 'UnsignedLong':
 97             return this._buffer.getLong(false);
 98         case 'Pointer':
 99             return this._buffer.getPointer();
100         }
101     },
102     /**
103      * Puts a field in this structure.
104      *
105      * @param {String} name The field name.
106      * @param {Number|String} value The field value to set.
107      * @param {Number} [index] The index of the value to get.
108      * @returns {jls.lang.Struct} This structure.
109      */
110     put : function(name, value, index) {
111         if (! (name in this._struct)) {
112             throw new jls.lang.Exception('Invalid name ' + name);
113         }
114         //jls.logger.warn('Struct.put("' + name + '", ' + value + ')');
115         var d = this._struct[name]
116         this._buffer.setPosition(d.position);
117         switch (d.type) {
118         case 'SignedByte':
119         case 'UnsignedByte':
120             this._buffer.putByte(value);
121             break;
122         case 'SignedShort':
123         case 'UnsignedShort':
124             this._buffer.putShort(value);
125             break;
126         case 'SignedInt':
127         case 'UnsignedInt':
128             this._buffer.putInt(value);
129             break;
130         case 'SignedLong':
131         case 'UnsignedLong':
132             this._buffer.putLong(value);
133             break;
134         case 'Pointer':
135             this._buffer.putPointer(value);
136             break;
137         }
138         return this;
139     }
140 });
141 
142 Object.extend(jls.lang.Struct, /** @lends jls.lang.Struct */
143 {
144     TYPE_SIZE : {
145         'SignedByte': 1,
146         'UnsignedByte': 1,
147         'SignedShort': 2,
148         'UnsignedShort': 2,
149         'SignedInt': 4,
150         'UnsignedInt': 4,
151         'SignedLong': 8,
152         'UnsignedLong': 8,
153         'Pointer': jls.lang.ByteBuffer.POINTER_SIZE
154     }
155 });
156 
157