Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cc41dde
initiate parse_int once
Uzlopak Jul 15, 2025
653d28e
remove commented out code
Uzlopak Jul 15, 2025
b6a1723
add jsdoc
Uzlopak Jul 15, 2025
8ce60c6
add benchmark based on tests
Uzlopak Jul 15, 2025
4bd6dd1
format with vscode
Uzlopak Jul 15, 2025
143e930
remove enotation check in resolveEnotation
Uzlopak Jul 15, 2025
a830509
improve jsdoc desc
Uzlopak Jul 15, 2025
9d40e67
improve
Uzlopak Jul 15, 2025
f85c326
improve
Uzlopak Jul 16, 2025
973d1b8
remove benchmark log
Uzlopak Jul 16, 2025
eb541a6
improve
Uzlopak Jul 16, 2025
8087593
improve bitmask magic
Uzlopak Jul 16, 2025
4456d13
simplify
Uzlopak Jul 17, 2025
882021d
reduce bs
Uzlopak Jul 17, 2025
f5e482e
reduce
Uzlopak Jul 20, 2025
5963d3d
exponent sign repetition
Uzlopak Jul 20, 2025
bcd8a42
ensure EXP_CHAR is always e or E
Uzlopak Jul 20, 2025
272539f
more
Uzlopak Jul 21, 2025
11bcce6
blub
Uzlopak Jul 21, 2025
2305233
more
Uzlopak Jul 21, 2025
a69eb2e
fix
Uzlopak Jul 21, 2025
a531870
add infinity
Uzlopak Jul 21, 2025
e54c9ee
Delete package-lock.json
amitguptagwl Jul 21, 2025
6a02a99
fix Infinity
Uzlopak Jul 22, 2025
d69fd64
fix signed prefixed numbers
Uzlopak Jul 22, 2025
167ba25
add missing whitespace
Uzlopak Jul 22, 2025
26ed551
better
Uzlopak Jul 24, 2025
c05c77a
improve
Uzlopak Jul 24, 2025
b725934
reorder
Uzlopak Jul 24, 2025
93f47a1
improve more
Uzlopak Jul 24, 2025
7d504aa
cut some corners
Uzlopak Jul 24, 2025
d71ce54
remove stuff again
Uzlopak Jul 24, 2025
1467352
improve
Uzlopak Jul 25, 2025
1facfc2
use codepoint
Uzlopak Jul 25, 2025
7125ba1
improve
Uzlopak Jul 25, 2025
bb8fac2
fix
Uzlopak Jul 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ npm install strnum
const toNumber = require("strnum");

toNumber(undefined) // undefined
toNumber(null)) //null
toNumber("")) // ""
toNumber(null) //null
toNumber("") // ""
toNumber("string"); //"string")
toNumber("12,12"); //"12,12")
toNumber("12 12"); //"12 12")
Expand Down
160 changes: 160 additions & 0 deletions benchmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { Bench } from 'tinybench'
import toNumber from "./strnum.js"

const bench = new Bench({ name: 'strnum benchmark', time: 100 })

function toNumberBenchmark(str, options) {
bench.add(`${str}${options ? ', ' + JSON.stringify(options) : ''}`, () => {
toNumber(str, options)
})
}

toNumberBenchmark(undefined);
toNumberBenchmark(null);
toNumberBenchmark("");
toNumberBenchmark("string");
toNumberBenchmark("e89794659669cb7bb967db73a7ea6889c3891727")
toNumberBenchmark("12,12");
toNumberBenchmark("12 12");
toNumberBenchmark("12-12");
toNumberBenchmark("12.12.12");
toNumberBenchmark("+12");
toNumberBenchmark("+ 12");
toNumberBenchmark("12+12");
toNumberBenchmark("1212+");
toNumberBenchmark("0x2f");
toNumberBenchmark("-0x2f");
toNumberBenchmark("0x2f", { hex: true });
toNumberBenchmark("-0x2f", { hex: true });
toNumberBenchmark("0x2f", { hex: false });
toNumberBenchmark("-0x2f", { hex: false });
toNumberBenchmark("0xzz");
toNumberBenchmark("iweraf0x123qwerqwer");
toNumberBenchmark("1230x55");
toNumberBenchmark("JVBERi0xLjMNCiXi48");
toNumberBenchmark("0");
toNumberBenchmark("00");
toNumberBenchmark("00.0");

toNumberBenchmark("0", { leadingZeros: false });
toNumberBenchmark("00", { leadingZeros: false });
toNumberBenchmark("00.0", { leadingZeros: false });

toNumberBenchmark("06");
toNumberBenchmark("06", { leadingZeros: true });
toNumberBenchmark("06", { leadingZeros: false });

toNumberBenchmark("006");
toNumberBenchmark("006", { leadingZeros: true });
toNumberBenchmark("006", { leadingZeros: false });

toNumberBenchmark("000000000000000000000000017717", { leadingZeros: false });
toNumberBenchmark("000000000000000000000000017717", { leadingZeros: true });
toNumberBenchmark("0420926189200190257681175017717");
toNumberBenchmark("20.21.030");
toNumberBenchmark("0.21.030");
toNumberBenchmark("0.21.");
toNumberBenchmark("0.");
toNumberBenchmark("+0.");
toNumberBenchmark("-0.");
toNumberBenchmark("1.");
toNumberBenchmark("00.00");
toNumberBenchmark("0.06");
toNumberBenchmark("00.6");
toNumberBenchmark(".006");
toNumberBenchmark("6.0");
toNumberBenchmark("06.0");

toNumberBenchmark("0.0", { leadingZeros: false });
toNumberBenchmark("00.00", { leadingZeros: false });
toNumberBenchmark("0.06", { leadingZeros: false });
toNumberBenchmark("00.6", { leadingZeros: false });
toNumberBenchmark(".006", { leadingZeros: false });
toNumberBenchmark("6.0", { leadingZeros: false });
toNumberBenchmark("06.0", { leadingZeros: false });
toNumberBenchmark("+06");
toNumberBenchmark("-06");
toNumberBenchmark("-06", { leadingZeros: true });
toNumberBenchmark("-06", { leadingZeros: false });

toNumberBenchmark("-0.0");
toNumberBenchmark("-00.00");
toNumberBenchmark("-0.06");
toNumberBenchmark("-00.6");
toNumberBenchmark("-.006");
toNumberBenchmark("-6.0");
toNumberBenchmark("-06.0");
toNumberBenchmark("+06.0");

toNumberBenchmark("-0.0", { leadingZeros: false });
toNumberBenchmark("-00.00", { leadingZeros: false });
toNumberBenchmark("-0.06", { leadingZeros: false });
toNumberBenchmark("-00.6", { leadingZeros: false });
toNumberBenchmark("-.006", { leadingZeros: false });
toNumberBenchmark("-6.0", { leadingZeros: false });
toNumberBenchmark("-06.0", { leadingZeros: false });
toNumberBenchmark("020211201030005811824");
toNumberBenchmark("20211201030005811824");
toNumberBenchmark("20.211201030005811824");
toNumberBenchmark("0.211201030005811824");
toNumberBenchmark("01.0e2", { leadingZeros: false });
toNumberBenchmark("-01.0e2", { leadingZeros: false });
toNumberBenchmark("01.0e2");
toNumberBenchmark("-01.0e2");
toNumberBenchmark("1.0e2");

toNumberBenchmark("-1.0e2");
toNumberBenchmark("1.0e-2");

toNumberBenchmark("420926189200190257681175017717");
toNumberBenchmark("420926189200190257681175017717", { eNotation: false });

toNumberBenchmark("1e-2");
toNumberBenchmark("1e+2");
toNumberBenchmark("1.e+2");
toNumberBenchmark("01.0E2", { leadingZeros: false });
toNumberBenchmark("-01.0E2", { leadingZeros: false });
toNumberBenchmark("01.0E2");
toNumberBenchmark("-01.0E2");
toNumberBenchmark("1.0E2");

toNumberBenchmark("-1.0E2");
toNumberBenchmark("1.0E-2");

toNumberBenchmark("E-2");
toNumberBenchmark("E2");
toNumberBenchmark("0E2");
toNumberBenchmark("-0E2");
toNumberBenchmark("00E2");
toNumberBenchmark("00E2", { leadingZeros: false });
toNumberBenchmark("0", { skipLike: /.*/ });
toNumberBenchmark("+12", { skipLike: /\+[0-9]{10}/ });
toNumberBenchmark("12+12", { skipLike: /\+[0-9]{10}/ });
toNumberBenchmark("12+1212121212", { skipLike: /\+[0-9]{10}/ });
toNumberBenchmark("+1212121212");
toNumberBenchmark("+1212121212", { skipLike: /\+[0-9]{10}/ });
toNumberBenchmark("+12 12");
toNumberBenchmark(" +12 12 ");
toNumberBenchmark(" +1212 ");
toNumberBenchmark("+1212");
toNumberBenchmark("+12.12");
toNumberBenchmark("-12.12");
toNumberBenchmark("-012.12");

toNumberBenchmark("Infinity");
toNumberBenchmark("-Infinity");
toNumberBenchmark("+Infinity");
toNumberBenchmark("Infinity", { infinity: true });
toNumberBenchmark("-Infinity", { infinity: true });
toNumberBenchmark("+Infinity", { infinity: true });
toNumberBenchmark("Infinity", { infinity: false });
toNumberBenchmark("-Infinity", { infinity: false });
toNumberBenchmark("+Infinity", { infinity: false });
toNumberBenchmark(" Infinity ");
toNumberBenchmark(" -Infinity ");
toNumberBenchmark(" +Infinity ");

await bench.run()

console.log(bench.name)
console.table(bench.table())
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
"description": "Parse String to Number based on configuration",
"type": "module",
"main": "strnum.js",
"types": "strnum.d.ts",
"scripts": {
"test": "jasmine strnum.test.js"
"test": "jasmine *.test.js",
"types": "tsc -p ."
},
"keywords": [
"string",
Expand All @@ -26,6 +28,8 @@
}
],
"devDependencies": {
"jasmine": "^5.6.0"
"jasmine": "^5.6.0",
"tinybench": "^4.0.1",
"typescript": "^5.8.3"
}
}
}
92 changes: 92 additions & 0 deletions strnum.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
declare module "strnum" {
/**
* @template {*} T
* @param {T} str - The string to convert to a number.
* @param {Options} [options] - Options to control the conversion behavior.
* @returns {number|T} - The converted number or the original value if conversion is not applicable.
*/
export default function toNumber<T extends unknown>(str: T, options?: Options): number | T;
/**
* @param {string} str - The string to analyze.
* @param {Options} options - Options to control the parsing behavior.
* @returns {number} - A bitmask representing the analysis result of the string.
*/
export function analyzeNumber(str: string, options: Options): number;
export type State = typeof NUMBER | typeof NOT_A_NUMBER | typeof BINARY | typeof DECIMAL | typeof OCTAL | typeof HEX | typeof FLOAT | typeof INTEGER | typeof BIGINT | typeof ZERO | typeof WHITESPACE | typeof BEGIN | typeof END | typeof LEADING_WHITESPACE | typeof TRAILING_WHITESPACE | typeof BEGIN_INTEGER_DIGITS | typeof BEGIN_FRAC_DIGITS | typeof BEGIN_BINARY | typeof BEGIN_HEX | typeof BEGIN_OCTAL | typeof BEGIN_EXPONENT | typeof BEGIN_ZERO | typeof FIRST_DIGIT_ZERO_NOT_LEADING | typeof LEADING_ZEROS | typeof INFINITY | typeof SIGN | typeof EXPONENT_INDICATOR | typeof EXPONENT_SIGN | typeof EXPONENT_DECIMAL;
export type Options = {
/**
* - Whether to allow hexadecimal numbers (e.g., "0x1A").
*/
hex?: boolean;
/**
* - Whether to allow octal numbers (e.g., "0o17").
*/
octal?: boolean;
/**
* - Whether to allow binary numbers (e.g., "0b1010").
*/
binary?: boolean;
/**
* - Whether to allow BigInt numbers (e.g., "123n").
*/
bigint?: boolean;
/**
* - Whether to allow leading zeros in numbers (e.g., "000123").
*/
leadingZeros?: boolean;
/**
* - Whether to check if the number is a safe integer.
*/
safeInteger?: boolean;
/**
* - Whether to allow "Infinity" and "-Infinity".
*/
infinity?: boolean;
/**
* - A regular expression to skip certain string patterns.
*/
skipLike?: RegExp;
/**
* - Whether to allow scientific notation (e.g., "1e10").
*/
eNotation?: boolean;
/**
* - Whether to treat empty strings or strings with whitespace as zero (e.g., " ").
*/
empty?: boolean;
/**
* - Whether to force IEEE 754 compliance for floating-point numbers (e.g. "1234567890.1234567890" => 1234567890.1234567).
*/
ieee754?: boolean;
};
const NUMBER: 0;
const NOT_A_NUMBER: 1;
const BINARY: 2;
const DECIMAL: 4;
const OCTAL: 8;
const HEX: 16;
const FLOAT: 32;
const INTEGER: 64;
const BIGINT: 128;
const ZERO: 2048;
const WHITESPACE: 512;
const BEGIN: 8192;
const END: 16384;
const LEADING_WHITESPACE: 8704;
const TRAILING_WHITESPACE: 16896;
const BEGIN_INTEGER_DIGITS: 8196;
const BEGIN_FRAC_DIGITS: 8224;
const BEGIN_BINARY: 8194;
const BEGIN_HEX: 8208;
const BEGIN_OCTAL: 8200;
const BEGIN_EXPONENT: 12288;
const BEGIN_ZERO: 10240;
const FIRST_DIGIT_ZERO_NOT_LEADING: 26624;
const LEADING_ZEROS: 10244;
const INFINITY: 256;
const SIGN: 1024;
const EXPONENT_INDICATOR: 4096;
const EXPONENT_SIGN: 5120;
const EXPONENT_DECIMAL: 4100;
export {};
}
Loading