2018-04-15 11:16:50 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const {
|
2019-03-18 02:29:39 +01:00
|
|
|
hideStackFrames,
|
|
|
|
codes: {
|
|
|
|
ERR_INVALID_ARG_TYPE,
|
|
|
|
ERR_INVALID_ARG_VALUE,
|
2019-04-08 19:06:02 +02:00
|
|
|
ERR_OUT_OF_RANGE,
|
|
|
|
ERR_UNKNOWN_SIGNAL
|
2019-03-18 02:29:39 +01:00
|
|
|
}
|
|
|
|
} = require('internal/errors');
|
2019-05-11 19:00:38 +02:00
|
|
|
const { normalizeEncoding } = require('internal/util');
|
2019-03-20 13:15:48 +01:00
|
|
|
const {
|
|
|
|
isArrayBufferView
|
|
|
|
} = require('internal/util/types');
|
2019-04-08 19:06:02 +02:00
|
|
|
const { signals } = internalBinding('constants').os;
|
2019-07-22 23:44:49 +02:00
|
|
|
const { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } = Number;
|
2018-04-15 11:16:50 +02:00
|
|
|
|
|
|
|
function isInt32(value) {
|
|
|
|
return value === (value | 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
function isUint32(value) {
|
|
|
|
return value === (value >>> 0);
|
|
|
|
}
|
|
|
|
|
2018-05-09 16:44:44 +02:00
|
|
|
const octalReg = /^[0-7]+$/;
|
|
|
|
const modeDesc = 'must be a 32-bit unsigned integer or an octal string';
|
2018-05-26 12:51:19 +02:00
|
|
|
|
|
|
|
/**
|
2019-03-20 12:00:47 +01:00
|
|
|
* Parse and validate values that will be converted into mode_t (the S_*
|
|
|
|
* constants). Only valid numbers and octal strings are allowed. They could be
|
|
|
|
* converted to 32-bit unsigned integers or non-negative signed integers in the
|
|
|
|
* C++ land, but any value higher than 0o777 will result in platform-specific
|
2018-05-26 12:51:19 +02:00
|
|
|
* behaviors.
|
|
|
|
*
|
|
|
|
* @param {*} value Values to be validated
|
|
|
|
* @param {string} name Name of the argument
|
|
|
|
* @param {number} def If specified, will be returned for invalid values
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
2019-03-20 12:00:47 +01:00
|
|
|
function parseMode(value, name, def) {
|
2018-05-09 16:44:44 +02:00
|
|
|
if (isUint32(value)) {
|
2018-05-26 12:51:19 +02:00
|
|
|
return value;
|
2018-05-09 16:44:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof value === 'number') {
|
2019-03-10 23:06:33 +01:00
|
|
|
validateInt32(value, name, 0, 2 ** 32 - 1);
|
2018-05-09 16:44:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof value === 'string') {
|
|
|
|
if (!octalReg.test(value)) {
|
|
|
|
throw new ERR_INVALID_ARG_VALUE(name, value, modeDesc);
|
|
|
|
}
|
2019-03-10 23:06:33 +01:00
|
|
|
return parseInt(value, 8);
|
2018-05-09 16:44:44 +02:00
|
|
|
}
|
|
|
|
|
2019-03-10 23:06:33 +01:00
|
|
|
if (def !== undefined && value == null) {
|
2018-05-09 16:44:44 +02:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new ERR_INVALID_ARG_VALUE(name, value, modeDesc);
|
|
|
|
}
|
|
|
|
|
2019-08-17 17:50:43 +02:00
|
|
|
const validateInteger = hideStackFrames(
|
2019-07-22 23:44:49 +02:00
|
|
|
(value, name, min = MIN_SAFE_INTEGER, max = MAX_SAFE_INTEGER) => {
|
|
|
|
if (typeof value !== 'number')
|
|
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
|
|
|
if (!Number.isInteger(value))
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, 'an integer', value);
|
|
|
|
if (value < min || value > max)
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
|
|
|
|
}
|
|
|
|
);
|
2019-03-18 02:29:39 +01:00
|
|
|
|
|
|
|
const validateInt32 = hideStackFrames(
|
|
|
|
(value, name, min = -2147483648, max = 2147483647) => {
|
|
|
|
// The defaults for min and max correspond to the limits of 32-bit integers.
|
|
|
|
if (!isInt32(value)) {
|
|
|
|
if (typeof value !== 'number') {
|
|
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
|
|
|
}
|
|
|
|
if (!Number.isInteger(value)) {
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, 'an integer', value);
|
|
|
|
}
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
|
2018-04-15 11:16:50 +02:00
|
|
|
}
|
2019-03-18 02:29:39 +01:00
|
|
|
if (value < min || value > max) {
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
|
|
|
|
}
|
2018-04-15 11:16:50 +02:00
|
|
|
}
|
2019-03-18 02:29:39 +01:00
|
|
|
);
|
2018-05-30 16:01:00 +02:00
|
|
|
|
2019-03-18 02:29:39 +01:00
|
|
|
const validateUint32 = hideStackFrames((value, name, positive) => {
|
2018-04-15 11:16:50 +02:00
|
|
|
if (!isUint32(value)) {
|
|
|
|
if (typeof value !== 'number') {
|
2019-03-18 02:29:39 +01:00
|
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
2018-04-15 11:16:50 +02:00
|
|
|
}
|
2019-03-18 02:29:39 +01:00
|
|
|
if (!Number.isInteger(value)) {
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, 'an integer', value);
|
|
|
|
}
|
|
|
|
const min = positive ? 1 : 0;
|
|
|
|
// 2 ** 32 === 4294967296
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, `>= ${min} && < 4294967296`, value);
|
2018-04-15 11:16:50 +02:00
|
|
|
}
|
2019-03-18 02:29:39 +01:00
|
|
|
if (positive && value === 0) {
|
|
|
|
throw new ERR_OUT_OF_RANGE(name, '>= 1 && < 4294967296', value);
|
|
|
|
}
|
|
|
|
});
|
2018-04-15 11:16:50 +02:00
|
|
|
|
2018-08-03 00:51:02 +02:00
|
|
|
function validateString(value, name) {
|
|
|
|
if (typeof value !== 'string')
|
|
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
|
|
|
|
}
|
|
|
|
|
2018-08-03 17:23:26 +02:00
|
|
|
function validateNumber(value, name) {
|
|
|
|
if (typeof value !== 'number')
|
|
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
|
|
|
}
|
|
|
|
|
2019-04-08 19:06:02 +02:00
|
|
|
function validateSignalName(signal, name = 'signal') {
|
|
|
|
if (typeof signal !== 'string')
|
|
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'string', signal);
|
|
|
|
|
|
|
|
if (signals[signal] === undefined) {
|
|
|
|
if (signals[signal.toUpperCase()] !== undefined) {
|
|
|
|
throw new ERR_UNKNOWN_SIGNAL(signal +
|
|
|
|
' (signals must use all capital letters)');
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new ERR_UNKNOWN_SIGNAL(signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-20 13:15:48 +01:00
|
|
|
const validateBuffer = hideStackFrames((buffer, name = 'buffer') => {
|
|
|
|
if (!isArrayBufferView(buffer)) {
|
|
|
|
throw new ERR_INVALID_ARG_TYPE(name,
|
|
|
|
['Buffer', 'TypedArray', 'DataView'],
|
|
|
|
buffer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-05-11 19:00:38 +02:00
|
|
|
function validateEncoding(data, encoding) {
|
|
|
|
const normalizedEncoding = normalizeEncoding(encoding);
|
|
|
|
const length = data.length;
|
|
|
|
|
|
|
|
if (normalizedEncoding === 'hex' && length % 2 !== 0) {
|
|
|
|
throw new ERR_INVALID_ARG_VALUE('encoding', encoding,
|
|
|
|
`is invalid for data of length ${length}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-15 11:16:50 +02:00
|
|
|
module.exports = {
|
|
|
|
isInt32,
|
|
|
|
isUint32,
|
2019-03-20 12:00:47 +01:00
|
|
|
parseMode,
|
2019-03-20 13:15:48 +01:00
|
|
|
validateBuffer,
|
2019-05-11 19:00:38 +02:00
|
|
|
validateEncoding,
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger,
|
2018-04-15 11:16:50 +02:00
|
|
|
validateInt32,
|
2018-08-03 00:51:02 +02:00
|
|
|
validateUint32,
|
2018-08-03 17:23:26 +02:00
|
|
|
validateString,
|
2019-04-08 19:06:02 +02:00
|
|
|
validateNumber,
|
|
|
|
validateSignalName
|
2018-04-15 11:16:50 +02:00
|
|
|
};
|