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