You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
11 KiB
482 lines
11 KiB
5 years ago
|
// Copyright (c) 2008, Fair Oaks Labs, Inc.
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||
|
// permitted provided that the following conditions are met:
|
||
|
//
|
||
|
// * Redistributions of source code must retain the above copyright notice, this list
|
||
|
// of conditions and the following disclaimer.
|
||
|
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||
|
// list of conditions and the following disclaimer in the documentation and/or other
|
||
|
// materials provided with the distribution.
|
||
|
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors may be
|
||
|
// used to endorse or promote products derived from this software without specific
|
||
|
// prior written permission.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||
|
// THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
// Modified from original JSPack <cbond@positrace.com>
|
||
|
exports.jspack = function (bigEndian) {
|
||
|
this.bigEndian = bigEndian;
|
||
|
}
|
||
|
|
||
|
exports.jspack.prototype._DeArray = function (a, p, l) {
|
||
|
return [a.slice(p, p + l)];
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._EnArray = function (a, p, l, v) {
|
||
|
for (var i = 0; i < l; ++i) {
|
||
|
a[p + i] = v[i] ? v[i] : 0;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._DeChar = function (a, p) {
|
||
|
return String.fromCharCode(a[p]);
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._EnChar = function (a, p, v) {
|
||
|
a[p] = v.charCodeAt(0);
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._DeInt = function (a, p) {
|
||
|
var lsb = bigEndian ? format.len - 1 : 0;
|
||
|
var nsb = bigEndian ? -1 : 1;
|
||
|
var stp = lsb + nsb * format.len,
|
||
|
rv;
|
||
|
var ret = 0;
|
||
|
|
||
|
var i = lsb;
|
||
|
var f = 1;
|
||
|
while (i != stp) {
|
||
|
rv += a[p + i] * f;
|
||
|
i += nsb;
|
||
|
f *= 256;
|
||
|
}
|
||
|
|
||
|
if (format.signed) {
|
||
|
if ((rv & Math.pow(2, format.len * 8 - 1)) != 0) {
|
||
|
rv -= Math.pow(2, format.len * 8);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rv;
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._EnInt = function (a, p, v) {
|
||
|
var lsb = bigEndian ? format.len - 1 : 0;
|
||
|
var nsb = bigEndian ? -1 : 1;
|
||
|
var stp = lsb + nsb * format.len;
|
||
|
|
||
|
v = v < format.min ? format.min : ((v > format.max) ? format.max : v);
|
||
|
|
||
|
var i = lsb;
|
||
|
while (i != stp) {
|
||
|
a[p + i] = v & 0xff;
|
||
|
i += nsb;
|
||
|
v >>= 8;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._DeString = function (a, p, l) {
|
||
|
var rv = new Array(1);
|
||
|
|
||
|
for (i = 0; i < l; i++) {
|
||
|
rv[i] = String.fromCharCode(a[p + i]);
|
||
|
}
|
||
|
|
||
|
return rv.join('');
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._EnString = function (a, p, l, v) {
|
||
|
for (var t, i = 0; i < l; ++i) {
|
||
|
t = v.charCodeAt(i);
|
||
|
if (!t) t = 0;
|
||
|
|
||
|
a[p + i] = t;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._De754 = function (a, p) {
|
||
|
var s, e, m, i, d, bits, bit, len, bias, max;
|
||
|
|
||
|
bit = format.bit;
|
||
|
len = format.len * 8 - format.bit - 1;
|
||
|
max = (1 << len) - 1;
|
||
|
bias = max >> 1;
|
||
|
|
||
|
i = bigEndian ? 0 : format.len - 1;
|
||
|
d = bigEndian ? 1 : -1;;
|
||
|
s = a[p + i];
|
||
|
i = i + d;
|
||
|
|
||
|
bits = -7;
|
||
|
|
||
|
e = s & ((1 << -bits) - 1);
|
||
|
s >>= -bits;
|
||
|
|
||
|
for (bits += len; bits > 0; bits -= 8) {
|
||
|
e = e * 256 + a[p + i];
|
||
|
i += d;
|
||
|
}
|
||
|
|
||
|
m = e & ((1 << -bits) - 1);
|
||
|
e >>= -bits;
|
||
|
|
||
|
for (bits += bit; bits > 0; bits -= 8) {
|
||
|
m = m * 256 + a[p + i];
|
||
|
i += d;
|
||
|
}
|
||
|
|
||
|
switch (e) {
|
||
|
case 0:
|
||
|
// Zero, or denormalized number
|
||
|
e = 1 - bias;
|
||
|
break;
|
||
|
|
||
|
case max:
|
||
|
// NaN, or +/-Infinity
|
||
|
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
||
|
|
||
|
default:
|
||
|
// Normalized number
|
||
|
m = m + Math.pow(2, bit);
|
||
|
e = e - bias;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return (s ? -1 : 1) * m * Math.pow(2, e - bit);
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._En754 = function (a, p, v) {
|
||
|
var s, e, m, i, d, c, bit, len, bias, max;
|
||
|
|
||
|
bit = format.bit;
|
||
|
len = format.len * 8 - format.bit - 1;
|
||
|
max = (1 << len) - 1;
|
||
|
bias = max >> 1;
|
||
|
|
||
|
s = v < 0 ? 1 : 0;
|
||
|
v = Math.abs(v);
|
||
|
|
||
|
if (isNaN(v) || (v == Infinity)) {
|
||
|
m = isNaN(v) ? 1 : 0;
|
||
|
e = max;
|
||
|
} else {
|
||
|
e = Math.floor(Math.log(v) / Math.LN2); // Calculate log2 of the value
|
||
|
c = Math.pow(2, -e);
|
||
|
if (v * c < 1) {
|
||
|
e--;
|
||
|
c = c * 2;
|
||
|
}
|
||
|
|
||
|
// Round by adding 1/2 the significand's LSD
|
||
|
if (e + bias >= 1) {
|
||
|
v += format.rt / c; // Normalized: bit significand digits
|
||
|
} else {
|
||
|
v += format.rt * Math.pow(2, 1 - bias); // Denormalized: <= bit significand digits
|
||
|
}
|
||
|
if (v * c >= 2) {
|
||
|
e++;
|
||
|
c = c / 2; // Rounding can increment the exponent
|
||
|
}
|
||
|
|
||
|
if (e + bias >= max) { // overflow
|
||
|
m = 0;
|
||
|
e = max;
|
||
|
} else if (e + bias >= 1) { // normalized
|
||
|
m = (v * c - 1) * Math.pow(2, bit); // do not reorder this expression
|
||
|
e = e + bias;
|
||
|
} else {
|
||
|
// Denormalized - also catches the '0' case, somewhat by chance
|
||
|
m = v * Math.pow(2, bias - 1) * Math.pow(2, bit);
|
||
|
e = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i = bigEndian ? format.len - 1 : 0;
|
||
|
d = bigEndian ? -1 : 1;;
|
||
|
|
||
|
while (bit >= 8) {
|
||
|
a[p + i] = m & 0xff;
|
||
|
i += d;
|
||
|
m /= 256;
|
||
|
bit -= 8;
|
||
|
}
|
||
|
|
||
|
e = (e << bit) | m;
|
||
|
for (len += bit; len > 0; len -= 8) {
|
||
|
a[p + i] = e & 0xff;
|
||
|
i += d;
|
||
|
e /= 256;
|
||
|
}
|
||
|
|
||
|
a[p + i - d] |= s * 128;
|
||
|
};
|
||
|
|
||
|
// Unpack a series of n formatements of size s from array a at offset p with fxn
|
||
|
exports.jspack.prototype._UnpackSeries = function (n, s, a, p) {
|
||
|
var fxn = format.de;
|
||
|
|
||
|
var ret = [];
|
||
|
for (var i = 0; i < n; i++) {
|
||
|
ret.push(fxn(a, p + i * s));
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
};
|
||
|
|
||
|
// Pack a series of n formatements of size s from array v at offset i to array a at offset p with fxn
|
||
|
exports.jspack.prototype._PackSeries = function (n, s, a, p, v, i) {
|
||
|
var fxn = format.en;
|
||
|
|
||
|
for (o = 0; o < n; o++) {
|
||
|
fxn(a, p + o * s, v[i + o]);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Unpack the octet array a, beginning at offset p, according to the fmt string
|
||
|
exports.jspack.prototype.Unpack = function (fmt, a, p) {
|
||
|
bigEndian = fmt.charAt(0) != '<';
|
||
|
|
||
|
if (p == undefined || p == null) p = 0;
|
||
|
|
||
|
var re = new RegExp(this._sPattern, 'g');
|
||
|
|
||
|
var ret = [];
|
||
|
|
||
|
for (var m; m = re.exec(fmt); /* */ ) {
|
||
|
var n;
|
||
|
if (m[1] == undefined || m[1] == '') n = 1;
|
||
|
else n = parseInt(m[1]);
|
||
|
|
||
|
var s = this._lenLut[m[2]];
|
||
|
|
||
|
if ((p + n * s) > a.length) return undefined;
|
||
|
|
||
|
switch (m[2]) {
|
||
|
case 'A':
|
||
|
case 's':
|
||
|
rv.push(this._formatLut[m[2]].de(a, p, n));
|
||
|
break;
|
||
|
case 'c':
|
||
|
case 'b':
|
||
|
case 'B':
|
||
|
case 'h':
|
||
|
case 'H':
|
||
|
case 'i':
|
||
|
case 'I':
|
||
|
case 'l':
|
||
|
case 'L':
|
||
|
case 'f':
|
||
|
case 'd':
|
||
|
format = this._formatLut[m[2]];
|
||
|
ret.push(this._UnpackSeries(n, s, a, p));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
p += n * s;
|
||
|
}
|
||
|
|
||
|
return Array.prototype.concat.apply([], ret);
|
||
|
};
|
||
|
|
||
|
// Pack the supplied values into the octet array a, beginning at offset p, according to the fmt string
|
||
|
exports.jspack.prototype.PackTo = function (fmt, a, p, values) {
|
||
|
bigEndian = (fmt.charAt(0) != '<');
|
||
|
|
||
|
var re = new RegExp(this._sPattern, 'g');
|
||
|
|
||
|
for (var m, i = 0; m = re.exec(fmt); /* */ ) {
|
||
|
var n;
|
||
|
if (m[1] == undefined || m[1] == '') n = 1;
|
||
|
else n = parseInt(m[1]);
|
||
|
|
||
|
var s = this._lenLut[m[2]];
|
||
|
|
||
|
if ((p + n * s) > a.length) return false;
|
||
|
|
||
|
switch (m[2]) {
|
||
|
case 'A':
|
||
|
case 's':
|
||
|
if ((i + 1) > values.length) return false;
|
||
|
|
||
|
this._formatLut[m[2]].en(a, p, n, values[i]);
|
||
|
|
||
|
i += 1;
|
||
|
break;
|
||
|
|
||
|
case 'c':
|
||
|
case 'b':
|
||
|
case 'B':
|
||
|
case 'h':
|
||
|
case 'H':
|
||
|
case 'i':
|
||
|
case 'I':
|
||
|
case 'l':
|
||
|
case 'L':
|
||
|
case 'f':
|
||
|
case 'd':
|
||
|
format = this._formatLut[m[2]];
|
||
|
|
||
|
if (i + n > values.length) return false;
|
||
|
|
||
|
this._PackSeries(n, s, a, p, values, i);
|
||
|
|
||
|
i += n;
|
||
|
break;
|
||
|
|
||
|
case 'x':
|
||
|
for (var j = 0; j < n; j++) {
|
||
|
a[p + j] = 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
p += n * s;
|
||
|
}
|
||
|
|
||
|
return a;
|
||
|
};
|
||
|
|
||
|
// Pack the supplied values into a new octet array, according to the fmt string
|
||
|
exports.jspack.prototype.Pack = function (fmt, values) {
|
||
|
return this.PackTo(fmt, new Array(this.CalcLength(fmt)), 0, values);
|
||
|
};
|
||
|
|
||
|
// Determine the number of bytes represented by the format string
|
||
|
exports.jspack.prototype.CalcLength = function (fmt) {
|
||
|
var re = new RegExp(this._sPattern, 'g');
|
||
|
var sz = 0;
|
||
|
|
||
|
while (match = re.exec(fmt)) {
|
||
|
var n;
|
||
|
if (match[1] == undefined || match[1] == '') n = 1;
|
||
|
else n = parseInt(match[1]);
|
||
|
|
||
|
sz += n * this._lenLut[match[2]];
|
||
|
}
|
||
|
|
||
|
return sz;
|
||
|
};
|
||
|
|
||
|
// Regular expression for counting digits
|
||
|
exports.jspack.prototype._sPattern = '(\\d+)?([AxcbBhHsfdiIlL])';
|
||
|
|
||
|
// Byte widths for associated formats
|
||
|
exports.jspack.prototype._lenLut = {
|
||
|
'A': 1,
|
||
|
'x': 1,
|
||
|
'c': 1,
|
||
|
'b': 1,
|
||
|
'B': 1,
|
||
|
'h': 2,
|
||
|
'H': 2,
|
||
|
's': 1,
|
||
|
'f': 4,
|
||
|
'd': 8,
|
||
|
'i': 4,
|
||
|
'I': 4,
|
||
|
'l': 4,
|
||
|
'L': 4
|
||
|
};
|
||
|
|
||
|
exports.jspack.prototype._formatLut = {
|
||
|
'A': {
|
||
|
en: exports.jspack.prototype._EnArray,
|
||
|
de: exports.jspack.prototype._DeArray
|
||
|
},
|
||
|
's': {
|
||
|
en: exports.jspack.prototype._EnString,
|
||
|
de: exports.jspack.prototype._DeString
|
||
|
},
|
||
|
'c': {
|
||
|
en: exports.jspack.prototype._EnChar,
|
||
|
de: exports.jspack.prototype._DeChar
|
||
|
},
|
||
|
'b': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 1,
|
||
|
signed: true,
|
||
|
min: -Math.pow(2, 7),
|
||
|
max: Math.pow(2, 7) - 1
|
||
|
},
|
||
|
'B': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 1,
|
||
|
signed: false,
|
||
|
min: 0,
|
||
|
max: Math.pow(2, 8) - 1
|
||
|
},
|
||
|
'h': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 2,
|
||
|
signed: true,
|
||
|
min: -Math.pow(2, 15),
|
||
|
max: Math.pow(2, 15) - 1
|
||
|
},
|
||
|
'H': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 2,
|
||
|
signed: false,
|
||
|
min: 0,
|
||
|
max: Math.pow(2, 16) - 1
|
||
|
},
|
||
|
'i': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 4,
|
||
|
signed: true,
|
||
|
min: -Math.pow(2, 31),
|
||
|
max: Math.pow(2, 31) - 1
|
||
|
},
|
||
|
'I': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 4,
|
||
|
signed: false,
|
||
|
min: 0,
|
||
|
max: Math.pow(2, 32) - 1
|
||
|
},
|
||
|
'l': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 4,
|
||
|
signed: true,
|
||
|
min: -Math.pow(2, 31),
|
||
|
max: Math.pow(2, 31) - 1
|
||
|
},
|
||
|
'L': {
|
||
|
en: exports.jspack.prototype._EnInt,
|
||
|
de: exports.jspack.prototype._DeInt,
|
||
|
len: 4,
|
||
|
signed: false,
|
||
|
min: 0,
|
||
|
max: Math.pow(2, 32) - 1
|
||
|
},
|
||
|
'f': {
|
||
|
en: exports.jspack.prototype._En754,
|
||
|
de: exports.jspack.prototype._De754,
|
||
|
len: 4,
|
||
|
bit: 23,
|
||
|
rt: Math.pow(2, -24) - Math.pow(2, -77)
|
||
|
},
|
||
|
'd': {
|
||
|
en: exports.jspack.prototype._En754,
|
||
|
de: exports.jspack.prototype._De754,
|
||
|
len: 8,
|
||
|
bit: 52,
|
||
|
rt: 0
|
||
|
}
|
||
|
};
|