|
|
@ -23,8 +23,7 @@ |
|
|
|
|
|
|
|
const binding = process.binding('buffer'); |
|
|
|
const { compare: compare_, compareOffset } = binding; |
|
|
|
const { isArrayBuffer, isSharedArrayBuffer, isUint8Array } = |
|
|
|
process.binding('util'); |
|
|
|
const { isAnyArrayBuffer, isUint8Array } = process.binding('util'); |
|
|
|
const bindingObj = {}; |
|
|
|
const internalUtil = require('internal/util'); |
|
|
|
|
|
|
@ -116,16 +115,19 @@ function Buffer(arg, encodingOrOffset, length) { |
|
|
|
* 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 (typeof value === 'string') |
|
|
|
return fromString(value, encodingOrOffset); |
|
|
|
|
|
|
|
if (isArrayBuffer(value) || isSharedArrayBuffer(value)) |
|
|
|
if (isAnyArrayBuffer(value)) |
|
|
|
return fromArrayBuffer(value, encodingOrOffset, length); |
|
|
|
|
|
|
|
if (typeof value === 'string') |
|
|
|
return fromString(value, encodingOrOffset); |
|
|
|
var b = fromObject(value); |
|
|
|
if (b) |
|
|
|
return b; |
|
|
|
|
|
|
|
return fromObject(value); |
|
|
|
if (typeof value === 'number') |
|
|
|
throw new TypeError('"value" argument must not be a number'); |
|
|
|
throw new TypeError(kFromErrorMsg); |
|
|
|
}; |
|
|
|
|
|
|
|
Object.setPrototypeOf(Buffer, Uint8Array); |
|
|
@ -218,16 +220,19 @@ function allocate(size) { |
|
|
|
|
|
|
|
|
|
|
|
function fromString(string, encoding) { |
|
|
|
if (typeof encoding !== 'string' || encoding === '') |
|
|
|
var length; |
|
|
|
if (typeof encoding !== 'string' || encoding.length === 0) { |
|
|
|
encoding = 'utf8'; |
|
|
|
|
|
|
|
if (!Buffer.isEncoding(encoding)) |
|
|
|
if (string.length === 0) |
|
|
|
return new FastBuffer(); |
|
|
|
length = binding.byteLengthUtf8(string); |
|
|
|
} else { |
|
|
|
length = byteLength(string, encoding, true); |
|
|
|
if (length === -1) |
|
|
|
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); |
|
|
@ -235,7 +240,7 @@ function fromString(string, encoding) { |
|
|
|
if (length > (poolSize - poolOffset)) |
|
|
|
createPool(); |
|
|
|
var b = new FastBuffer(allocPool, poolOffset, length); |
|
|
|
var actual = b.write(string, encoding); |
|
|
|
const actual = b.write(string, encoding); |
|
|
|
if (actual !== length) { |
|
|
|
// byteLength() may overestimate. That's a rare case, though.
|
|
|
|
b = new FastBuffer(allocPool, poolOffset, actual); |
|
|
@ -255,8 +260,14 @@ function fromArrayLike(obj) { |
|
|
|
|
|
|
|
function fromArrayBuffer(obj, byteOffset, length) { |
|
|
|
// convert byteOffset to integer
|
|
|
|
if (byteOffset === undefined) { |
|
|
|
byteOffset = 0; |
|
|
|
} else { |
|
|
|
byteOffset = +byteOffset; |
|
|
|
byteOffset = byteOffset ? Math.trunc(byteOffset) : 0; |
|
|
|
// check for NaN
|
|
|
|
if (byteOffset !== byteOffset) |
|
|
|
byteOffset = 0; |
|
|
|
} |
|
|
|
|
|
|
|
const maxLength = obj.byteLength - byteOffset; |
|
|
|
|
|
|
@ -268,11 +279,17 @@ function fromArrayBuffer(obj, byteOffset, length) { |
|
|
|
} else { |
|
|
|
// convert length to non-negative integer
|
|
|
|
length = +length; |
|
|
|
length = length ? Math.trunc(length) : 0; |
|
|
|
length = length <= 0 ? 0 : Math.min(length, Number.MAX_SAFE_INTEGER); |
|
|
|
|
|
|
|
// Check for NaN
|
|
|
|
if (length !== length) { |
|
|
|
length = 0; |
|
|
|
} else if (length > 0) { |
|
|
|
length = (length < Number.MAX_SAFE_INTEGER ? |
|
|
|
length : Number.MAX_SAFE_INTEGER); |
|
|
|
if (length > maxLength) |
|
|
|
throw new RangeError("'length' is out of bounds"); |
|
|
|
} else { |
|
|
|
length = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return new FastBuffer(obj, byteOffset, length); |
|
|
@ -289,9 +306,8 @@ function fromObject(obj) { |
|
|
|
return b; |
|
|
|
} |
|
|
|
|
|
|
|
if (obj) { |
|
|
|
if (obj.length !== undefined || isArrayBuffer(obj.buffer) || |
|
|
|
isSharedArrayBuffer(obj.buffer)) { |
|
|
|
if (obj != undefined) { |
|
|
|
if (obj.length !== undefined || isAnyArrayBuffer(obj.buffer)) { |
|
|
|
if (typeof obj.length !== 'number' || obj.length !== obj.length) { |
|
|
|
return new FastBuffer(); |
|
|
|
} |
|
|
@ -302,8 +318,6 @@ function fromObject(obj) { |
|
|
|
return fromArrayLike(obj.data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
throw new TypeError(kFromErrorMsg); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -388,53 +402,63 @@ function base64ByteLength(str, bytes) { |
|
|
|
|
|
|
|
function byteLength(string, encoding) { |
|
|
|
if (typeof string !== 'string') { |
|
|
|
if (ArrayBuffer.isView(string) || isArrayBuffer(string) || |
|
|
|
isSharedArrayBuffer(string)) { |
|
|
|
if (ArrayBuffer.isView(string) || isAnyArrayBuffer(string)) { |
|
|
|
return string.byteLength; |
|
|
|
} |
|
|
|
|
|
|
|
throw new TypeError('"string" must be a string, Buffer, or ArrayBuffer'); |
|
|
|
} |
|
|
|
|
|
|
|
var len = string.length; |
|
|
|
if (len === 0) |
|
|
|
const len = string.length; |
|
|
|
const mustMatch = (arguments.length > 2 && arguments[2] === true); |
|
|
|
if (!mustMatch && 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': |
|
|
|
if (!encoding) |
|
|
|
return (mustMatch ? -1 : binding.byteLengthUtf8(string)); |
|
|
|
|
|
|
|
encoding += ''; |
|
|
|
switch (encoding.length) { |
|
|
|
case 4: |
|
|
|
if (encoding === 'utf8') return binding.byteLengthUtf8(string); |
|
|
|
if (encoding === 'ucs2') return len * 2; |
|
|
|
encoding = encoding.toLowerCase(); |
|
|
|
if (encoding === 'utf8') return binding.byteLengthUtf8(string); |
|
|
|
if (encoding === 'ucs2') return len * 2; |
|
|
|
break; |
|
|
|
case 5: |
|
|
|
if (encoding === 'utf-8') return binding.byteLengthUtf8(string); |
|
|
|
if (encoding === 'ascii') return len; |
|
|
|
if (encoding === 'ucs-2') return len * 2; |
|
|
|
encoding = encoding.toLowerCase(); |
|
|
|
if (encoding === 'utf-8') return binding.byteLengthUtf8(string); |
|
|
|
if (encoding === 'ascii') return len; |
|
|
|
if (encoding === 'ucs-2') return len * 2; |
|
|
|
break; |
|
|
|
case 7: |
|
|
|
if (encoding === 'utf16le' || encoding.toLowerCase() === 'utf16le') |
|
|
|
return len * 2; |
|
|
|
|
|
|
|
case 'hex': |
|
|
|
break; |
|
|
|
case 8: |
|
|
|
if (encoding === 'utf-16le' || encoding.toLowerCase() === 'utf-16le') |
|
|
|
return len * 2; |
|
|
|
break; |
|
|
|
case 6: |
|
|
|
if (encoding === 'latin1' || encoding === 'binary') return len; |
|
|
|
if (encoding === 'base64') return base64ByteLength(string, len); |
|
|
|
encoding = encoding.toLowerCase(); |
|
|
|
if (encoding === 'latin1' || encoding === 'binary') return len; |
|
|
|
if (encoding === 'base64') return base64ByteLength(string, len); |
|
|
|
break; |
|
|
|
case 3: |
|
|
|
if (encoding === 'hex' || encoding.toLowerCase() === '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; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
if (mustMatch) |
|
|
|
throw new TypeError('Unknown encoding: ' + encoding); |
|
|
|
else |
|
|
|
return binding.byteLengthUtf8(string); |
|
|
|
} |
|
|
|
|
|
|
|
Buffer.byteLength = byteLength; |
|
|
|