2013-05-17 17:44:50 +08:00
|
|
|
|
|
|
|
function ArrayBufferSer(type, data, options) {
|
2015-05-13 18:23:27 +08:00
|
|
|
if(type === undefined) {
|
|
|
|
throw "ArrayBufferSer should be created with a type";
|
|
|
|
}
|
2014-08-03 02:23:47 +08:00
|
|
|
this.options = options || {};
|
2013-05-17 17:44:50 +08:00
|
|
|
this._initFunctions();
|
|
|
|
this.headerSize = 8;
|
|
|
|
this.data = data;
|
|
|
|
this.type = type = Math.min(type, ArrayBufferSer.BUFFER);
|
|
|
|
var size = this._sizeFor(this.headerSize, data);
|
|
|
|
this.buffer = new Buffer(this.headerSize + size);
|
|
|
|
this.buffer.writeUInt32BE(type, 0); // this could be one byte but for byte padding is better to be 4 bytes
|
|
|
|
this.buffer.writeUInt32BE(size, 4);
|
|
|
|
this.offset = this.headerSize;
|
|
|
|
|
|
|
|
var w = this.writeFn[type];
|
|
|
|
|
2015-05-13 18:23:27 +08:00
|
|
|
var i;
|
2013-05-17 17:44:50 +08:00
|
|
|
if(!this.options.delta) {
|
2015-05-13 18:23:27 +08:00
|
|
|
for(i = 0; i < data.length; ++i) {
|
2013-05-17 17:44:50 +08:00
|
|
|
this[w](data[i]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this[w](data[0]);
|
2015-05-13 18:23:27 +08:00
|
|
|
for(i = 1; i < data.length; ++i) {
|
2013-05-17 17:44:50 +08:00
|
|
|
this[w](data[i] - data[i - 1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// constants
|
|
|
|
//
|
|
|
|
ArrayBufferSer.INT8 = 1;
|
|
|
|
ArrayBufferSer.UINT8 = 2;
|
|
|
|
ArrayBufferSer.UINT8_CLAMP = 3;
|
|
|
|
ArrayBufferSer.INT16 = 4;
|
|
|
|
ArrayBufferSer.UINT16 = 5;
|
|
|
|
ArrayBufferSer.INT32 = 6;
|
|
|
|
ArrayBufferSer.UINT32 = 7;
|
|
|
|
ArrayBufferSer.FLOAT32 = 8;
|
|
|
|
//ArrayBufferSer.FLOAT64 = 9; not supported
|
|
|
|
ArrayBufferSer.STRING = 10;
|
|
|
|
ArrayBufferSer.BUFFER = 11;
|
|
|
|
|
|
|
|
ArrayBufferSer.MAX_PADDING = ArrayBufferSer.INT32;
|
|
|
|
|
|
|
|
|
|
|
|
ArrayBufferSer.typeNames = {
|
|
|
|
'int8': ArrayBufferSer.INT8,
|
|
|
|
'uint8': ArrayBufferSer.UINT8,
|
|
|
|
'uintclamp': ArrayBufferSer.UINT8_CLAMP,
|
|
|
|
'int16': ArrayBufferSer.INT16,
|
|
|
|
'uint16': ArrayBufferSer.UINT16,
|
|
|
|
'int32': ArrayBufferSer.INT32,
|
|
|
|
'uint32': ArrayBufferSer.UINT32,
|
|
|
|
'float32': ArrayBufferSer.FLOAT32,
|
|
|
|
'string': ArrayBufferSer.STRING,
|
|
|
|
'buffer': ArrayBufferSer.BUFFER
|
|
|
|
};
|
|
|
|
|
|
|
|
ArrayBufferSer.prototype = {
|
|
|
|
|
|
|
|
// 0 not used
|
|
|
|
sizes: [NaN, 1, 1, 1, 2, 2, 4, 4, 4, 8],
|
|
|
|
|
|
|
|
_paddingFor: function(off, type) {
|
2014-08-03 02:23:47 +08:00
|
|
|
var s = this.sizes[type];
|
2013-05-17 17:44:50 +08:00
|
|
|
if(s) {
|
|
|
|
var r = off % s;
|
2015-05-13 18:23:27 +08:00
|
|
|
return r === 0 ? 0 : s - r;
|
2013-05-17 17:44:50 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
},
|
|
|
|
|
|
|
|
_sizeFor: function(offset, t) {
|
|
|
|
var self = this;
|
2014-08-03 02:23:47 +08:00
|
|
|
var s = this.sizes[this.type];
|
2013-05-17 17:44:50 +08:00
|
|
|
if(s) {
|
|
|
|
return s*t.length;
|
|
|
|
}
|
|
|
|
s = 0;
|
2015-05-13 18:23:27 +08:00
|
|
|
if(this.type === ArrayBufferSer.STRING) {
|
2013-05-17 17:44:50 +08:00
|
|
|
// calculate size with padding
|
|
|
|
t.forEach(function(arr) {
|
|
|
|
var pad = self._paddingFor(offset, ArrayBufferSer.MAX_PADDING);
|
|
|
|
s += pad;
|
|
|
|
offset += pad;
|
2014-08-03 02:23:47 +08:00
|
|
|
var len = (self.headerSize + arr.length*2);
|
2013-05-17 17:44:50 +08:00
|
|
|
s += len;
|
|
|
|
offset += len;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
t.forEach(function(arr) {
|
|
|
|
var pad = self._paddingFor(offset, ArrayBufferSer.MAX_PADDING);
|
|
|
|
s += pad;
|
|
|
|
offset += pad;
|
2014-08-03 02:23:47 +08:00
|
|
|
s += arr.getSize();
|
2013-05-17 17:44:50 +08:00
|
|
|
offset += arr.getSize();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
|
|
|
|
getDataSize: function() {
|
|
|
|
return this._sizeFor(0, this.data);
|
|
|
|
},
|
|
|
|
|
|
|
|
getSize: function() {
|
|
|
|
return this.headerSize + this._sizeFor(this.headerSize, this.data);
|
|
|
|
},
|
|
|
|
|
2015-05-13 18:23:27 +08:00
|
|
|
writeFn: [
|
|
|
|
'',
|
|
|
|
'writeInt8',
|
|
|
|
'writeUInt8',
|
|
|
|
'writeUInt8Clamp',
|
|
|
|
'writeInt16LE',
|
|
|
|
'writeUInt16LE',
|
|
|
|
'writeUInt32LE',
|
|
|
|
'writeUInt32LE',
|
|
|
|
'writeFloatLE',
|
|
|
|
'writeDoubleLE',
|
|
|
|
'writeString',
|
|
|
|
'writteBuffer'
|
|
|
|
],
|
2013-05-17 17:44:50 +08:00
|
|
|
|
|
|
|
_initFunctions: function() {
|
|
|
|
var self = this;
|
|
|
|
this.writeFn.forEach(function(fn) {
|
2015-05-13 18:23:27 +08:00
|
|
|
if(self[fn] === undefined) {
|
2013-05-17 17:44:50 +08:00
|
|
|
self[fn] = function(d) {
|
|
|
|
self.buffer[fn](d, self.offset);
|
|
|
|
self.offset += self.sizes[self.type];
|
2015-05-13 18:23:27 +08:00
|
|
|
};
|
|
|
|
}
|
2013-05-17 17:44:50 +08:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
writeUInt8Clamp: function(c) {
|
|
|
|
this.buffer.writeUInt8(Math.min(255, c), this.offset);
|
|
|
|
this.offset += 1;
|
|
|
|
},
|
|
|
|
|
|
|
|
writeString: function(s) {
|
|
|
|
var arr = [];
|
|
|
|
for(var i = 0, len = s.length; i < len; ++i) {
|
|
|
|
arr.push(s.charCodeAt(i));
|
|
|
|
}
|
|
|
|
var str = new ArrayBufferSer(ArrayBufferSer.UINT16, arr);
|
|
|
|
this.writteBuffer(str);
|
|
|
|
},
|
|
|
|
|
|
|
|
writteBuffer: function(b) {
|
|
|
|
this.offset += this._paddingFor(this.offset, ArrayBufferSer.MAX_PADDING);
|
|
|
|
// copy header
|
2014-08-03 02:23:47 +08:00
|
|
|
b.buffer.copy(this.buffer, this.offset);
|
2013-05-17 17:44:50 +08:00
|
|
|
this.offset += b.buffer.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = ArrayBufferSer;
|