123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- 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/
- };
- function toNumber(str, options = {}){
- options = Object.assign({}, consider, options );
- if(!str || typeof str !== "string" ) return str;
-
- let trimmedStr = str.trim();
-
- if(options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;
- else if(str==="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 (trimmedStr.search(/[eE]/)!== -1) { //eNotation
- const notation = trimmedStr.match(/^([-\+])?(0*)([0-9]*(\.[0-9]*)?[eE][-\+]?[0-9]+)$/);
- // +00.123 => [ , '+', '00', '.123', ..
- if(notation){
- // console.log(notation)
- if(options.leadingZeros){ //accept with leading zeros
- trimmedStr = (notation[1] || "") + notation[3];
- }else{
- if(notation[2] === "0" && notation[3][0]=== "."){ //valid number
- }else{
- return str;
- }
- }
- return options.eNotation ? Number(trimmedStr) : str;
- }else{
- return str;
- }
- // }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
- //trim ending zeros for floating number
-
- if(!options.leadingZeros && leadingZeros.length > 0 && sign && trimmedStr[2] !== ".") return str; //-0123
- else if(!options.leadingZeros && leadingZeros.length > 0 && !sign && trimmedStr[1] !== ".") return str; //0123
- else if(options.leadingZeros && leadingZeros===str) return 0; //00
-
- else{//no leading zeros or leading zeros are allowed
- const num = Number(trimmedStr);
- const numStr = "" + num;
- if(numStr.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(numStr === "0" && (numTrimmedByZeros === "") ) return num; //0.0
- else if(numStr === numTrimmedByZeros) return num; //0.456. 0.79000
- else if( sign && numStr === "-"+numTrimmedByZeros) return num;
- else return str;
- }
-
- if(leadingZeros){
- return (numTrimmedByZeros === numStr) || (sign+numTrimmedByZeros === numStr) ? num : str
- }else {
- return (trimmedStr === numStr) || (trimmedStr === sign+numStr) ? num : str
- }
- }
- }else{ //non-numeric string
- 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.substr(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")
- }
- module.exports = toNumber;
|