Skip to content

Instantly share code, notes, and snippets.

@kig
Created May 18, 2012 10:26
Show Gist options
  • Save kig/2724530 to your computer and use it in GitHub Desktop.
Save kig/2724530 to your computer and use it in GitHub Desktop.
ArrayBuffer struct reader & writer
/**
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