UNPKG

diffusion

Version:

Diffusion JavaScript client

182 lines (140 loc) 4.42 kB
var _implements = require('util/interface')._implements; var Int64 = require('../../../data/primitive/int64'); var P16 = 1 << 16; var P24 = 1 << 24; var P32 = P16 * P16; function putInt32(value, buffer, high) { var offset = high ? 0 : 4; for (var i = 3; i >= 0; --i) { buffer[offset + i] = value & 255; value = value >> 8; } } function getInt32(buffer, high) { var offset = high ? 0 : 4; return (buffer[offset] * P24) + (buffer[offset + 1] << 16) + (buffer[offset + 2] << 8) + buffer[offset + 3]; } function putPositiveNumber(value, buffer) { for (var i = 7; i >= 0; --i) { buffer[i] = value & 255; value /= 256; } } function putNegativeNumber(value, buffer) { value++; for (var i = 7; i >= 0; --i) { buffer[i] = ((-value) & 255) ^ 255; value /= 256; } } function putString(value, radix, buffer) { radix = radix || 10; var negative = value[0] === "-"; if (negative) { value = value.substring(1); } else if (value.substring(0, 2) === "0x") { value = value.substring(2); radix = 16; } var high = 0; var low = 0; for (var i = 0; i < value.length; ++i) { low = low * radix + parseInt(value[i], radix); high = high * radix + Math.floor(low / P32); low %= P32; } if (negative) { high = ~high; if (low) { low = P32 - low; } else { high++; } } putInt32(high, buffer, true); putInt32(low, buffer, false); } /** * Implementation of signed 64-bit integer. May be constructed from a buffer, string or number. */ module.exports = _implements(Int64, function Int64Impl(value, radix) { var buffer = new Buffer([0, 0, 0, 0, 0, 0, 0, 0]); if (Buffer.isBuffer(value)) { buffer = value; } if (typeof value === 'string') { putString(value, radix, buffer); } if (typeof value === 'number') { // Explicit high/low bits if (typeof radix === 'number') { putInt32(value, buffer, true); putInt32(radix, buffer, false); } else if (value >= 0) { putPositiveNumber(value, buffer); } else { putNegativeNumber(value, buffer); } } if (value instanceof Int64Impl) { putInt32(value.getHighBits(), buffer, true); putInt32(value.getLowBits(), buffer, false); } this.getHighBits = function() { return getInt32(buffer, true); }; this.getLowBits = function() { return getInt32(buffer, false); }; this.toBuffer = function() { return buffer; }; this.toNumber = function() { var high = this.getHighBits() | 0; var low = this.getLowBits(); // This is a lossy operation - see docs. Will be accurate for numbers up to 2 ^ 53 return high ? high * P32 + low : low; }; this.isNegative = function() { return this.getHighBits() & 0x80000000; }; this.toString = function(radix) { radix = radix || 10; var high = this.getHighBits(); var low = this.getLowBits(); var sign = this.isNegative(); if (sign) { high = ~high; low = P32 - low; } if (high === 0 && low === 0) { return "0"; } var result = ""; while (high || low) { // Multiply modulo remainder up to its "real" value (since it represents the top 32 bits of a single value) var rem = (high % radix) * P32 + low; // Divide by radix, essentially reducing the high/low values by the digits we've taken from the modulo // remainder. We can't use bitwise operations to coerce to integer, as that would truncate to 32 bits high = Math.floor(high / radix); low = Math.floor(rem / radix); result = (rem % radix).toString(radix) + result; } if (sign) { result = "-" + result; } return result; }; this.equals = function(other) { if (other && other instanceof Int64Impl) { return this.getHighBits() === other.getHighBits() && this.getLowBits() === other.getLowBits(); } return false; }; }); module.exports.toString = function() { return "Int64Impl"; };