UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

161 lines (147 loc) 6.34 kB
const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/; const numRegex = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/; // const octRegex = /^0x[a-z0-9]+/; // const binRegex = /0x[a-z0-9]+/; const consider = { hex: true, // oct: false, leadingZeros: true, decimalPoint: "\.", eNotation: true, //skipLike: /regex/, infinity: "original", // "null", "infinity" (Infinity type), "string" ("Infinity" (the string literal)) }; export default function toNumber(str, options = {}) { options = Object.assign({}, consider, options); if (!str || typeof str !== "string") return str; let trimmedStr = str.trim(); if (trimmedStr.length === 0) return str; else if (options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str; else if (trimmedStr === "0") return 0; else if (options.hex && hexRegex.test(trimmedStr)) { return parse_int(trimmedStr, 16); // }else if (options.oct && octRegex.test(str)) { // return Number.parseInt(val, 8); } else if (!isFinite(trimmedStr)) { //Infinity return handleInfinity(str, Number(trimmedStr), options); } else if (trimmedStr.includes('e') || trimmedStr.includes('E')) { //eNotation return resolveEnotation(str, trimmedStr, options); // }else if (options.parseBin && binRegex.test(str)) { // return Number.parseInt(val, 2); } else { //separate negative sign, leading zeros, and rest number const match = numRegex.exec(trimmedStr); // +00.123 => [ , '+', '00', '.123', .. if (match) { const sign = match[1] || ""; const leadingZeros = match[2]; let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros const decimalAdjacentToLeadingZeros = sign ? // 0., -00., 000. str[leadingZeros.length + 1] === "." : str[leadingZeros.length] === "."; //trim ending zeros for floating number if (!options.leadingZeros //leading zeros are not allowed && (leadingZeros.length > 1 || (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))) { // 00, 00.3, +03.24, 03, 03.24 return str; } else {//no leading zeros or leading zeros are allowed const num = Number(trimmedStr); const parsedStr = String(num); if (num === 0) return num; if (parsedStr.search(/[eE]/) !== -1) { //given number is long and parsed to eNotation if (options.eNotation) return num; else return str; } else if (trimmedStr.indexOf(".") !== -1) { //floating number if (parsedStr === "0") return num; //0.0 else if (parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000 else if (parsedStr === `${sign}${numTrimmedByZeros}`) return num; else return str; } let n = leadingZeros ? numTrimmedByZeros : trimmedStr; if (leadingZeros) { // -009 => -9 return (n === parsedStr) || (sign + n === parsedStr) ? num : str } else { // +9 return (n === parsedStr) || (n === sign + parsedStr) ? num : str } } } else { //non-numeric string return str; } } } const eNotationRegx = /^([-+])?(0*)(\d*(\.\d*)?[eE][-\+]?\d+)$/; function resolveEnotation(str, trimmedStr, options) { if (!options.eNotation) return str; const notation = trimmedStr.match(eNotationRegx); if (notation) { let sign = notation[1] || ""; const eChar = notation[3].indexOf("e") === -1 ? "E" : "e"; const leadingZeros = notation[2]; const eAdjacentToLeadingZeros = sign ? // 0E. str[leadingZeros.length + 1] === eChar : str[leadingZeros.length] === eChar; if (leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str; else if (leadingZeros.length === 1 && (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)) { return Number(trimmedStr); } else if (leadingZeros.length > 0) { // Has leading zeros — only accept if leadingZeros option allows it if (options.leadingZeros && !eAdjacentToLeadingZeros) { trimmedStr = (notation[1] || "") + notation[3]; return Number(trimmedStr); } else return str; } else { // No leading zeros — always valid e-notation, parse it return Number(trimmedStr); } } else { return str; } } /** * * @param {string} numStr without leading zeros * @returns */ function trimZeros(numStr) { if (numStr && numStr.indexOf(".") !== -1) {//float numStr = numStr.replace(/0+$/, ""); //remove ending zeros if (numStr === ".") numStr = "0"; else if (numStr[0] === ".") numStr = "0" + numStr; else if (numStr[numStr.length - 1] === ".") numStr = numStr.substring(0, numStr.length - 1); return numStr; } return numStr; } function parse_int(numStr, base) { //polyfill if (parseInt) return parseInt(numStr, base); else if (Number.parseInt) return Number.parseInt(numStr, base); else if (window && window.parseInt) return window.parseInt(numStr, base); else throw new Error("parseInt, Number.parseInt, window.parseInt are not supported") } /** * Handle infinite values based on user option * @param {string} str - original input string * @param {number} num - parsed number (Infinity or -Infinity) * @param {object} options - user options * @returns {string|number|null} based on infinity option */ function handleInfinity(str, num, options) { const isPositive = num === Infinity; switch (options.infinity.toLowerCase()) { case "null": return null; case "infinity": return num; // Return Infinity or -Infinity case "string": return isPositive ? "Infinity" : "-Infinity"; case "original": default: return str; // Return original string like "1e1000" } }