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.
293 lines
8.2 KiB
293 lines
8.2 KiB
// int64-buffer.js |
|
|
|
/*jshint -W018 */ // Confusing use of '!'. |
|
/*jshint -W030 */ // Expected an assignment or function call and instead saw an expression. |
|
/*jshint -W093 */ // Did you mean to return a conditional instead of an assignment? |
|
|
|
var Uint64BE, Int64BE, Uint64LE, Int64LE; |
|
|
|
!function(exports) { |
|
// constants |
|
|
|
var UNDEFINED = "undefined"; |
|
var BUFFER = (UNDEFINED !== typeof Buffer) && Buffer; |
|
var UINT8ARRAY = (UNDEFINED !== typeof Uint8Array) && Uint8Array; |
|
var ARRAYBUFFER = (UNDEFINED !== typeof ArrayBuffer) && ArrayBuffer; |
|
var ZERO = [0, 0, 0, 0, 0, 0, 0, 0]; |
|
var isArray = Array.isArray || _isArray; |
|
var BIT32 = 4294967296; |
|
var BIT24 = 16777216; |
|
|
|
// storage class |
|
|
|
var storage; // Array; |
|
|
|
// generate classes |
|
|
|
Uint64BE = factory("Uint64BE", true, true); |
|
Int64BE = factory("Int64BE", true, false); |
|
Uint64LE = factory("Uint64LE", false, true); |
|
Int64LE = factory("Int64LE", false, false); |
|
|
|
// class factory |
|
|
|
function factory(name, bigendian, unsigned) { |
|
var posH = bigendian ? 0 : 4; |
|
var posL = bigendian ? 4 : 0; |
|
var pos0 = bigendian ? 0 : 3; |
|
var pos1 = bigendian ? 1 : 2; |
|
var pos2 = bigendian ? 2 : 1; |
|
var pos3 = bigendian ? 3 : 0; |
|
var fromPositive = bigendian ? fromPositiveBE : fromPositiveLE; |
|
var fromNegative = bigendian ? fromNegativeBE : fromNegativeLE; |
|
var proto = Int64.prototype; |
|
var isName = "is" + name; |
|
var _isInt64 = "_" + isName; |
|
|
|
// properties |
|
proto.buffer = void 0; |
|
proto.offset = 0; |
|
proto[_isInt64] = true; |
|
|
|
// methods |
|
proto.toNumber = toNumber; |
|
proto.toString = toString; |
|
proto.toJSON = toNumber; |
|
proto.toArray = toArray; |
|
|
|
// add .toBuffer() method only when Buffer available |
|
if (BUFFER) proto.toBuffer = toBuffer; |
|
|
|
// add .toArrayBuffer() method only when Uint8Array available |
|
if (UINT8ARRAY) proto.toArrayBuffer = toArrayBuffer; |
|
|
|
// isUint64BE, isInt64BE |
|
Int64[isName] = isInt64; |
|
|
|
// CommonJS |
|
exports[name] = Int64; |
|
|
|
return Int64; |
|
|
|
// constructor |
|
function Int64(buffer, offset, value, raddix) { |
|
if (!(this instanceof Int64)) return new Int64(buffer, offset, value, raddix); |
|
return init(this, buffer, offset, value, raddix); |
|
} |
|
|
|
// isUint64BE, isInt64BE |
|
function isInt64(b) { |
|
return !!(b && b[_isInt64]); |
|
} |
|
|
|
// initializer |
|
function init(that, buffer, offset, value, raddix) { |
|
if (UINT8ARRAY && ARRAYBUFFER) { |
|
if (buffer instanceof ARRAYBUFFER) buffer = new UINT8ARRAY(buffer); |
|
if (value instanceof ARRAYBUFFER) value = new UINT8ARRAY(value); |
|
} |
|
|
|
// Int64BE() style |
|
if (!buffer && !offset && !value && !storage) { |
|
// shortcut to initialize with zero |
|
that.buffer = newArray(ZERO, 0); |
|
return; |
|
} |
|
|
|
// Int64BE(value, raddix) style |
|
if (!isValidBuffer(buffer, offset)) { |
|
var _storage = storage || Array; |
|
raddix = offset; |
|
value = buffer; |
|
offset = 0; |
|
buffer = new _storage(8); |
|
} |
|
|
|
that.buffer = buffer; |
|
that.offset = offset |= 0; |
|
|
|
// Int64BE(buffer, offset) style |
|
if (UNDEFINED === typeof value) return; |
|
|
|
// Int64BE(buffer, offset, value, raddix) style |
|
if ("string" === typeof value) { |
|
fromString(buffer, offset, value, raddix || 10); |
|
} else if (isValidBuffer(value, raddix)) { |
|
fromArray(buffer, offset, value, raddix); |
|
} else if ("number" === typeof raddix) { |
|
writeInt32(buffer, offset + posH, value); // high |
|
writeInt32(buffer, offset + posL, raddix); // low |
|
} else if (value > 0) { |
|
fromPositive(buffer, offset, value); // positive |
|
} else if (value < 0) { |
|
fromNegative(buffer, offset, value); // negative |
|
} else { |
|
fromArray(buffer, offset, ZERO, 0); // zero, NaN and others |
|
} |
|
} |
|
|
|
function fromString(buffer, offset, str, raddix) { |
|
var pos = 0; |
|
var len = str.length; |
|
var high = 0; |
|
var low = 0; |
|
if (str[0] === "-") pos++; |
|
var sign = pos; |
|
while (pos < len) { |
|
var chr = parseInt(str[pos++], raddix); |
|
if (!(chr >= 0)) break; // NaN |
|
low = low * raddix + chr; |
|
high = high * raddix + Math.floor(low / BIT32); |
|
low %= BIT32; |
|
} |
|
if (sign) { |
|
high = ~high; |
|
if (low) { |
|
low = BIT32 - low; |
|
} else { |
|
high++; |
|
} |
|
} |
|
writeInt32(buffer, offset + posH, high); |
|
writeInt32(buffer, offset + posL, low); |
|
} |
|
|
|
function toNumber() { |
|
var buffer = this.buffer; |
|
var offset = this.offset; |
|
var high = readInt32(buffer, offset + posH); |
|
var low = readInt32(buffer, offset + posL); |
|
if (!unsigned) high |= 0; // a trick to get signed |
|
return high ? (high * BIT32 + low) : low; |
|
} |
|
|
|
function toString(radix) { |
|
var buffer = this.buffer; |
|
var offset = this.offset; |
|
var high = readInt32(buffer, offset + posH); |
|
var low = readInt32(buffer, offset + posL); |
|
var str = ""; |
|
var sign = !unsigned && (high & 0x80000000); |
|
if (sign) { |
|
high = ~high; |
|
low = BIT32 - low; |
|
} |
|
radix = radix || 10; |
|
while (1) { |
|
var mod = (high % radix) * BIT32 + low; |
|
high = Math.floor(high / radix); |
|
low = Math.floor(mod / radix); |
|
str = (mod % radix).toString(radix) + str; |
|
if (!high && !low) break; |
|
} |
|
if (sign) { |
|
str = "-" + str; |
|
} |
|
return str; |
|
} |
|
|
|
function writeInt32(buffer, offset, value) { |
|
buffer[offset + pos3] = value & 255; |
|
value = value >> 8; |
|
buffer[offset + pos2] = value & 255; |
|
value = value >> 8; |
|
buffer[offset + pos1] = value & 255; |
|
value = value >> 8; |
|
buffer[offset + pos0] = value & 255; |
|
} |
|
|
|
function readInt32(buffer, offset) { |
|
return (buffer[offset + pos0] * BIT24) + |
|
(buffer[offset + pos1] << 16) + |
|
(buffer[offset + pos2] << 8) + |
|
buffer[offset + pos3]; |
|
} |
|
} |
|
|
|
function toArray(raw) { |
|
var buffer = this.buffer; |
|
var offset = this.offset; |
|
storage = null; // Array |
|
if (raw !== false && offset === 0 && buffer.length === 8 && isArray(buffer)) return buffer; |
|
return newArray(buffer, offset); |
|
} |
|
|
|
function toBuffer(raw) { |
|
var buffer = this.buffer; |
|
var offset = this.offset; |
|
storage = BUFFER; |
|
if (raw !== false && offset === 0 && buffer.length === 8 && Buffer.isBuffer(buffer)) return buffer; |
|
var dest = new BUFFER(8); |
|
fromArray(dest, 0, buffer, offset); |
|
return dest; |
|
} |
|
|
|
function toArrayBuffer(raw) { |
|
var buffer = this.buffer; |
|
var offset = this.offset; |
|
var arrbuf = buffer.buffer; |
|
storage = UINT8ARRAY; |
|
if (raw !== false && offset === 0 && (arrbuf instanceof ARRAYBUFFER) && arrbuf.byteLength === 8) return arrbuf; |
|
var dest = new UINT8ARRAY(8); |
|
fromArray(dest, 0, buffer, offset); |
|
return dest.buffer; |
|
} |
|
|
|
function isValidBuffer(buffer, offset) { |
|
var len = buffer && buffer.length; |
|
offset |= 0; |
|
return len && (offset + 8 <= len) && ("string" !== typeof buffer[offset]); |
|
} |
|
|
|
function fromArray(destbuf, destoff, srcbuf, srcoff) { |
|
destoff |= 0; |
|
srcoff |= 0; |
|
for (var i = 0; i < 8; i++) { |
|
destbuf[destoff++] = srcbuf[srcoff++] & 255; |
|
} |
|
} |
|
|
|
function newArray(buffer, offset) { |
|
return Array.prototype.slice.call(buffer, offset, offset + 8); |
|
} |
|
|
|
function fromPositiveBE(buffer, offset, value) { |
|
var pos = offset + 8; |
|
while (pos > offset) { |
|
buffer[--pos] = value & 255; |
|
value /= 256; |
|
} |
|
} |
|
|
|
function fromNegativeBE(buffer, offset, value) { |
|
var pos = offset + 8; |
|
value++; |
|
while (pos > offset) { |
|
buffer[--pos] = ((-value) & 255) ^ 255; |
|
value /= 256; |
|
} |
|
} |
|
|
|
function fromPositiveLE(buffer, offset, value) { |
|
var end = offset + 8; |
|
while (offset < end) { |
|
buffer[offset++] = value & 255; |
|
value /= 256; |
|
} |
|
} |
|
|
|
function fromNegativeLE(buffer, offset, value) { |
|
var end = offset + 8; |
|
value++; |
|
while (offset < end) { |
|
buffer[offset++] = ((-value) & 255) ^ 255; |
|
value /= 256; |
|
} |
|
} |
|
|
|
// https://github.com/retrofox/is-array |
|
function _isArray(val) { |
|
return !!val && "[object Array]" == Object.prototype.toString.call(val); |
|
} |
|
|
|
}(typeof exports === 'object' && typeof exports.nodeName !== 'string' ? exports : (this || {}));
|
|
|