|
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the
|
|
|
|
// "Software"), to deal in the Software without restriction, including
|
|
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
|
|
// following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included
|
|
|
|
// in all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
/* eslint-disable require-buffer */
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const binding = process.binding('buffer');
|
|
|
|
const { compare: compare_, compareOffset } = binding;
|
|
|
|
const { isArrayBuffer, isSharedArrayBuffer, isUint8Array } =
|
|
|
|
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);
|
|
|
|
|
|
|
|
// |binding.zeroFill| can be undefined when running inside an isolate where we
|
|
|
|
// do not own the ArrayBuffer allocator. Zero fill is always on in that case.
|
|
|
|
const zeroFill = bindingObj.zeroFill || [0];
|
|
|
|
|
|
|
|
function createUnsafeBuffer(size) {
|
|
|
|
return new FastBuffer(createUnsafeArrayBuffer(size));
|
|
|
|
}
|
|
|
|
|
|
|
|
function createUnsafeArrayBuffer(size) {
|
|
|
|
zeroFill[0] = 0;
|
|
|
|
try {
|
|
|
|
return new ArrayBuffer(size);
|
|
|
|
} finally {
|
|
|
|
zeroFill[0] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function createPool() {
|
|
|
|
poolSize = Buffer.poolSize;
|
|
|
|
allocPool = createUnsafeArrayBuffer(poolSize);
|
|
|
|
poolOffset = 0;
|
|
|
|
}
|
|
|
|
createPool();
|
|
|
|
|
|
|
|
|
|
|
|
function alignPool() {
|
|
|
|
// Ensure aligned slices
|
|
|
|
if (poolOffset & 0x7) {
|
|
|
|
poolOffset |= 0x7;
|
|
|
|
poolOffset++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The Buffer() construtor is deprecated in 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 runtime deprecation because of the extent
|
|
|
|
* to which the Buffer constructor is used in the ecosystem currently -- a
|
|
|
|
* runtime deprecation would introduce too much breakage at this time. It's not
|
|
|
|
* likely that the Buffer constructors would ever actually be removed.
|
|
|
|
* Deprecation Code: DEP0005
|
|
|
|
**/
|
|
|
|
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);
|
|
|
|
|
|
|
|
// The 'assertSize' method will remove itself from the callstack when an error
|
|
|
|
// occurs. This is done simply to keep the internal details of the
|
|
|
|
// implementation from bleeding out to users.
|
|
|
|
function assertSize(size) {
|
|
|
|
let err = null;
|
|
|
|
|
|
|
|
if (typeof size !== 'number')
|
|
|
|
err = new TypeError('"size" argument must be a number');
|
|
|
|
else if (size < 0)
|
|
|
|
err = new RangeError('"size" argument must not be negative');
|
|
|
|
else if (size > binding.kMaxLength)
|
|
|
|
err = new RangeError('"size" argument must not be larger ' +
|
|
|
|
'than ' + binding.kMaxLength);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
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;
|
|
|
|
assertSize(+length);
|
|
|
|
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 = new FastBuffer(allocPool, poolOffset, size);
|
|
|
|
poolOffset += size;
|
|
|
|
alignPool();
|
|
|
|
return b;
|
|
|
|
} else {
|
|
|
|
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 b = new FastBuffer(allocPool, poolOffset, length);
|
|
|
|
var actual = b.write(string, encoding);
|
|
|
|
if (actual !== length) {
|
|
|
|
// byteLength() may overestimate. That's a rare case, though.
|
|
|
|
b = new FastBuffer(allocPool, 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>
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>
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 (isUint8Array(obj)) {
|
|
|
|
const b = allocate(obj.length);
|
|
|
|
|
|
|
|
if (b.length === 0)
|
|
|
|
return b;
|
|
|
|
|
|
|
|
binding.copy(obj, b, 0, 0, obj.length);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj) {
|
|
|
|
if (obj.length !== undefined || 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 (!isUint8Array(a) || !isUint8Array(b)) {
|
|
|
|
throw new TypeError('Arguments must be Buffers or Uint8Arrays');
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
const kConcatErrMsg = '"list" argument must be an Array ' +
|
|
|
|
'of Buffer or Uint8Array instances';
|
|
|
|
|
|
|
|
Buffer.concat = function(list, length) {
|
|
|
|
var i;
|
|
|
|
if (!Array.isArray(list))
|
|
|
|
throw new TypeError(kConcatErrMsg);
|
|
|
|
|
|
|
|
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 (!isUint8Array(buf))
|
|
|
|
throw new TypeError(kConcatErrMsg);
|
|
|
|
binding.copy(buf, 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new TypeError('"string" must be a string, Buffer, or ArrayBuffer');
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
return this.buffer;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Object.defineProperty(Buffer.prototype, 'offset', {
|
|
|
|
enumerable: true,
|
|
|
|
get: function() {
|
|
|
|
if (!(this instanceof Buffer))
|
|
|
|
return undefined;
|
|
|
|
return this.byteOffset;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function slowToString(buf, encoding, start, end) {
|
|
|
|
var loweredCase = false;
|
|
|
|
|
|
|
|
// No need to verify that "buf.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 > buf.length. Done here to prevent potential uint32
|
|
|
|
// coercion fail below.
|
|
|
|
if (start > buf.length)
|
|
|
|
return '';
|
|
|
|
|
|
|
|
if (end === undefined || end > buf.length)
|
|
|
|
end = buf.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 === undefined) encoding = 'utf8';
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
switch (encoding) {
|
|
|
|
case 'hex':
|
|
|
|
return buf.hexSlice(start, end);
|
|
|
|
|
|
|
|
case 'utf8':
|
|
|
|
case 'utf-8':
|
|
|
|
return buf.utf8Slice(start, end);
|
|
|
|
|
|
|
|
case 'ascii':
|
|
|
|
return buf.asciiSlice(start, end);
|
|
|
|
|
|
|
|
case 'latin1':
|
|
|
|
case 'binary':
|
|
|
|
return buf.latin1Slice(start, end);
|
|
|
|
|
|
|
|
case 'base64':
|
|
|
|
return buf.base64Slice(start, end);
|
|
|
|
|
|
|
|
case 'ucs2':
|
|
|
|
case 'ucs-2':
|
|
|
|
case 'utf16le':
|
|
|
|
case 'utf-16le':
|
|
|
|
return buf.ucs2Slice(start, end);
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (loweredCase)
|
|
|
|
throw new TypeError('Unknown encoding: ' + encoding);
|
|
|
|
encoding = (encoding + '').toLowerCase();
|
|
|
|
loweredCase = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer.prototype.copy = function(target, targetStart, sourceStart, sourceEnd) {
|
|
|
|
return binding.copy(this, target, targetStart, sourceStart, sourceEnd);
|
|
|
|
};
|
|
|
|
|
|
|
|
Buffer.prototype.toString = function(encoding, start, end) {
|
|
|
|
let result;
|
|
|
|
if (arguments.length === 0) {
|
|
|
|
result = this.utf8Slice(0, this.length);
|
|
|
|
} else {
|
|
|
|
result = slowToString(this, encoding, start, end);
|
|
|
|
}
|
|
|
|
if (result === undefined)
|
|
|
|
throw new Error('"toString()" failed');
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.equals = function equals(b) {
|
|
|
|
if (!isUint8Array(b))
|
|
|
|
throw new TypeError('Argument must be a Buffer or Uint8Array');
|
|
|
|
|
|
|
|
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;
|
|
|
|
str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
|
|
|
|
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 (!isUint8Array(target))
|
|
|
|
throw new TypeError('Argument must be a Buffer or Uint8Array');
|
|
|
|
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 (isUint8Array(val)) {
|
|
|
|
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, Buffer ' +
|
|
|
|
'or Uint8Array');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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 (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);
|
|
|
|
};
|
|
|
|
|
|
|
|
Buffer.prototype.toLocaleString = Buffer.prototype.toString;
|
|
|
|
|
|
|
|
// Put this at the end because internal/buffer has a circular
|
|
|
|
// dependency on Buffer.
|
|
|
|
exports.transcode = require('internal/buffer').transcode;
|