|
|
|
/* eslint-disable require-buffer */
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const binding = process.binding('buffer');
|
|
|
|
const { compare: compare_, compareOffset } = binding;
|
|
|
|
const { isArrayBuffer, isSharedArrayBuffer } = process.binding('util');
|
|
|
|
const bindingObj = {};
|
|
|
|
const internalUtil = require('internal/util');
|
|
|
|
|
|
|
|
class FastBuffer extends Uint8Array {
|
|
|
|
constructor(arg1, arg2, arg3) {
|
|
|
|
super(arg1, arg2, arg3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FastBuffer.prototype.constructor = Buffer;
|
|
|
|
Buffer.prototype = FastBuffer.prototype;
|
|
|
|
|
|
|
|
exports.Buffer = Buffer;
|
|
|
|
exports.SlowBuffer = SlowBuffer;
|
|
|
|
exports.INSPECT_MAX_BYTES = 50;
|
|
|
|
exports.kMaxLength = binding.kMaxLength;
|
|
|
|
|
|
|
|
const kFromErrorMsg = 'First argument must be a string, Buffer, ' +
|
|
|
|
'ArrayBuffer, Array, or array-like object.';
|
|
|
|
|
|
|
|
Buffer.poolSize = 8 * 1024;
|
|
|
|
var poolSize, poolOffset, allocPool;
|
|
|
|
|
|
|
|
|
|
|
|
binding.setupBufferJS(Buffer.prototype, bindingObj);
|
|
|
|
|
|
|
|
const flags = bindingObj.flags;
|
|
|
|
const kNoZeroFill = 0;
|
|
|
|
|
|
|
|
function createUnsafeBuffer(size) {
|
|
|
|
flags[kNoZeroFill] = 1;
|
|
|
|
try {
|
|
|
|
return new FastBuffer(size);
|
|
|
|
} finally {
|
|
|
|
flags[kNoZeroFill] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function createPool() {
|
|
|
|
poolSize = Buffer.poolSize;
|
|
|
|
allocPool = createUnsafeBuffer(poolSize);
|
|
|
|
poolOffset = 0;
|
|
|
|
}
|
|
|
|
createPool();
|
|
|
|
|
|
|
|
|
|
|
|
function alignPool() {
|
|
|
|
// Ensure aligned slices
|
|
|
|
if (poolOffset & 0x7) {
|
|
|
|
poolOffset |= 0x7;
|
|
|
|
poolOffset++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The Buffer() construtor is "soft deprecated" ... that is, it is deprecated
|
|
|
|
* in the documentation and should not be used moving forward. Rather,
|
|
|
|
* developers should use one of the three new factory APIs: Buffer.from(),
|
|
|
|
* Buffer.allocUnsafe() or Buffer.alloc() based on their specific needs. There
|
|
|
|
* is no hard deprecation because of the extent to which the Buffer constructor
|
|
|
|
* is used in the ecosystem currently -- a hard deprecation would introduce too
|
|
|
|
* much breakage at this time. It's not likely that the Buffer constructors
|
|
|
|
* would ever actually be removed.
|
|
|
|
**/
|
|
|
|
function Buffer(arg, encodingOrOffset, length) {
|
|
|
|
// Common case.
|
|
|
|
if (typeof arg === 'number') {
|
|
|
|
if (typeof encodingOrOffset === 'string') {
|
|
|
|
throw new Error(
|
|
|
|
'If encoding is specified then the first argument must be a string'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Buffer.allocUnsafe(arg);
|
|
|
|
}
|
|
|
|
return Buffer.from(arg, encodingOrOffset, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
|
|
|
|
* if value is a number.
|
|
|
|
* Buffer.from(str[, encoding])
|
|
|
|
* Buffer.from(array)
|
|
|
|
* Buffer.from(buffer)
|
|
|
|
* Buffer.from(arrayBuffer[, byteOffset[, length]])
|
|
|
|
**/
|
|
|
|
Buffer.from = function(value, encodingOrOffset, length) {
|
|
|
|
if (typeof value === 'number')
|
|
|
|
throw new TypeError('"value" argument must not be a number');
|
|
|
|
|
|
|
|
if (isArrayBuffer(value) || isSharedArrayBuffer(value))
|
|
|
|
return fromArrayBuffer(value, encodingOrOffset, length);
|
|
|
|
|
|
|
|
if (typeof value === 'string')
|
|
|
|
return fromString(value, encodingOrOffset);
|
|
|
|
|
|
|
|
return fromObject(value);
|
|
|
|
};
|
|
|
|
|
|
|
|
Object.setPrototypeOf(Buffer, Uint8Array);
|
|
|
|
|
|
|
|
function assertSize(size) {
|
|
|
|
if (typeof size !== 'number') {
|
|
|
|
const err = new TypeError('"size" argument must be a number');
|
|
|
|
// The following hides the 'assertSize' method from the
|
|
|
|
// callstack. This is done simply to hide the internal
|
|
|
|
// details of the implementation from bleeding out to users.
|
|
|
|
Error.captureStackTrace(err, assertSize);
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new filled Buffer instance.
|
|
|
|
* alloc(size[, fill[, encoding]])
|
|
|
|
**/
|
|
|
|
Buffer.alloc = function(size, fill, encoding) {
|
|
|
|
assertSize(size);
|
|
|
|
if (size > 0 && fill !== undefined) {
|
|
|
|
// Since we are filling anyway, don't zero fill initially.
|
|
|
|
// Only pay attention to encoding if it's a string. This
|
|
|
|
// prevents accidentally sending in a number that would
|
|
|
|
// be interpretted as a start offset.
|
|
|
|
if (typeof encoding !== 'string')
|
|
|
|
encoding = undefined;
|
|
|
|
return createUnsafeBuffer(size).fill(fill, encoding);
|
|
|
|
}
|
|
|
|
return new FastBuffer(size);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer
|
|
|
|
* instance. If `--zero-fill-buffers` is set, will zero-fill the buffer.
|
|
|
|
**/
|
|
|
|
Buffer.allocUnsafe = function(size) {
|
|
|
|
assertSize(size);
|
|
|
|
return allocate(size);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled
|
|
|
|
* Buffer instance that is not allocated off the pre-initialized pool.
|
|
|
|
* If `--zero-fill-buffers` is set, will zero-fill the buffer.
|
|
|
|
**/
|
|
|
|
Buffer.allocUnsafeSlow = function(size) {
|
|
|
|
assertSize(size);
|
|
|
|
return createUnsafeBuffer(size);
|
|
|
|
};
|
|
|
|
|
|
|
|
// If --zero-fill-buffers command line argument is set, a zero-filled
|
|
|
|
// buffer is returned.
|
|
|
|
function SlowBuffer(length) {
|
|
|
|
if (+length != length)
|
|
|
|
length = 0;
|
|
|
|
return createUnsafeBuffer(+length);
|
|
|
|
}
|
|
|
|
|
|
|
|
Object.setPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype);
|
|
|
|
Object.setPrototypeOf(SlowBuffer, Uint8Array);
|
|
|
|
|
|
|
|
|
|
|
|
function allocate(size) {
|
|
|
|
if (size <= 0) {
|
|
|
|
return new FastBuffer();
|
|
|
|
}
|
|
|
|
if (size < (Buffer.poolSize >>> 1)) {
|
|
|
|
if (size > (poolSize - poolOffset))
|
|
|
|
createPool();
|
|
|
|
var b = allocPool.slice(poolOffset, poolOffset + size);
|
|
|
|
poolOffset += size;
|
|
|
|
alignPool();
|
|
|
|
return b;
|
|
|
|
} else {
|
|
|
|
// Even though this is checked above, the conditional is a safety net and
|
|
|
|
// sanity check to prevent any subsequent typed array allocation from not
|
|
|
|
// being zero filled.
|
|
|
|
return createUnsafeBuffer(size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function fromString(string, encoding) {
|
|
|
|
if (typeof encoding !== 'string' || encoding === '')
|
|
|
|
encoding = 'utf8';
|
|
|
|
|
|
|
|
if (!Buffer.isEncoding(encoding))
|
|
|
|
throw new TypeError('"encoding" must be a valid string encoding');
|
|
|
|
|
|
|
|
if (string.length === 0)
|
|
|
|
return new FastBuffer();
|
|
|
|
|
|
|
|
var length = byteLength(string, encoding);
|
|
|
|
|
|
|
|
if (length >= (Buffer.poolSize >>> 1))
|
|
|
|
return binding.createFromString(string, encoding);
|
|
|
|
|
|
|
|
if (length > (poolSize - poolOffset))
|
|
|
|
createPool();
|
|
|
|
var actual = allocPool.write(string, poolOffset, encoding);
|
|
|
|
var b = allocPool.slice(poolOffset, poolOffset + actual);
|
|
|
|
poolOffset += actual;
|
|
|
|
alignPool();
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
function fromArrayLike(obj) {
|
|
|
|
const length = obj.length;
|
|
|
|
const b = allocate(length);
|
|
|
|
for (var i = 0; i < length; i++)
|
|
|
|
b[i] = obj[i];
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
function fromArrayBuffer(obj, byteOffset, length) {
|
buffer: convert offset & length to int properly
As per ecma-262 2015's #sec-%typedarray%-buffer-byteoffset-length,
`offset` would be an integer, not a 32 bit unsigned integer. Also,
`length` would be an integer with the maximum value of 2^53 - 1, not a
32 bit unsigned integer.
This would be a problem because, if we create a buffer from an
arraybuffer, from an offset which is greater than 2^32, it would be
actually pointing to a different location in arraybuffer. For example,
if we use 2^40 as offset, then the actual value used will be 0,
because `byteOffset >>>= 0` will convert `byteOffset` to a 32 bit
unsigned int, which is based on 2^32 modulo.
This is a redo, as the ca37fa527f174b547893817fe8c67a3befa02317 broke
CI.
Refer: https://github.com/nodejs/node/pull/9814
Refer: https://github.com/nodejs/node/pull/9492
PR-URL: https://github.com/nodejs/node/pull/9815
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Backport-Of: https://github.com/nodejs/node/pull/9815
PR-URL: https://github.com/nodejs/node/pull/11176
Reviewed-By: James M Snell <jasnell@gmail.com>
8 years ago
|
|
|
byteOffset = internalUtil.toInteger(byteOffset);
|
|
|
|
|
|
|
|
const maxLength = obj.byteLength - byteOffset;
|
|
|
|
|
|
|
|
if (maxLength < 0)
|
|
|
|
throw new RangeError("'offset' is out of bounds");
|
|
|
|
|
|
|
|
if (length === undefined) {
|
|
|
|
length = maxLength;
|
|
|
|
} else {
|
buffer: convert offset & length to int properly
As per ecma-262 2015's #sec-%typedarray%-buffer-byteoffset-length,
`offset` would be an integer, not a 32 bit unsigned integer. Also,
`length` would be an integer with the maximum value of 2^53 - 1, not a
32 bit unsigned integer.
This would be a problem because, if we create a buffer from an
arraybuffer, from an offset which is greater than 2^32, it would be
actually pointing to a different location in arraybuffer. For example,
if we use 2^40 as offset, then the actual value used will be 0,
because `byteOffset >>>= 0` will convert `byteOffset` to a 32 bit
unsigned int, which is based on 2^32 modulo.
This is a redo, as the ca37fa527f174b547893817fe8c67a3befa02317 broke
CI.
Refer: https://github.com/nodejs/node/pull/9814
Refer: https://github.com/nodejs/node/pull/9492
PR-URL: https://github.com/nodejs/node/pull/9815
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Backport-Of: https://github.com/nodejs/node/pull/9815
PR-URL: https://github.com/nodejs/node/pull/11176
Reviewed-By: James M Snell <jasnell@gmail.com>
8 years ago
|
|
|
length = internalUtil.toLength(length);
|
|
|
|
if (length > maxLength)
|
|
|
|
throw new RangeError("'length' is out of bounds");
|
|
|
|
}
|
|
|
|
|
|
|
|
return new FastBuffer(obj, byteOffset, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
function fromObject(obj) {
|
|
|
|
if (obj instanceof Buffer) {
|
|
|
|
const b = allocate(obj.length);
|
|
|
|
|
|
|
|
if (b.length === 0)
|
|
|
|
return b;
|
|
|
|
|
|
|
|
obj.copy(b, 0, 0, obj.length);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj) {
|
|
|
|
if ('length' in obj || isArrayBuffer(obj.buffer) ||
|
|
|
|
isSharedArrayBuffer(obj.buffer)) {
|
|
|
|
if (typeof obj.length !== 'number' || obj.length !== obj.length) {
|
|
|
|
return new FastBuffer();
|
|
|
|
}
|
|
|
|
return fromArrayLike(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
|
|
|
|
return fromArrayLike(obj.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new TypeError(kFromErrorMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Static methods
|
|
|
|
|
|
|
|
Buffer.isBuffer = function isBuffer(b) {
|
|
|
|
return b instanceof Buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.compare = function compare(a, b) {
|
|
|
|
if (!(a instanceof Buffer) ||
|
|
|
|
!(b instanceof Buffer)) {
|
|
|
|
throw new TypeError('Arguments must be Buffers');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a === b) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return binding.compare(a, b);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.isEncoding = function(encoding) {
|
|
|
|
return typeof encoding === 'string' &&
|
|
|
|
typeof internalUtil.normalizeEncoding(encoding) === 'string';
|
|
|
|
};
|
|
|
|
Buffer[internalUtil.kIsEncodingSymbol] = Buffer.isEncoding;
|
|
|
|
|
|
|
|
Buffer.concat = function(list, length) {
|
|
|
|
var i;
|
|
|
|
if (!Array.isArray(list))
|
|
|
|
throw new TypeError('"list" argument must be an Array of Buffers');
|
|
|
|
|
|
|
|
if (list.length === 0)
|
|
|
|
return new FastBuffer();
|
|
|
|
|
|
|
|
if (length === undefined) {
|
|
|
|
length = 0;
|
|
|
|
for (i = 0; i < list.length; i++)
|
|
|
|
length += list[i].length;
|
|
|
|
} else {
|
|
|
|
length = length >>> 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
var buffer = Buffer.allocUnsafe(length);
|
|
|
|
var pos = 0;
|
|
|
|
for (i = 0; i < list.length; i++) {
|
|
|
|
var buf = list[i];
|
|
|
|
if (!Buffer.isBuffer(buf))
|
|
|
|
throw new TypeError('"list" argument must be an Array of Buffers');
|
|
|
|
buf.copy(buffer, pos);
|
|
|
|
pos += buf.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note: `length` is always equal to `buffer.length` at this point
|
|
|
|
if (pos < length) {
|
|
|
|
// Zero-fill the remaining bytes if the specified `length` was more than
|
|
|
|
// the actual total length, i.e. if we have some remaining allocated bytes
|
|
|
|
// there were not initialized.
|
|
|
|
buffer.fill(0, pos, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function base64ByteLength(str, bytes) {
|
|
|
|
// Handle padding
|
|
|
|
if (str.charCodeAt(bytes - 1) === 0x3D)
|
|
|
|
bytes--;
|
|
|
|
if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3D)
|
|
|
|
bytes--;
|
|
|
|
|
|
|
|
// Base64 ratio: 3/4
|
|
|
|
return (bytes * 3) >>> 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function byteLength(string, encoding) {
|
|
|
|
if (typeof string !== 'string') {
|
|
|
|
if (ArrayBuffer.isView(string) || isArrayBuffer(string) ||
|
|
|
|
isSharedArrayBuffer(string)) {
|
|
|
|
return string.byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
string = '' + string;
|
|
|
|
}
|
|
|
|
|
|
|
|
var len = string.length;
|
|
|
|
if (len === 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Use a for loop to avoid recursion
|
|
|
|
var loweredCase = false;
|
|
|
|
for (;;) {
|
|
|
|
switch (encoding) {
|
|
|
|
case 'ascii':
|
|
|
|
case 'latin1':
|
|
|
|
case 'binary':
|
|
|
|
return len;
|
|
|
|
|
|
|
|
case 'utf8':
|
|
|
|
case 'utf-8':
|
|
|
|
case undefined:
|
|
|
|
return binding.byteLengthUtf8(string);
|
|
|
|
|
|
|
|
case 'ucs2':
|
|
|
|
case 'ucs-2':
|
|
|
|
case 'utf16le':
|
|
|
|
case 'utf-16le':
|
|
|
|
return len * 2;
|
|
|
|
|
|
|
|
case 'hex':
|
|
|
|
return len >>> 1;
|
|
|
|
|
|
|
|
case 'base64':
|
|
|
|
return base64ByteLength(string, len);
|
|
|
|
|
|
|
|
default:
|
|
|
|
// The C++ binding defaulted to UTF8, we should too.
|
|
|
|
if (loweredCase)
|
|
|
|
return binding.byteLengthUtf8(string);
|
|
|
|
|
|
|
|
encoding = ('' + encoding).toLowerCase();
|
|
|
|
loweredCase = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer.byteLength = byteLength;
|
|
|
|
|
|
|
|
|
|
|
|
// For backwards compatibility.
|
|
|
|
Object.defineProperty(Buffer.prototype, 'parent', {
|
|
|
|
enumerable: true,
|
|
|
|
get: function() {
|
|
|
|
if (!(this instanceof Buffer))
|
|
|
|
return undefined;
|
|
|
|
if (this.byteLength === 0 ||
|
|
|
|
this.byteLength === this.buffer.byteLength) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
return this.buffer;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Object.defineProperty(Buffer.prototype, 'offset', {
|
|
|
|
enumerable: true,
|
|
|
|
get: function() {
|
|
|
|
if (!(this instanceof Buffer))
|
|
|
|
return undefined;
|
|
|
|
return this.byteOffset;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function slowToString(encoding, start, end) {
|
|
|
|
var loweredCase = false;
|
|
|
|
|
|
|
|
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
|
|
|
|
// property of a typed array.
|
|
|
|
|
|
|
|
// This behaves neither like String nor Uint8Array in that we set start/end
|
|
|
|
// to their upper/lower bounds if the value passed is out of range.
|
|
|
|
// undefined is handled specially as per ECMA-262 6th Edition,
|
|
|
|
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
|
|
|
|
if (start === undefined || start < 0)
|
|
|
|
start = 0;
|
|
|
|
// Return early if start > this.length. Done here to prevent potential uint32
|
|
|
|
// coercion fail below.
|
|
|
|
if (start > this.length)
|
|
|
|
return '';
|
|
|
|
|
|
|
|
if (end === undefined || end > this.length)
|
|
|
|
end = this.length;
|
|
|
|
|
|
|
|
if (end <= 0)
|
|
|
|
return '';
|
|
|
|
|
|
|
|
// Force coersion to uint32. This will also coerce falsey/NaN values to 0.
|
|
|
|
end >>>= 0;
|
|
|
|
start >>>= 0;
|
|
|
|
|
|
|
|
if (end <= start)
|
|
|
|
return '';
|
|
|
|
|
|
|
|
if (!encoding) encoding = 'utf8';
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
switch (encoding) {
|
|
|
|
case 'hex':
|
|
|
|
return this.hexSlice(start, end);
|
|
|
|
|
|
|
|
case 'utf8':
|
|
|
|
case 'utf-8':
|
|
|
|
return this.utf8Slice(start, end);
|
|
|
|
|
|
|
|
case 'ascii':
|
|
|
|
return this.asciiSlice(start, end);
|
|
|
|
|
|
|
|
case 'latin1':
|
|
|
|
case 'binary':
|
|
|
|
return this.latin1Slice(start, end);
|
|
|
|
|
|
|
|
case 'base64':
|
|
|
|
return this.base64Slice(start, end);
|
|
|
|
|
|
|
|
case 'ucs2':
|
|
|
|
case 'ucs-2':
|
|
|
|
case 'utf16le':
|
|
|
|
case 'utf-16le':
|
|
|
|
return this.ucs2Slice(start, end);
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (loweredCase)
|
|
|
|
throw new TypeError('Unknown encoding: ' + encoding);
|
|
|
|
encoding = (encoding + '').toLowerCase();
|
|
|
|
loweredCase = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.toString = function() {
|
|
|
|
let result;
|
|
|
|
if (arguments.length === 0) {
|
|
|
|
result = this.utf8Slice(0, this.length);
|
|
|
|
} else {
|
|
|
|
result = slowToString.apply(this, arguments);
|
|
|
|
}
|
|
|
|
if (result === undefined)
|
|
|
|
throw new Error('"toString()" failed');
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.equals = function equals(b) {
|
|
|
|
if (!(b instanceof Buffer))
|
|
|
|
throw new TypeError('Argument must be a Buffer');
|
|
|
|
|
|
|
|
if (this === b)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return binding.compare(this, b) === 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Override how buffers are presented by util.inspect().
|
|
|
|
Buffer.prototype[internalUtil.customInspectSymbol] = function inspect() {
|
|
|
|
var str = '';
|
|
|
|
var max = exports.INSPECT_MAX_BYTES;
|
|
|
|
if (this.length > 0) {
|
|
|
|
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ');
|
|
|
|
if (this.length > max)
|
|
|
|
str += ' ... ';
|
|
|
|
}
|
|
|
|
return '<' + this.constructor.name + ' ' + str + '>';
|
|
|
|
};
|
|
|
|
Buffer.prototype.inspect = Buffer.prototype[internalUtil.customInspectSymbol];
|
|
|
|
|
|
|
|
Buffer.prototype.compare = function compare(target,
|
|
|
|
start,
|
|
|
|
end,
|
|
|
|
thisStart,
|
|
|
|
thisEnd) {
|
|
|
|
|
|
|
|
if (!(target instanceof Buffer))
|
|
|
|
throw new TypeError('Argument must be a Buffer');
|
|
|
|
if (arguments.length === 1)
|
|
|
|
return compare_(this, target);
|
|
|
|
|
|
|
|
if (start === undefined)
|
|
|
|
start = 0;
|
|
|
|
else if (start < 0)
|
|
|
|
throw new RangeError('out of range index');
|
|
|
|
else
|
|
|
|
start >>>= 0;
|
|
|
|
|
|
|
|
if (end === undefined)
|
|
|
|
end = target.length;
|
|
|
|
else if (end > target.length)
|
|
|
|
throw new RangeError('out of range index');
|
|
|
|
else
|
|
|
|
end >>>= 0;
|
|
|
|
|
|
|
|
if (thisStart === undefined)
|
|
|
|
thisStart = 0;
|
|
|
|
else if (thisStart < 0)
|
|
|
|
throw new RangeError('out of range index');
|
|
|
|
else
|
|
|
|
thisStart >>>= 0;
|
|
|
|
|
|
|
|
if (thisEnd === undefined)
|
|
|
|
thisEnd = this.length;
|
|
|
|
else if (thisEnd > this.length)
|
|
|
|
throw new RangeError('out of range index');
|
|
|
|
else
|
|
|
|
thisEnd >>>= 0;
|
|
|
|
|
|
|
|
if (thisStart >= thisEnd)
|
|
|
|
return (start >= end ? 0 : -1);
|
|
|
|
else if (start >= end)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return compareOffset(this, target, start, thisStart, end, thisEnd);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
|
|
|
|
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
|
|
|
|
//
|
|
|
|
// Arguments:
|
|
|
|
// - buffer - a Buffer to search
|
|
|
|
// - val - a string, Buffer, or number
|
|
|
|
// - byteOffset - an index into `buffer`; will be clamped to an int32
|
|
|
|
// - encoding - an optional encoding, relevant is val is a string
|
|
|
|
// - dir - true for indexOf, false for lastIndexOf
|
|
|
|
function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
|
|
|
|
if (typeof byteOffset === 'string') {
|
|
|
|
encoding = byteOffset;
|
|
|
|
byteOffset = undefined;
|
|
|
|
} else if (byteOffset > 0x7fffffff) {
|
|
|
|
byteOffset = 0x7fffffff;
|
|
|
|
} else if (byteOffset < -0x80000000) {
|
|
|
|
byteOffset = -0x80000000;
|
|
|
|
}
|
|
|
|
// Coerce to Number. Values like null and [] become 0.
|
|
|
|
byteOffset = +byteOffset;
|
|
|
|
// If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer.
|
|
|
|
if (Number.isNaN(byteOffset)) {
|
|
|
|
byteOffset = dir ? 0 : (buffer.length - 1);
|
|
|
|
}
|
|
|
|
dir = !!dir; // Cast to bool.
|
|
|
|
|
|
|
|
if (typeof val === 'string') {
|
|
|
|
if (encoding === undefined) {
|
|
|
|
return binding.indexOfString(buffer, val, byteOffset, encoding, dir);
|
|
|
|
}
|
|
|
|
return slowIndexOf(buffer, val, byteOffset, encoding, dir);
|
|
|
|
} else if (val instanceof Buffer) {
|
|
|
|
return binding.indexOfBuffer(buffer, val, byteOffset, encoding, dir);
|
|
|
|
} else if (typeof val === 'number') {
|
|
|
|
return binding.indexOfNumber(buffer, val, byteOffset, dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new TypeError('"val" argument must be string, number or Buffer');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function slowIndexOf(buffer, val, byteOffset, encoding, dir) {
|
|
|
|
var loweredCase = false;
|
|
|
|
for (;;) {
|
|
|
|
switch (encoding) {
|
|
|
|
case 'utf8':
|
|
|
|
case 'utf-8':
|
|
|
|
case 'ucs2':
|
|
|
|
case 'ucs-2':
|
|
|
|
case 'utf16le':
|
|
|
|
case 'utf-16le':
|
|
|
|
case 'latin1':
|
|
|
|
case 'binary':
|
|
|
|
return binding.indexOfString(buffer, val, byteOffset, encoding, dir);
|
|
|
|
|
|
|
|
case 'base64':
|
|
|
|
case 'ascii':
|
|
|
|
case 'hex':
|
|
|
|
return binding.indexOfBuffer(
|
|
|
|
buffer, Buffer.from(val, encoding), byteOffset, encoding, dir);
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (loweredCase) {
|
|
|
|
throw new TypeError('Unknown encoding: ' + encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
encoding = ('' + encoding).toLowerCase();
|
|
|
|
loweredCase = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) {
|
|
|
|
return bidirectionalIndexOf(this, val, byteOffset, encoding, true);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) {
|
|
|
|
return bidirectionalIndexOf(this, val, byteOffset, encoding, false);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.includes = function includes(val, byteOffset, encoding) {
|
|
|
|
return this.indexOf(val, byteOffset, encoding) !== -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Usage:
|
|
|
|
// buffer.fill(number[, offset[, end]])
|
|
|
|
// buffer.fill(buffer[, offset[, end]])
|
|
|
|
// buffer.fill(string[, offset[, end]][, encoding])
|
|
|
|
Buffer.prototype.fill = function fill(val, start, end, encoding) {
|
|
|
|
// Handle string cases:
|
|
|
|
if (typeof val === 'string') {
|
|
|
|
if (typeof start === 'string') {
|
|
|
|
encoding = start;
|
|
|
|
start = 0;
|
|
|
|
end = this.length;
|
|
|
|
} else if (typeof end === 'string') {
|
|
|
|
encoding = end;
|
|
|
|
end = this.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (encoding !== undefined && typeof encoding !== 'string') {
|
|
|
|
throw new TypeError('encoding must be a string');
|
|
|
|
}
|
|
|
|
var normalizedEncoding = internalUtil.normalizeEncoding(encoding);
|
|
|
|
if (normalizedEncoding === undefined) {
|
|
|
|
throw new TypeError('Unknown encoding: ' + encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (val.length === 0) {
|
|
|
|
// Previously, if val === '', the Buffer would not fill,
|
|
|
|
// which is rather surprising.
|
|
|
|
val = 0;
|
|
|
|
} else if (val.length === 1) {
|
|
|
|
var code = val.charCodeAt(0);
|
|
|
|
if ((normalizedEncoding === 'utf8' && code < 128) ||
|
|
|
|
normalizedEncoding === 'latin1') {
|
|
|
|
// Fast path: If `val` fits into a single byte, use that numeric value.
|
|
|
|
val = code;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (typeof val === 'number') {
|
|
|
|
val = val & 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invalid ranges are not set to a default, so can range check early.
|
|
|
|
if (start < 0 || end > this.length)
|
|
|
|
throw new RangeError('Out of range index');
|
|
|
|
|
|
|
|
if (end <= start)
|
|
|
|
return this;
|
|
|
|
|
|
|
|
start = start >>> 0;
|
|
|
|
end = end === undefined ? this.length : end >>> 0;
|
|
|
|
|
|
|
|
binding.fill(this, val, start, end, encoding);
|
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.write = function(string, offset, length, encoding) {
|
|
|
|
// Buffer#write(string);
|
|
|
|
if (offset === undefined) {
|
|
|
|
encoding = 'utf8';
|
|
|
|
length = this.length;
|
|
|
|
offset = 0;
|
|
|
|
|
|
|
|
// Buffer#write(string, encoding)
|
|
|
|
} else if (length === undefined && typeof offset === 'string') {
|
|
|
|
encoding = offset;
|
|
|
|
length = this.length;
|
|
|
|
offset = 0;
|
|
|
|
|
|
|
|
// Buffer#write(string, offset[, length][, encoding])
|
|
|
|
} else if (isFinite(offset)) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (isFinite(length)) {
|
|
|
|
length = length >>> 0;
|
|
|
|
if (encoding === undefined)
|
|
|
|
encoding = 'utf8';
|
|
|
|
} else {
|
|
|
|
encoding = length;
|
|
|
|
length = undefined;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// if someone is still calling the obsolete form of write(), tell them.
|
|
|
|
// we don't want eg buf.write("foo", "utf8", 10) to silently turn into
|
|
|
|
// buf.write("foo", "utf8"), so we can't ignore extra args
|
|
|
|
throw new Error('Buffer.write(string, encoding, offset[, length]) ' +
|
|
|
|
'is no longer supported');
|
|
|
|
}
|
|
|
|
|
|
|
|
var remaining = this.length - offset;
|
|
|
|
if (length === undefined || length > remaining)
|
|
|
|
length = remaining;
|
|
|
|
|
|
|
|
if (string.length > 0 && (length < 0 || offset < 0))
|
|
|
|
throw new RangeError('Attempt to write outside buffer bounds');
|
|
|
|
|
|
|
|
if (!encoding)
|
|
|
|
encoding = 'utf8';
|
|
|
|
|
|
|
|
var loweredCase = false;
|
|
|
|
for (;;) {
|
|
|
|
switch (encoding) {
|
|
|
|
case 'hex':
|
|
|
|
return this.hexWrite(string, offset, length);
|
|
|
|
|
|
|
|
case 'utf8':
|
|
|
|
case 'utf-8':
|
|
|
|
return this.utf8Write(string, offset, length);
|
|
|
|
|
|
|
|
case 'ascii':
|
|
|
|
return this.asciiWrite(string, offset, length);
|
|
|
|
|
|
|
|
case 'latin1':
|
|
|
|
case 'binary':
|
|
|
|
return this.latin1Write(string, offset, length);
|
|
|
|
|
|
|
|
case 'base64':
|
|
|
|
// Warning: maxLength not taken into account in base64Write
|
|
|
|
return this.base64Write(string, offset, length);
|
|
|
|
|
|
|
|
case 'ucs2':
|
|
|
|
case 'ucs-2':
|
|
|
|
case 'utf16le':
|
|
|
|
case 'utf-16le':
|
|
|
|
return this.ucs2Write(string, offset, length);
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (loweredCase)
|
|
|
|
throw new TypeError('Unknown encoding: ' + encoding);
|
|
|
|
encoding = ('' + encoding).toLowerCase();
|
|
|
|
loweredCase = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.toJSON = function() {
|
|
|
|
if (this.length) {
|
|
|
|
const data = [];
|
|
|
|
for (var i = 0; i < this.length; ++i)
|
|
|
|
data[i] = this[i];
|
|
|
|
return { type: 'Buffer', data };
|
|
|
|
} else {
|
|
|
|
return { type: 'Buffer', data: [] };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function adjustOffset(offset, length) {
|
|
|
|
// Use Math.trunc() to convert offset to an integer value that can be larger
|
|
|
|
// than an Int32. Hence, don't use offset | 0 or similar techniques.
|
|
|
|
offset = Math.trunc(offset);
|
|
|
|
if (offset === 0 || Number.isNaN(offset)) {
|
|
|
|
return 0;
|
buffer: coerce slice parameters consistently
As shown in https://github.com/nodejs/node/issues/9096, the offset and
end value of the `slice` call are coerced to numbers and then passed to
`FastBuffer`, which internally truncates the mantissa part if the number
is actually a floating point number. This actually affects the new
length of the slice calculation. For example,
> const original = Buffer.from('abcd');
undefined
> original.slice(original.length / 3).toString()
'bc'
This happens because, starting value of the slice is 4 / 3, which is
1.33 (approximately). Now, the length of the slice is calculated as
the difference between the actual length of the buffer and the starting
offset. So, it becomes 2.67 (4 - 1.33). Now, a new `FastBuffer` is
constructed, with the following values as parameters,
1. actual buffer object,
2. starting value, which is 1.33 and
3. the length 2.67.
The underlying C++ code truncates the numbers and they become 1 and 2.
That is why the result is just `bc`.
This patch makes sure that all the offsets are coerced to integers
before any calculations are done.
Fixes: https://github.com/nodejs/node/issues/9096
PR-URL: https://github.com/nodejs/node/pull/9101
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
8 years ago
|
|
|
} else if (offset < 0) {
|
|
|
|
offset += length;
|
|
|
|
return offset > 0 ? offset : 0;
|
|
|
|
} else {
|
|
|
|
return offset < length ? offset : length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.slice = function slice(start, end) {
|
|
|
|
const srcLength = this.length;
|
|
|
|
start = adjustOffset(start, srcLength);
|
|
|
|
end = end !== undefined ? adjustOffset(end, srcLength) : srcLength;
|
|
|
|
const newLength = end > start ? end - start : 0;
|
|
|
|
return new FastBuffer(this.buffer, this.byteOffset + start, newLength);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function checkOffset(offset, ext, length) {
|
|
|
|
if (offset + ext > length)
|
|
|
|
throw new RangeError('Index out of range');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readUIntLE = function(offset, byteLength, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
byteLength = byteLength >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
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(offset, byteLength, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
byteLength = byteLength >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
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(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 1, this.length);
|
|
|
|
return this[offset];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 2, this.length);
|
|
|
|
return this[offset] | (this[offset + 1] << 8);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 2, this.length);
|
|
|
|
return (this[offset] << 8) | this[offset + 1];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readUInt32LE = function(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(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(offset, byteLength, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
byteLength = byteLength >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
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(offset, byteLength, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
byteLength = byteLength >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
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(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(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(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(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(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]);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 4, this.length);
|
|
|
|
return binding.readFloatLE(this, offset);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 4, this.length);
|
|
|
|
return binding.readFloatBE(this, offset);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 8, this.length);
|
|
|
|
return binding.readDoubleLE(this, offset);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
checkOffset(offset, 8, this.length);
|
|
|
|
return binding.readDoubleBE(this, offset);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function checkInt(buffer, value, offset, ext, max, min) {
|
|
|
|
if (!(buffer instanceof Buffer))
|
|
|
|
throw new TypeError('"buffer" argument must be a Buffer instance');
|
|
|
|
if (value > max || value < min)
|
|
|
|
throw new TypeError('"value" argument is out of bounds');
|
|
|
|
if (offset + ext > buffer.length)
|
|
|
|
throw new RangeError('Index out of range');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.writeUIntLE = function(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(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(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(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(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(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(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(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(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(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(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(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(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(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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
|
|
|
|
val = +val;
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
binding.writeFloatLE(this, val, offset);
|
|
|
|
else
|
|
|
|
binding.writeFloatLE(this, val, offset, true);
|
|
|
|
return offset + 4;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
|
|
|
|
val = +val;
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
binding.writeFloatBE(this, val, offset);
|
|
|
|
else
|
|
|
|
binding.writeFloatBE(this, val, offset, true);
|
|
|
|
return offset + 4;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
|
|
|
|
val = +val;
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
binding.writeDoubleLE(this, val, offset);
|
|
|
|
else
|
|
|
|
binding.writeDoubleLE(this, val, offset, true);
|
|
|
|
return offset + 8;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
|
|
|
|
val = +val;
|
|
|
|
offset = offset >>> 0;
|
|
|
|
if (!noAssert)
|
|
|
|
binding.writeDoubleBE(this, val, offset);
|
|
|
|
else
|
|
|
|
binding.writeDoubleBE(this, val, offset, true);
|
|
|
|
return offset + 8;
|
|
|
|
};
|
|
|
|
|
|
|
|
const swap16n = binding.swap16;
|
|
|
|
const swap32n = binding.swap32;
|
|
|
|
const swap64n = binding.swap64;
|
|
|
|
|
|
|
|
function swap(b, n, m) {
|
|
|
|
const i = b[n];
|
|
|
|
b[n] = b[m];
|
|
|
|
b[m] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.swap16 = function swap16() {
|
|
|
|
// For Buffer.length < 128, it's generally faster to
|
|
|
|
// do the swap in javascript. For larger buffers,
|
|
|
|
// dropping down to the native code is faster.
|
|
|
|
const len = this.length;
|
|
|
|
if (len % 2 !== 0)
|
|
|
|
throw new RangeError('Buffer size must be a multiple of 16-bits');
|
|
|
|
if (len < 128) {
|
|
|
|
for (var i = 0; i < len; i += 2)
|
|
|
|
swap(this, i, i + 1);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
return swap16n(this);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.swap32 = function swap32() {
|
|
|
|
// For Buffer.length < 192, it's generally faster to
|
|
|
|
// do the swap in javascript. For larger buffers,
|
|
|
|
// dropping down to the native code is faster.
|
|
|
|
const len = this.length;
|
|
|
|
if (len % 4 !== 0)
|
|
|
|
throw new RangeError('Buffer size must be a multiple of 32-bits');
|
|
|
|
if (len < 192) {
|
|
|
|
for (var i = 0; i < len; i += 4) {
|
|
|
|
swap(this, i, i + 3);
|
|
|
|
swap(this, i + 1, i + 2);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
return swap32n(this);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.swap64 = function swap64() {
|
|
|
|
// For Buffer.length < 192, it's generally faster to
|
|
|
|
// do the swap in javascript. For larger buffers,
|
|
|
|
// dropping down to the native code is faster.
|
|
|
|
const len = this.length;
|
|
|
|
if (len % 8 !== 0)
|
|
|
|
throw new RangeError('Buffer size must be a multiple of 64-bits');
|
|
|
|
if (len < 192) {
|
|
|
|
for (var i = 0; i < len; i += 8) {
|
|
|
|
swap(this, i, i + 7);
|
|
|
|
swap(this, i + 1, i + 6);
|
|
|
|
swap(this, i + 2, i + 5);
|
|
|
|
swap(this, i + 3, i + 4);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
return swap64n(this);
|
|
|
|
};
|