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 this._buffer = buffer || jls.lang.ByteBuffer.allocate(this._size); 37 }, 38 /** 39 * Returns the buffer. 40 * 41 * @returns {jls.lang.ByteBuffer} The buffer. 42 */ 43 buffer : function() { 44 return this._buffer; 45 }, 46 /** 47 * Returns the size of the struct. 48 * 49 * @returns {Number} The size. 50 */ 51 size : function() { 52 return this._size; 53 }, 54 /** 55 * Gets a field in this structure. 56 * 57 * @param {String} name The field name. 58 * @param {Number} [index] The index of the value to get. 59 * @returns {Number|String} The field value. 60 */ 61 get : function(name, index) { 62 if (! (name in this._struct)) { 63 throw new jls.lang.Exception('Invalid name ' + name); 64 } 65 var d = this._struct[name]; 66 this._buffer.setPosition(d.position); 67 switch (d.type) { 68 case 'SignedByte': 69 return this._buffer.getByte(true); 70 case 'UnsignedByte': 71 return this._buffer.getByte(false); 72 case 'SignedShort': 73 return this._buffer.getShort(true); 74 case 'UnsignedShort': 75 return this._buffer.getShort(false); 76 case 'SignedInt': 77 return this._buffer.getInt(true); 78 case 'UnsignedInt': 79 return this._buffer.getInt(false); 80 case 'SignedLong': 81 return this._buffer.getLong(true); 82 case 'UnsignedLong': 83 return this._buffer.getLong(false); 84 case 'Pointer': 85 return this._buffer.getPointer(); 86 } 87 }, 88 /** 89 * Puts a field in this structure. 90 * 91 * @param {String} name The field name. 92 * @param {Number|String} value The field value to set. 93 * @param {Number} [index] The index of the value to get. 94 * @returns {jls.lang.Struct} This structure. 95 */ 96 put : function(name, value, index) { 97 if (! (name in this._struct)) { 98 throw new jls.lang.Exception('Invalid name ' + name); 99 } 100 //jls.logger.warn('Struct.put("' + name + '", ' + value + ')'); 101 var d = this._struct[name] 102 this._buffer.setPosition(d.position); 103 switch (d.type) { 104 case 'SignedByte': 105 case 'UnsignedByte': 106 this._buffer.putByte(value); 107 break; 108 case 'SignedShort': 109 case 'UnsignedShort': 110 this._buffer.putShort(value); 111 break; 112 case 'SignedInt': 113 case 'UnsignedInt': 114 this._buffer.putInt(value); 115 break; 116 case 'SignedLong': 117 case 'UnsignedLong': 118 this._buffer.putLong(value); 119 break; 120 case 'Pointer': 121 this._buffer.putPointer(value); 122 break; 123 } 124 return this; 125 } 126 }); 127 128 Object.extend(jls.lang.Struct, /** @lends jls.lang.Struct */ 129 { 130 TYPE_SIZE : { 131 'SignedByte': 1, 132 'UnsignedByte': 1, 133 'SignedShort': 2, 134 'UnsignedShort': 2, 135 'SignedInt': 4, 136 'UnsignedInt': 4, 137 'SignedLong': 8, 138 'UnsignedLong': 8, 139 'Pointer': jls.lang.ByteBuffer.POINTER_SIZE 140 } 141 }); 142 143