Created
May 18, 2012 10:26
-
-
Save kig/2724530 to your computer and use it in GitHub Desktop.
ArrayBuffer struct reader & writer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Struct definition object: | |
var myStruct = { | |
'width': 'uint32', | |
'height': 'uint32', | |
'channels': 'uint8', | |
'bias': 'float32', | |
'name': 'cstring', | |
'thumbnail': { | |
'length': 'uint32', | |
'data': ['uint8', 'length'] | |
} | |
}; | |
var u = new Uint8Array([137, 80, 78, 71, 0, 136, 136, 255, 137, 80, 78, 71, 0, 136, 136, 255, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33, 0, 0, 2, 0,1,2,3, 1,2,3,4, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33, 0]); | |
var dv = new DataView(u.buffer); | |
var def = { | |
tag: 'uint32', | |
code: 'uint32le', | |
embed: { tag:'uint32', code:'uint32le', greet:'cstring' }, | |
length: 'uint16', | |
data: ['float32', 'length'], | |
greet: 'cstring' }; | |
var obj = readStruct(dv, [0], def); | |
var u2 = new Uint8Array(u.length); | |
var dv2 = new DataView(u2.buffer); | |
writeStruct(dv2, [0], def, obj); | |
var success = true; | |
for (var i=0; i<u2.length; i++) { | |
if (u[i] != u2[i]) { | |
console.log('roundtrip failure at', i, u[i] + ' != ' + u2[i]); | |
success = false; | |
} | |
} | |
console.log('success: ', success); | |
*/ | |
var readStruct = function(dataView, idx, structDefinition) { | |
var struct = {}; | |
for (var n in structDefinition) { | |
var t = structDefinition[n] | |
struct[n] = readType(dataView, idx, t, struct); | |
} | |
return struct; | |
}; | |
var readType = function(dataView, idx, t, struct) { | |
switch(t) { | |
case 'uint8': | |
var v = dataView.getUint8(idx[0]); | |
idx[0]++; | |
return v; | |
case 'int8': | |
var v = dataView.getInt8(idx[0]); | |
idx[0]++; | |
return v; | |
case 'uint16': | |
var v = dataView.getUint16(idx[0]); | |
idx[0]+=2; | |
return v; | |
case 'int16': | |
var v = dataView.getInt16(idx[0]); | |
idx[0]+=2; | |
return v; | |
case 'uint32': | |
var v = dataView.getUint32(idx[0]); | |
idx[0]+=4; | |
return v; | |
case 'int32': | |
var v = dataView.getInt32(idx[0]); | |
idx[0]+=4; | |
return v; | |
case 'float32': | |
var v = dataView.getFloat32(idx[0]); | |
idx[0]+=4; | |
return v; | |
case 'float64': | |
var v = dataView.getFloat64(idx[0]); | |
idx[0]+=8; | |
return v; | |
case 'uint16le': | |
var v = dataView.getUint16(idx[0], true); | |
idx[0]+=2; | |
return v; | |
case 'int16le': | |
var v = dataView.getInt16(idx[0], true); | |
idx[0]+=2; | |
return v; | |
case 'uint32le': | |
var v = dataView.getUint32(idx[0], true); | |
idx[0]+=4; | |
return v; | |
case 'int32le': | |
var v = dataView.getInt32(idx[0], true); | |
idx[0]+=4; | |
return v; | |
case 'float32le': | |
var v = dataView.getFloat32(idx[0], true); | |
idx[0]+=4; | |
return v; | |
case 'float64le': | |
var v = dataView.getFloat64(idx[0], true); | |
idx[0]+=8; | |
return v; | |
case 'cstring': | |
var v = '', c; | |
while (c = dataView.getUint8(idx[0]++)) { | |
v += String.fromCharCode(c); | |
} | |
return v; | |
default: | |
if (t instanceof Array) { | |
var ta = t[0]; | |
var length = t[1]; | |
if (typeof length == 'string') { | |
length = struct[length]; | |
} | |
var v = new Array(length); | |
for (var i=0; i<length; i++) { | |
v[i] = readType(dataView, idx, ta, struct); | |
} | |
return v; | |
} else { | |
return readStruct(dataView, idx, t); | |
} | |
} | |
}; | |
var writeStruct = function(dataView, idx, structDefinition, struct) { | |
for (var n in structDefinition) { | |
var t = structDefinition[n] | |
writeType(dataView, idx, t, struct[n]); | |
} | |
return; | |
}; | |
var writeType = function(dataView, idx, t, v) { | |
switch(t) { | |
case 'uint8': | |
dataView.setUint8(idx[0], v); | |
idx[0]++; | |
return; | |
case 'int8': | |
dataView.setInt8(idx[0], v); | |
idx[0]++; | |
return; | |
case 'uint16': | |
dataView.setUint16(idx[0], v); | |
idx[0]+=2; | |
return; | |
case 'int16': | |
dataView.setInt16(idx[0], v); | |
idx[0]+=2; | |
return; | |
case 'uint32': | |
dataView.setUint32(idx[0], v); | |
idx[0]+=4; | |
return; | |
case 'int32': | |
dataView.setInt32(idx[0], v); | |
idx[0]+=4; | |
return; | |
case 'float32': | |
dataView.setFloat32(idx[0], v); | |
idx[0]+=4; | |
return; | |
case 'float64': | |
dataView.setFloat64(idx[0], v); | |
idx[0]+=8; | |
return; | |
case 'uint16le': | |
dataView.setUint16(idx[0], v, true); | |
idx[0]+=2; | |
return; | |
case 'int16le': | |
dataView.setInt16(idx[0], v, true); | |
idx[0]+=2; | |
return; | |
case 'uint32le': | |
dataView.setUint32(idx[0], v, true); | |
idx[0]+=4; | |
return; | |
case 'int32le': | |
dataView.setInt32(idx[0], v, true); | |
idx[0]+=4; | |
return; | |
case 'float32le': | |
dataView.setFloat32(idx[0], v, true); | |
idx[0]+=4; | |
return; | |
case 'float64le': | |
dataView.setFloat64(idx[0], v, true); | |
idx[0]+=8; | |
return; | |
case 'cstring': | |
for (var i=0; i<v.length; i++) { | |
dataView.setUint8(idx[0]++, v.charCodeAt(i)); | |
} | |
dataView.setUint8(idx[0]++, 0); | |
return; | |
default: | |
if (t instanceof Array) { | |
var ta = t[0]; | |
for (var i=0; i<v.length; i++) { | |
writeType(dataView, idx, ta, v[i]); | |
} | |
return; | |
} else { | |
return writeStruct(dataView, idx, t, v); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment