2018-10-24 21:42:33 +08:00
|
|
|
'use strict';
|
2013-05-17 17:44:50 +08:00
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
function ArrayBufferSer (type, data, options) {
|
|
|
|
if (type === undefined) {
|
|
|
|
throw 'ArrayBufferSer should be created with a type';
|
2013-05-17 17:44:50 +08:00
|
|
|
}
|
2019-12-24 01:19:08 +08:00
|
|
|
this.options = options || {};
|
|
|
|
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];
|
|
|
|
|
|
|
|
var i;
|
|
|
|
if (!this.options.delta) {
|
|
|
|
for (i = 0; i < data.length; ++i) {
|
|
|
|
this[w](data[i]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this[w](data[0]);
|
|
|
|
for (i = 1; i < data.length; ++i) {
|
|
|
|
this[w](data[i] - data[i - 1]);
|
|
|
|
}
|
2013-05-17 17:44:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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;
|
2019-12-24 01:19:08 +08:00
|
|
|
// ArrayBufferSer.FLOAT64 = 9; not supported
|
2013-05-17 17:44:50 +08:00
|
|
|
ArrayBufferSer.STRING = 10;
|
|
|
|
ArrayBufferSer.BUFFER = 11;
|
|
|
|
|
|
|
|
ArrayBufferSer.MAX_PADDING = ArrayBufferSer.INT32;
|
|
|
|
|
|
|
|
ArrayBufferSer.typeNames = {
|
2019-12-24 01:19:08 +08:00
|
|
|
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
|
2013-05-17 17:44:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
ArrayBufferSer.prototype = {
|
|
|
|
|
2019-12-24 01:19:08 +08:00
|
|
|
// 0 not used
|
|
|
|
sizes: [NaN, 1, 1, 1, 2, 2, 4, 4, 4, 8],
|
|
|
|
|
|
|
|
_paddingFor: function (off, type) {
|
|
|
|
var s = this.sizes[type];
|
|
|
|
if (s) {
|
|
|
|
var r = off % s;
|
|
|
|
return r === 0 ? 0 : s - r;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
},
|
|
|
|
|
|
|
|
_sizeFor: function (offset, t) {
|
|
|
|
var self = this;
|
|
|
|
var s = this.sizes[this.type];
|
|
|
|
if (s) {
|
|
|
|
return s * t.length;
|
|
|
|
}
|
|
|
|
s = 0;
|
|
|
|
if (this.type === ArrayBufferSer.STRING) {
|
|
|
|
// calculate size with padding
|
|
|
|
t.forEach(function (arr) {
|
|
|
|
var pad = self._paddingFor(offset, ArrayBufferSer.MAX_PADDING);
|
|
|
|
s += pad;
|
|
|
|
offset += pad;
|
|
|
|
var len = (self.headerSize + arr.length * 2);
|
|
|
|
s += len;
|
|
|
|
offset += len;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
t.forEach(function (arr) {
|
|
|
|
var pad = self._paddingFor(offset, ArrayBufferSer.MAX_PADDING);
|
|
|
|
s += pad;
|
|
|
|
offset += pad;
|
|
|
|
s += arr.getSize();
|
|
|
|
offset += arr.getSize();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
|
|
|
|
getDataSize: function () {
|
|
|
|
return this._sizeFor(0, this.data);
|
|
|
|
},
|
|
|
|
|
|
|
|
getSize: function () {
|
|
|
|
return this.headerSize + this._sizeFor(this.headerSize, this.data);
|
|
|
|
},
|
|
|
|
|
|
|
|
writeFn: [
|
|
|
|
'',
|
|
|
|
'writeInt8',
|
|
|
|
'writeUInt8',
|
|
|
|
'writeUInt8Clamp',
|
|
|
|
'writeInt16LE',
|
|
|
|
'writeUInt16LE',
|
|
|
|
'writeUInt32LE',
|
|
|
|
'writeUInt32LE',
|
|
|
|
'writeFloatLE',
|
|
|
|
'writeDoubleLE',
|
|
|
|
'writeString',
|
|
|
|
'writteBuffer'
|
|
|
|
],
|
|
|
|
|
|
|
|
_initFunctions: function () {
|
|
|
|
var self = this;
|
|
|
|
this.writeFn.forEach(function (fn) {
|
|
|
|
if (self[fn] === undefined) {
|
|
|
|
self[fn] = function (d) {
|
|
|
|
self.buffer[fn](d, self.offset);
|
|
|
|
self.offset += self.sizes[self.type];
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
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
|
|
|
|
b.buffer.copy(this.buffer, this.offset);
|
|
|
|
this.offset += b.buffer.length;
|
2013-05-17 17:44:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = ArrayBufferSer;
|