aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2018-01-30 17:34:25 +0100
committerRuben Bridgewater <ruben@bridgewater.de>2018-03-02 19:29:46 +0000
commite8bb1f35df079cf0111fc18a8a24ec0a2d66eb3e (patch)
tree635c3c8e56a123fb45ab1f3136739aade631ba9c /lib
parenta6c490cc8e8c848d6c4d5b8739827198055fe40f (diff)
downloadandroid-node-v8-e8bb1f35df079cf0111fc18a8a24ec0a2d66eb3e.tar.gz
android-node-v8-e8bb1f35df079cf0111fc18a8a24ec0a2d66eb3e.tar.bz2
android-node-v8-e8bb1f35df079cf0111fc18a8a24ec0a2d66eb3e.zip
buffer: refactor all read/write functions
There are a lot of changes in this commit: 1) Remove the `noAssert` argument from all read and write functions. 2) Improve the performance of all read floating point functions significantly. This is done by switching to TypedArrays as the write floating point write functions. 3) No implicit type coercion for offset and byteLength anymore. 4) Adds a lot of tests. 5) Moves the read and write functions to the internal buffer file to split the files in smaller chunks. 6) Reworked a lot of existing tests. 7) Improve the performane of all all read write functions by using a faster input validation and by improving function logic. 8) Significantly improved the performance of all read int functions. This is done by using a implementation without a loop. 9) Improved error handling. 10) Rename test file to use the correct subsystem. PR-URL: https://github.com/nodejs/node/pull/18395 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'lib')
-rw-r--r--lib/buffer.js555
-rw-r--r--lib/internal/buffer.js786
2 files changed, 789 insertions, 552 deletions
diff --git a/lib/buffer.js b/lib/buffer.js
index 220437f25d..ead43b453d 100644
--- a/lib/buffer.js
+++ b/lib/buffer.js
@@ -68,6 +68,10 @@ internalBuffer.FastBuffer = FastBuffer;
Buffer.prototype = FastBuffer.prototype;
+for (const [name, method] of Object.entries(internalBuffer.readWrites)) {
+ Buffer.prototype[name] = method;
+}
+
const constants = Object.defineProperties({}, {
MAX_LENGTH: {
value: kMaxLength,
@@ -81,12 +85,6 @@ const constants = Object.defineProperties({}, {
}
});
-// Temporary buffers to convert numbers.
-const float32Array = new Float32Array(1);
-const uInt8Float32Array = new Uint8Array(float32Array.buffer);
-const float64Array = new Float64Array(1);
-const uInt8Float64Array = new Uint8Array(float64Array.buffer);
-
Buffer.poolSize = 8 * 1024;
var poolSize, poolOffset, allocPool;
@@ -998,551 +996,6 @@ Buffer.prototype.slice = function slice(start, end) {
return new FastBuffer(this.buffer, this.byteOffset + start, newLength);
};
-function checkOffset(offset, ext, length) {
- if (offset + ext > length)
- throw new errors.RangeError('ERR_INDEX_OUT_OF_RANGE');
-}
-
-function checkByteLength(byteLength) {
- if (byteLength < 1 || byteLength > 6) {
- throw new errors.RangeError('ERR_OUT_OF_RANGE',
- 'byteLength',
- '>= 1 and <= 6');
- }
-}
-
-Buffer.prototype.readUIntLE =
- function readUIntLE(offset, byteLength, noAssert) {
- offset = offset >>> 0;
- byteLength = byteLength >>> 0;
- if (!noAssert) {
- checkByteLength(byteLength);
- checkOffset(offset, byteLength, this.length);
- }
-
- var val = this[offset];
- var mul = 1;
- var i = 0;
- while (++i < byteLength && (mul *= 0x100))
- val += this[offset + i] * mul;
-
- return val;
- };
-
-Buffer.prototype.readUIntBE =
- function readUIntBE(offset, byteLength, noAssert) {
- offset = offset >>> 0;
- byteLength = byteLength >>> 0;
- if (!noAssert) {
- checkByteLength(byteLength);
- checkOffset(offset, byteLength, this.length);
- }
-
- var val = this[offset + --byteLength];
- var mul = 1;
- while (byteLength > 0 && (mul *= 0x100))
- val += this[offset + --byteLength] * mul;
-
- return val;
- };
-
-Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 1, this.length);
- return this[offset];
-};
-
-Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 2, this.length);
- return this[offset] | (this[offset + 1] << 8);
-};
-
-Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 2, this.length);
- return (this[offset] << 8) | this[offset + 1];
-};
-
-Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 4, this.length);
-
- return ((this[offset]) |
- (this[offset + 1] << 8) |
- (this[offset + 2] << 16)) +
- (this[offset + 3] * 0x1000000);
-};
-
-Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 4, this.length);
-
- return (this[offset] * 0x1000000) +
- ((this[offset + 1] << 16) |
- (this[offset + 2] << 8) |
- this[offset + 3]);
-};
-
-Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) {
- offset = offset >>> 0;
- byteLength = byteLength >>> 0;
-
- if (!noAssert) {
- checkByteLength(byteLength);
- checkOffset(offset, byteLength, this.length);
- }
-
- var val = this[offset];
- var mul = 1;
- var i = 0;
- while (++i < byteLength && (mul *= 0x100))
- val += this[offset + i] * mul;
- mul *= 0x80;
-
- if (val >= mul)
- val -= Math.pow(2, 8 * byteLength);
-
- return val;
-};
-
-Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) {
- offset = offset >>> 0;
- byteLength = byteLength >>> 0;
-
- if (!noAssert) {
- checkByteLength(byteLength);
- checkOffset(offset, byteLength, this.length);
- }
-
- var i = byteLength;
- var mul = 1;
- var val = this[offset + --i];
- while (i > 0 && (mul *= 0x100))
- val += this[offset + --i] * mul;
- mul *= 0x80;
-
- if (val >= mul)
- val -= Math.pow(2, 8 * byteLength);
-
- return val;
-};
-
-Buffer.prototype.readInt8 = function readInt8(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 1, this.length);
- var val = this[offset];
- return !(val & 0x80) ? val : (0xff - val + 1) * -1;
-};
-
-Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 2, this.length);
- var val = this[offset] | (this[offset + 1] << 8);
- return (val & 0x8000) ? val | 0xFFFF0000 : val;
-};
-
-Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 2, this.length);
- var val = this[offset + 1] | (this[offset] << 8);
- return (val & 0x8000) ? val | 0xFFFF0000 : val;
-};
-
-Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 4, this.length);
-
- return (this[offset]) |
- (this[offset + 1] << 8) |
- (this[offset + 2] << 16) |
- (this[offset + 3] << 24);
-};
-
-Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) {
- offset = offset >>> 0;
- if (!noAssert)
- checkOffset(offset, 4, this.length);
-
- return (this[offset] << 24) |
- (this[offset + 1] << 16) |
- (this[offset + 2] << 8) |
- (this[offset + 3]);
-};
-
-// For the casual reader who has not at the current time memorized the
-// IEEE-754 standard in full detail: floating point numbers consist of
-// a fraction, an exponent and a sign bit: 23+8+1 bits for single precision
-// numbers and 52+11+1 bits for double precision numbers.
-//
-// A zero exponent is either a positive or negative zero, if the fraction
-// is zero, or a denormalized number when it is non-zero. Multiplying the
-// fraction by the smallest possible denormal yields the denormalized number.
-//
-// An all-bits-one exponent is either a positive or negative infinity, if
-// the fraction is zero, or NaN when it is non-zero. The standard allows
-// both quiet and signaling NaNs but since NaN is a canonical value in
-// JavaScript, we cannot (and do not) distinguish between the two.
-//
-// Other exponents are regular numbers and are computed by subtracting the bias
-// from the exponent (127 for single precision, 1023 for double precision),
-// yielding an exponent in the ranges -126-127 and -1022-1024 respectively.
-//
-// Of interest is that the fraction of a normal number has an extra bit of
-// precision that is not stored but is reconstructed by adding one after
-// multiplying the fraction with the result of 2**-bits_in_fraction.
-
-function toDouble(x0, x1) {
- const frac = x0 + 0x100000000 * (x1 & 0xFFFFF);
- const expt = (x1 >>> 20) & 2047;
- const sign = (x1 >>> 31) ? -1 : 1;
- if (expt === 0) {
- if (frac === 0) return sign * 0;
- return sign * frac * 2 ** -1074;
- } else if (expt === 2047) {
- if (frac === 0) return sign * Infinity;
- return NaN;
- }
- return sign * 2 ** (expt - 1023) * (1 + frac * 2 ** -52);
-}
-
-function toFloat(x) {
- const frac = x & 0x7FFFFF;
- const expt = (x >>> 23) & 255;
- const sign = (x >>> 31) ? -1 : 1;
- if (expt === 0) {
- if (frac === 0) return sign * 0;
- return sign * frac * 2 ** -149;
- } else if (expt === 255) {
- if (frac === 0) return sign * Infinity;
- return NaN;
- }
- return sign * 2 ** (expt - 127) * (1 + frac * 2 ** -23);
-}
-
-Buffer.prototype.readDoubleBE = function(offset, noAssert) {
- offset = offset >>> 0;
- const x1 = this.readUInt32BE(offset + 0, noAssert);
- const x0 = this.readUInt32BE(offset + 4, noAssert);
- return toDouble(x0, x1);
-};
-
-Buffer.prototype.readDoubleLE = function(offset, noAssert) {
- offset = offset >>> 0;
- const x0 = this.readUInt32LE(offset + 0, noAssert);
- const x1 = this.readUInt32LE(offset + 4, noAssert);
- return toDouble(x0, x1);
-};
-
-Buffer.prototype.readFloatBE = function(offset, noAssert) {
- offset = offset >>> 0;
- return toFloat(this.readUInt32BE(offset, noAssert));
-};
-
-Buffer.prototype.readFloatLE = function(offset, noAssert) {
- offset = offset >>> 0;
- return toFloat(this.readUInt32LE(offset, noAssert));
-};
-
-function checkOOB(buffer, offset, ext) {
- if (offset + ext > buffer.length)
- throw new errors.RangeError('ERR_INDEX_OUT_OF_RANGE');
-}
-
-function checkInt(buffer, value, offset, ext, max, min) {
- if (value > max || value < min)
- throw new errors.RangeError('ERR_INVALID_OPT_VALUE', 'value', value);
- checkOOB(buffer, offset, ext);
-}
-
-Buffer.prototype.writeUIntLE =
- function writeUIntLE(value, offset, byteLength, noAssert) {
- value = +value;
- offset = offset >>> 0;
- byteLength = byteLength >>> 0;
- if (!noAssert) {
- const maxBytes = Math.pow(2, 8 * byteLength) - 1;
- checkInt(this, value, offset, byteLength, maxBytes, 0);
- }
-
- var mul = 1;
- var i = 0;
- this[offset] = value;
- while (++i < byteLength && (mul *= 0x100))
- this[offset + i] = (value / mul) >>> 0;
-
- return offset + byteLength;
- };
-
-Buffer.prototype.writeUIntBE =
- function writeUIntBE(value, offset, byteLength, noAssert) {
- value = +value;
- offset = offset >>> 0;
- byteLength = byteLength >>> 0;
- if (!noAssert) {
- const maxBytes = Math.pow(2, 8 * byteLength) - 1;
- checkInt(this, value, offset, byteLength, maxBytes, 0);
- }
-
- var i = byteLength - 1;
- var mul = 1;
- this[offset + i] = value;
- while (--i >= 0 && (mul *= 0x100))
- this[offset + i] = (value / mul) >>> 0;
-
- return offset + byteLength;
- };
-
-Buffer.prototype.writeUInt8 =
- function writeUInt8(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 1, 0xff, 0);
- this[offset] = value;
- return offset + 1;
- };
-
-Buffer.prototype.writeUInt16LE =
- function writeUInt16LE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 2, 0xffff, 0);
- this[offset] = value;
- this[offset + 1] = (value >>> 8);
- return offset + 2;
- };
-
-Buffer.prototype.writeUInt16BE =
- function writeUInt16BE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 2, 0xffff, 0);
- this[offset] = (value >>> 8);
- this[offset + 1] = value;
- return offset + 2;
- };
-
-Buffer.prototype.writeUInt32LE =
- function writeUInt32LE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 4, 0xffffffff, 0);
- this[offset + 3] = (value >>> 24);
- this[offset + 2] = (value >>> 16);
- this[offset + 1] = (value >>> 8);
- this[offset] = value;
- return offset + 4;
- };
-
-Buffer.prototype.writeUInt32BE =
- function writeUInt32BE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 4, 0xffffffff, 0);
- this[offset] = (value >>> 24);
- this[offset + 1] = (value >>> 16);
- this[offset + 2] = (value >>> 8);
- this[offset + 3] = value;
- return offset + 4;
- };
-
-Buffer.prototype.writeIntLE =
- function writeIntLE(value, offset, byteLength, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert) {
- checkInt(this,
- value,
- offset,
- byteLength,
- Math.pow(2, 8 * byteLength - 1) - 1,
- -Math.pow(2, 8 * byteLength - 1));
- }
-
- var i = 0;
- var mul = 1;
- var sub = 0;
- this[offset] = value;
- while (++i < byteLength && (mul *= 0x100)) {
- if (value < 0 && sub === 0 && this[offset + i - 1] !== 0)
- sub = 1;
- this[offset + i] = ((value / mul) >> 0) - sub;
- }
-
- return offset + byteLength;
- };
-
-Buffer.prototype.writeIntBE =
- function writeIntBE(value, offset, byteLength, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert) {
- checkInt(this,
- value,
- offset,
- byteLength,
- Math.pow(2, 8 * byteLength - 1) - 1,
- -Math.pow(2, 8 * byteLength - 1));
- }
-
- var i = byteLength - 1;
- var mul = 1;
- var sub = 0;
- this[offset + i] = value;
- while (--i >= 0 && (mul *= 0x100)) {
- if (value < 0 && sub === 0 && this[offset + i + 1] !== 0)
- sub = 1;
- this[offset + i] = ((value / mul) >> 0) - sub;
- }
-
- return offset + byteLength;
- };
-
-Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 1, 0x7f, -0x80);
- this[offset] = value;
- return offset + 1;
-};
-
-Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 2, 0x7fff, -0x8000);
- this[offset] = value;
- this[offset + 1] = (value >>> 8);
- return offset + 2;
-};
-
-Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 2, 0x7fff, -0x8000);
- this[offset] = (value >>> 8);
- this[offset + 1] = value;
- return offset + 2;
-};
-
-Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
- this[offset] = value;
- this[offset + 1] = (value >>> 8);
- this[offset + 2] = (value >>> 16);
- this[offset + 3] = (value >>> 24);
- return offset + 4;
-};
-
-Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) {
- value = +value;
- offset = offset >>> 0;
- if (!noAssert)
- checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
- this[offset] = (value >>> 24);
- this[offset + 1] = (value >>> 16);
- this[offset + 2] = (value >>> 8);
- this[offset + 3] = value;
- return offset + 4;
-};
-
-function writeDoubleForwards(val, offset, noAssert) {
- val = +val;
- offset = offset >>> 0;
- if (!noAssert)
- checkOOB(this, offset, 8);
-
- float64Array[0] = val;
- this[offset++] = uInt8Float64Array[0];
- this[offset++] = uInt8Float64Array[1];
- this[offset++] = uInt8Float64Array[2];
- this[offset++] = uInt8Float64Array[3];
- this[offset++] = uInt8Float64Array[4];
- this[offset++] = uInt8Float64Array[5];
- this[offset++] = uInt8Float64Array[6];
- this[offset++] = uInt8Float64Array[7];
- return offset;
-}
-
-function writeDoubleBackwards(val, offset, noAssert) {
- val = +val;
- offset = offset >>> 0;
- if (!noAssert)
- checkOOB(this, offset, 8);
-
- float64Array[0] = val;
- this[offset++] = uInt8Float64Array[7];
- this[offset++] = uInt8Float64Array[6];
- this[offset++] = uInt8Float64Array[5];
- this[offset++] = uInt8Float64Array[4];
- this[offset++] = uInt8Float64Array[3];
- this[offset++] = uInt8Float64Array[2];
- this[offset++] = uInt8Float64Array[1];
- this[offset++] = uInt8Float64Array[0];
- return offset;
-}
-
-function writeFloatForwards(val, offset, noAssert) {
- val = +val;
- offset = offset >>> 0;
- if (!noAssert)
- checkOOB(this, offset, 4);
-
- float32Array[0] = val;
- this[offset++] = uInt8Float32Array[0];
- this[offset++] = uInt8Float32Array[1];
- this[offset++] = uInt8Float32Array[2];
- this[offset++] = uInt8Float32Array[3];
- return offset;
-}
-
-function writeFloatBackwards(val, offset, noAssert) {
- val = +val;
- offset = offset >>> 0;
- if (!noAssert)
- checkOOB(this, offset, 4);
-
- float32Array[0] = val;
- this[offset++] = uInt8Float32Array[3];
- this[offset++] = uInt8Float32Array[2];
- this[offset++] = uInt8Float32Array[1];
- this[offset++] = uInt8Float32Array[0];
- return offset;
-}
-
-// Check endianness.
-float32Array[0] = -1;
-if (uInt8Float32Array[3] === 0) { // Big endian.
- Buffer.prototype.writeFloatLE = writeFloatBackwards;
- Buffer.prototype.writeFloatBE = writeFloatForwards;
- Buffer.prototype.writeDoubleLE = writeDoubleBackwards;
- Buffer.prototype.writeDoubleBE = writeDoubleForwards;
-} else { // Small endian.
- Buffer.prototype.writeFloatLE = writeFloatForwards;
- Buffer.prototype.writeFloatBE = writeFloatBackwards;
- Buffer.prototype.writeDoubleLE = writeDoubleForwards;
- Buffer.prototype.writeDoubleBE = writeDoubleBackwards;
-}
-
function swap(b, n, m) {
const i = b[n];
b[n] = b[m];
diff --git a/lib/internal/buffer.js b/lib/internal/buffer.js
index 105ff4132a..b5da69a5b3 100644
--- a/lib/internal/buffer.js
+++ b/lib/internal/buffer.js
@@ -1,13 +1,797 @@
'use strict';
const binding = process.binding('buffer');
+const { TypeError, RangeError } = require('internal/errors');
const { setupBufferJS } = binding;
// Remove from the binding so that function is only available as exported here.
// (That is, for internal use only.)
delete binding.setupBufferJS;
+// Temporary buffers to convert numbers.
+const float32Array = new Float32Array(1);
+const uInt8Float32Array = new Uint8Array(float32Array.buffer);
+const float64Array = new Float64Array(1);
+const uInt8Float64Array = new Uint8Array(float64Array.buffer);
+
+// Check endianness.
+float32Array[0] = -1;
+const bigEndian = uInt8Float32Array[3] === 0;
+
+function checkBounds(buf, offset, byteLength) {
+ checkNumberType(offset);
+ if (buf[offset] === undefined || buf[offset + byteLength] === undefined)
+ boundsError(offset, buf.length - (byteLength + 1));
+}
+
+function checkInt(value, min, max, buf, offset, byteLength) {
+ if (value > max || value < min) {
+ throw new RangeError('ERR_OUT_OF_RANGE',
+ 'value', `>= ${min} and <= ${max}`, value);
+ }
+ checkBounds(buf, offset, byteLength);
+}
+
+function checkNumberType(value, type) {
+ if (typeof value !== 'number') {
+ throw new TypeError('ERR_INVALID_ARG_TYPE',
+ type || 'offset', 'number', value);
+ }
+}
+
+function boundsError(value, length, type) {
+ if (Math.floor(value) !== value) {
+ checkNumberType(value, type);
+ throw new RangeError('ERR_OUT_OF_RANGE',
+ type || 'offset', 'an integer', value);
+ }
+
+ if (length < 0)
+ throw new RangeError('ERR_BUFFER_OUT_OF_BOUNDS', null, true);
+
+ throw new RangeError('ERR_OUT_OF_RANGE',
+ type || 'offset',
+ `>= ${type ? 1 : 0} and <= ${length}`,
+ value);
+}
+
+// Read integers.
+function readUIntLE(offset, byteLength) {
+ if (byteLength === 6)
+ return readUInt48LE(this, offset);
+ if (byteLength === 5)
+ return readUInt40LE(this, offset);
+ if (byteLength === 3)
+ return readUInt24LE(this, offset);
+ if (byteLength === 4)
+ return this.readUInt32LE(offset);
+ if (byteLength === 2)
+ return this.readUInt16LE(offset);
+ if (byteLength === 1)
+ return this.readUInt8(offset);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function readUInt48LE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 5];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 6);
+
+ return first +
+ buf[++offset] * 2 ** 8 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 24 +
+ (buf[++offset] + last * 2 ** 8) * 2 ** 32;
+}
+
+function readUInt40LE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 4];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 5);
+
+ return first +
+ buf[++offset] * 2 ** 8 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 24 +
+ last * 2 ** 32;
+}
+
+function readUInt32LE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 3];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 4);
+
+ return first +
+ this[++offset] * 2 ** 8 +
+ this[++offset] * 2 ** 16 +
+ last * 2 ** 24;
+}
+
+function readUInt24LE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 2];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 3);
+
+ return first + buf[++offset] * 2 ** 8 + last * 2 ** 16;
+}
+
+function readUInt16LE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 1];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 2);
+
+ return first + last * 2 ** 8;
+}
+
+function readUInt8(offset) {
+ checkNumberType(offset);
+ const val = this[offset];
+ if (val === undefined)
+ boundsError(offset, this.length - 1);
+
+ return val;
+}
+
+function readUIntBE(offset, byteLength) {
+ if (byteLength === 6)
+ return readUInt48BE(this, offset);
+ if (byteLength === 5)
+ return readUInt40BE(this, offset);
+ if (byteLength === 3)
+ return readUInt24BE(this, offset);
+ if (byteLength === 4)
+ return this.readUInt32BE(offset);
+ if (byteLength === 2)
+ return this.readUInt16BE(offset);
+ if (byteLength === 1)
+ return this.readUInt8(offset);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function readUInt48BE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 5];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 6);
+
+ return (first * 2 ** 8 + buf[++offset]) * 2 ** 32 +
+ buf[++offset] * 2 ** 24 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 8 +
+ last;
+}
+
+function readUInt40BE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 4];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 5);
+
+ return first * 2 ** 32 +
+ buf[++offset] * 2 ** 24 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 8 +
+ last;
+}
+
+function readUInt32BE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 3];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 4);
+
+ return first * 2 ** 24 +
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 8 +
+ last;
+}
+
+function readUInt24BE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 2];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 3);
+
+ return first * 2 ** 16 + buf[++offset] * 2 ** 8 + last;
+}
+
+function readUInt16BE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 1];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 2);
+
+ return first * 2 ** 8 + last;
+}
+
+function readIntLE(offset, byteLength) {
+ if (byteLength === 6)
+ return readInt48LE(this, offset);
+ if (byteLength === 5)
+ return readInt40LE(this, offset);
+ if (byteLength === 3)
+ return readInt24LE(this, offset);
+ if (byteLength === 4)
+ return this.readInt32LE(offset);
+ if (byteLength === 2)
+ return this.readInt16LE(offset);
+ if (byteLength === 1)
+ return this.readInt8(offset);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function readInt48LE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 5];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 6);
+
+ const val = buf[offset + 4] + last * 2 ** 8;
+ return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 +
+ first +
+ buf[++offset] * 2 ** 8 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 24;
+}
+
+function readInt40LE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 4];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 5);
+
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 +
+ first +
+ buf[++offset] * 2 ** 8 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 24;
+}
+
+function readInt32LE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 3];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 4);
+
+ return first +
+ this[++offset] * 2 ** 8 +
+ this[++offset] * 2 ** 16 +
+ (last << 24); // Overflow
+}
+
+function readInt24LE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 2];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 3);
+
+ const val = first + buf[++offset] * 2 ** 8 + last * 2 ** 16;
+ return val | (val & 2 ** 23) * 0x1fe;
+}
+
+function readInt16LE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 1];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 2);
+
+ const val = first + last * 2 ** 8;
+ return val | (val & 2 ** 15) * 0x1fffe;
+}
+
+function readInt8(offset) {
+ checkNumberType(offset);
+ const val = this[offset];
+ if (val === undefined)
+ boundsError(offset, this.length - 1);
+
+ return val | (val & 2 ** 7) * 0x1fffffe;
+}
+
+function readIntBE(offset, byteLength) {
+ if (byteLength === 6)
+ return readInt48BE(this, offset);
+ if (byteLength === 5)
+ return readInt40BE(this, offset);
+ if (byteLength === 3)
+ return readInt24BE(this, offset);
+ if (byteLength === 4)
+ return this.readInt32BE(offset);
+ if (byteLength === 2)
+ return this.readInt16BE(offset);
+ if (byteLength === 1)
+ return this.readInt8(offset);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function readInt48BE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 5];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 6);
+
+ const val = buf[++offset] + first * 2 ** 8;
+ return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 +
+ buf[++offset] * 2 ** 24 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 8 +
+ last;
+}
+
+function readInt40BE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 4];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 5);
+
+ return (first | (first & 2 ** 7) * 0x1fffffe) * 2 ** 32 +
+ buf[++offset] * 2 ** 24 +
+ buf[++offset] * 2 ** 16 +
+ buf[++offset] * 2 ** 8 +
+ last;
+}
+
+function readInt32BE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 3];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 4);
+
+ return (first << 24) + // Overflow
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 8 +
+ last;
+}
+
+function readInt24BE(buf, offset) {
+ checkNumberType(offset);
+ const first = buf[offset];
+ const last = buf[offset + 2];
+ if (first === undefined || last === undefined)
+ boundsError(offset, buf.length - 3);
+
+ const val = first * 2 ** 16 + buf[++offset] * 2 ** 8 + last;
+ return val | (val & 2 ** 23) * 0x1fe;
+}
+
+function readInt16BE(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 1];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 2);
+
+ const val = first * 2 ** 8 + last;
+ return val | (val & 2 ** 15) * 0x1fffe;
+}
+
+// Read floats
+function readFloatBackwards(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 3];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 4);
+
+ uInt8Float32Array[3] = first;
+ uInt8Float32Array[2] = this[++offset];
+ uInt8Float32Array[1] = this[++offset];
+ uInt8Float32Array[0] = last;
+ return float32Array[0];
+}
+
+function readFloatForwards(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 3];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 4);
+
+ uInt8Float32Array[0] = first;
+ uInt8Float32Array[1] = this[++offset];
+ uInt8Float32Array[2] = this[++offset];
+ uInt8Float32Array[3] = last;
+ return float32Array[0];
+}
+
+function readDoubleBackwards(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 7];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 8);
+
+ uInt8Float64Array[7] = first;
+ uInt8Float64Array[6] = this[++offset];
+ uInt8Float64Array[5] = this[++offset];
+ uInt8Float64Array[4] = this[++offset];
+ uInt8Float64Array[3] = this[++offset];
+ uInt8Float64Array[2] = this[++offset];
+ uInt8Float64Array[1] = this[++offset];
+ uInt8Float64Array[0] = last;
+ return float64Array[0];
+}
+
+function readDoubleForwards(offset) {
+ checkNumberType(offset);
+ const first = this[offset];
+ const last = this[offset + 7];
+ if (first === undefined || last === undefined)
+ boundsError(offset, this.length - 8);
+
+ uInt8Float64Array[0] = first;
+ uInt8Float64Array[1] = this[++offset];
+ uInt8Float64Array[2] = this[++offset];
+ uInt8Float64Array[3] = this[++offset];
+ uInt8Float64Array[4] = this[++offset];
+ uInt8Float64Array[5] = this[++offset];
+ uInt8Float64Array[6] = this[++offset];
+ uInt8Float64Array[7] = last;
+ return float64Array[0];
+}
+
+// Write integers.
+function writeUIntLE(value, offset, byteLength) {
+ if (byteLength === 6)
+ return writeU_Int48LE(this, value, offset, 0, 0xffffffffffff);
+ if (byteLength === 5)
+ return writeU_Int40LE(this, value, offset, 0, 0xffffffffff);
+ if (byteLength === 3)
+ return writeU_Int24LE(this, value, offset, 0, 0xffffff);
+ if (byteLength === 4)
+ return writeU_Int32LE(this, value, offset, 0, 0xffffffff);
+ if (byteLength === 2)
+ return writeU_Int16LE(this, value, offset, 0, 0xffff);
+ if (byteLength === 1)
+ return writeU_Int8(this, value, offset, 0, 0xff);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function writeU_Int48LE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 5);
+
+ const newVal = Math.floor(value * 2 ** -32);
+ buf[offset++] = value;
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 24);
+ buf[offset++] = newVal;
+ buf[offset++] = (newVal >>> 8);
+ return offset;
+}
+
+function writeU_Int40LE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 4);
+
+ const newVal = value;
+ buf[offset++] = value;
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 24);
+ buf[offset++] = Math.floor(newVal * 2 ** -32);
+ return offset;
+}
+
+function writeU_Int32LE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 3);
+
+ buf[offset++] = value;
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 24);
+ return offset;
+}
+
+function writeUInt32LE(value, offset) {
+ return writeU_Int32LE(this, value, offset, 0, 0xffffffff);
+}
+
+function writeU_Int24LE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 2);
+
+ buf[offset++] = value;
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = (value >>> 16);
+ return offset;
+}
+
+function writeU_Int16LE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 1);
+
+ buf[offset++] = value;
+ buf[offset++] = (value >>> 8);
+ return offset;
+}
+
+function writeUInt16LE(value, offset) {
+ return writeU_Int16LE(this, value, offset, 0, 0xffff);
+}
+
+function writeU_Int8(buf, value, offset, min, max) {
+ value = +value;
+ // `checkInt()` can not be used here because it checks two entries.
+ checkNumberType(offset);
+ if (value > max || value < min) {
+ throw new RangeError('ERR_OUT_OF_RANGE',
+ 'value',
+ `>= ${min} and <= ${max}`, value);
+ }
+ if (buf[offset] === undefined)
+ boundsError(offset, buf.length - 1);
+
+ buf[offset] = value;
+ return offset + 1;
+}
+
+function writeUInt8(value, offset) {
+ return writeU_Int8(this, value, offset, 0, 0xff);
+}
+
+function writeUIntBE(value, offset, byteLength) {
+ if (byteLength === 6)
+ return writeU_Int48BE(this, value, offset, 0, 0xffffffffffffff);
+ if (byteLength === 5)
+ return writeU_Int40BE(this, value, offset, 0, 0xffffffffff);
+ if (byteLength === 3)
+ return writeU_Int24BE(this, value, offset, 0, 0xffffff);
+ if (byteLength === 4)
+ return writeU_Int32BE(this, value, offset, 0, 0xffffffff);
+ if (byteLength === 2)
+ return writeU_Int16BE(this, value, offset, 0, 0xffff);
+ if (byteLength === 1)
+ return writeU_Int8(this, value, offset, 0, 0xff);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function writeU_Int48BE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 5);
+
+ const newVal = Math.floor(value * 2 ** -32);
+ buf[offset++] = (newVal >>> 8);
+ buf[offset++] = newVal;
+ buf[offset++] = (value >>> 24);
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = value;
+ return offset;
+}
+
+function writeU_Int40BE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 4);
+
+ buf[offset++] = Math.floor(value * 2 ** -32);
+ buf[offset++] = (value >>> 24);
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = value;
+ return offset;
+}
+
+function writeU_Int32BE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 3);
+
+ buf[offset++] = (value >>> 24);
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = value;
+ return offset;
+}
+
+function writeUInt32BE(value, offset) {
+ return writeU_Int32BE(this, value, offset, 0, 0xffffffff);
+}
+
+function writeU_Int24BE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 2);
+
+ buf[offset++] = (value >>> 16);
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = value;
+ return offset;
+}
+
+function writeU_Int16BE(buf, value, offset, min, max) {
+ value = +value;
+ checkInt(value, min, max, buf, offset, 1);
+
+ buf[offset++] = (value >>> 8);
+ buf[offset++] = value;
+ return offset;
+}
+
+function writeUInt16BE(value, offset) {
+ return writeU_Int16BE(this, value, offset, 0, 0xffffffff);
+}
+
+function writeIntLE(value, offset, byteLength) {
+ if (byteLength === 6)
+ return writeU_Int48LE(this, value, offset, -0x800000000000, 0x7fffffffffff);
+ if (byteLength === 5)
+ return writeU_Int40LE(this, value, offset, -0x8000000000, 0x7fffffffff);
+ if (byteLength === 3)
+ return writeU_Int24LE(this, value, offset, -0x800000, 0x7fffff);
+ if (byteLength === 4)
+ return writeU_Int32LE(this, value, offset, -0x80000000, 0x7fffffff);
+ if (byteLength === 2)
+ return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff);
+ if (byteLength === 1)
+ return writeU_Int8(this, value, offset, -0x80, 0x7f);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function writeInt32LE(value, offset) {
+ return writeU_Int32LE(this, value, offset, -0x80000000, 0x7fffffff);
+}
+
+function writeInt16LE(value, offset) {
+ return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff);
+}
+
+function writeInt8(value, offset) {
+ return writeU_Int8(this, value, offset, -0x80, 0x7f);
+}
+
+function writeIntBE(value, offset, byteLength) {
+ if (byteLength === 6)
+ return writeU_Int48BE(this, value, offset, -0x800000000000, 0x7fffffffffff);
+ if (byteLength === 5)
+ return writeU_Int40BE(this, value, offset, -0x8000000000, 0x7fffffffff);
+ if (byteLength === 3)
+ return writeU_Int24BE(this, value, offset, -0x800000, 0x7fffff);
+ if (byteLength === 4)
+ return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff);
+ if (byteLength === 2)
+ return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff);
+ if (byteLength === 1)
+ return writeU_Int8(this, value, offset, -0x80, 0x7f);
+
+ boundsError(byteLength, 6, 'byteLength');
+}
+
+function writeInt32BE(value, offset) {
+ return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff);
+}
+
+function writeInt16BE(value, offset) {
+ return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff);
+}
+
+// Write floats.
+function writeDoubleForwards(val, offset) {
+ val = +val;
+ checkBounds(this, offset, 7);
+
+ float64Array[0] = val;
+ this[offset++] = uInt8Float64Array[0];
+ this[offset++] = uInt8Float64Array[1];
+ this[offset++] = uInt8Float64Array[2];
+ this[offset++] = uInt8Float64Array[3];
+ this[offset++] = uInt8Float64Array[4];
+ this[offset++] = uInt8Float64Array[5];
+ this[offset++] = uInt8Float64Array[6];
+ this[offset++] = uInt8Float64Array[7];
+ return offset;
+}
+
+function writeDoubleBackwards(val, offset) {
+ val = +val;
+ checkBounds(this, offset, 7);
+
+ float64Array[0] = val;
+ this[offset++] = uInt8Float64Array[7];
+ this[offset++] = uInt8Float64Array[6];
+ this[offset++] = uInt8Float64Array[5];
+ this[offset++] = uInt8Float64Array[4];
+ this[offset++] = uInt8Float64Array[3];
+ this[offset++] = uInt8Float64Array[2];
+ this[offset++] = uInt8Float64Array[1];
+ this[offset++] = uInt8Float64Array[0];
+ return offset;
+}
+
+function writeFloatForwards(val, offset) {
+ val = +val;
+ checkBounds(this, offset, 3);
+
+ float32Array[0] = val;
+ this[offset++] = uInt8Float32Array[0];
+ this[offset++] = uInt8Float32Array[1];
+ this[offset++] = uInt8Float32Array[2];
+ this[offset++] = uInt8Float32Array[3];
+ return offset;
+}
+
+function writeFloatBackwards(val, offset) {
+ val = +val;
+ checkBounds(this, offset, 3);
+
+ float32Array[0] = val;
+ this[offset++] = uInt8Float32Array[3];
+ this[offset++] = uInt8Float32Array[2];
+ this[offset++] = uInt8Float32Array[1];
+ this[offset++] = uInt8Float32Array[0];
+ return offset;
+}
+
// FastBuffer wil be inserted here by lib/buffer.js
module.exports = {
- setupBufferJS
+ setupBufferJS,
+ // Container to export all read write functions.
+ readWrites: {
+ readUIntLE,
+ readUInt32LE,
+ readUInt16LE,
+ readUInt8,
+ readUIntBE,
+ readUInt32BE,
+ readUInt16BE,
+ readIntLE,
+ readInt32LE,
+ readInt16LE,
+ readInt8,
+ readIntBE,
+ readInt32BE,
+ readInt16BE,
+ writeUIntLE,
+ writeUInt32LE,
+ writeUInt16LE,
+ writeUInt8,
+ writeUIntBE,
+ writeUInt32BE,
+ writeUInt16BE,
+ writeIntLE,
+ writeInt32LE,
+ writeInt16LE,
+ writeInt8,
+ writeIntBE,
+ writeInt32BE,
+ writeInt16BE,
+ readFloatLE: bigEndian ? readFloatBackwards : readFloatForwards,
+ readFloatBE: bigEndian ? readFloatForwards : readFloatBackwards,
+ readDoubleLE: bigEndian ? readDoubleBackwards : readDoubleForwards,
+ readDoubleBE: bigEndian ? readDoubleForwards : readDoubleBackwards,
+ writeFloatLE: bigEndian ? writeFloatBackwards : writeFloatForwards,
+ writeFloatBE: bigEndian ? writeFloatForwards : writeFloatBackwards,
+ writeDoubleLE: bigEndian ? writeDoubleBackwards : writeDoubleForwards,
+ writeDoubleBE: bigEndian ? writeDoubleForwards : writeDoubleBackwards
+ }
};