@vltpkg/fast-split 0.0.0-0.1730239248325

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright (c) vlt technology, Inc.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7
+ Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by:
8
+
9
+ (a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of contributors, in source or binary form) alone; or
10
+ (b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution.
11
+ Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this license, whether expressly, by implication, estoppel or otherwise.
12
+
13
+ DISCLAIMER
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # `@vltpkg/fast-split`
2
+
3
+ This is a very fast alternative to `String.split()`, which can be
4
+ used to quickly parse a small-to-medium sized string by a given
5
+ delimiter.
6
+
7
+ ## HOW FAST IS IT!?
8
+
9
+ This is about 10% faster for splitting short strings by a short delimiter.
10
+ When we have to walk the resulting list for any reason, or limit the number
11
+ of items returned, it's an even bigger difference.
12
+
13
+ 2024 M1 macbook pro, using node 20.11.0, v8 version 11.3.244.8-node.17
14
+ Counts are operations per ms, splitting the string '1.2.3-asdf+foo' by the
15
+ delimiter '.', transforms calling part.toUpperCase(), and limits at 2 items
16
+
17
+ ```
18
+ split 10385.779
19
+ fastSplit 10718.341
20
+ splitEmptyCheck 9563.721
21
+ fastSplitEmptyCheck 11273.537
22
+ splitTransformLoop 5722.724
23
+ splitTransformMap 6136.161
24
+ fastSplitTransform 6438.606
25
+ splitLimit 7076.179
26
+ fastSplitLimit 13257.948
27
+ ```
28
+
29
+ ## USAGE
30
+
31
+ ```js
32
+ import { fastSplit } from '@vltpkg/fast-split'
33
+
34
+ // say we want to split a string on '.' characters
35
+ const str = getSomeStringSomehow()
36
+
37
+ // basic usage, just like str.split('.'), gives us an array
38
+ const parts = fastSplit(str, '.')
39
+
40
+ // get just the first two parts, leave the rest intact
41
+ // Note: unlike str.split('.', 3), the 'rest' here will
42
+ // include the entire rest of the string.
43
+ // If you do `str.split('.', 3)`, then the last item in the
44
+ // returned array is truncated at the next delimiter
45
+ const [first, second, rest] = fastSplit(str, '.', 3)
46
+
47
+ // If you need to transform it, say if it's an IPv4 address
48
+ // that you want to turn into numbers, you can do that by
49
+ // providing the onPart method, which will be slightly faster
50
+ // than getting an array and subsequently looping over it
51
+ // pass `-1` as the limit to give us all parts
52
+ const nums = fastSplit(str, '.', -1, (part, parts, index) =>
53
+ Number(s),
54
+ )
55
+ ```
@@ -0,0 +1,44 @@
1
+ /** utility types to turn a null/undefined/void return into string */
2
+ export type NullToString<T> = VoidReplace<T>;
3
+ /** Utility type to replace null/undefined with a given type */
4
+ export type NullReplace<T, R = string> = T extends NonNullable<T> ? T : NonNullable<T> | R;
5
+ /** Utility type to replace void with a given type */
6
+ export type VoidReplace<T, R = string> = undefined extends T ? NullReplace<Exclude<T, void>, R> | R : NullReplace<T, R>;
7
+ /**
8
+ * Split a string by a string delimiter, optionally limiting the number
9
+ * of parts parsed, and/or transforming the string parts into some other
10
+ * type of value.
11
+ *
12
+ * Pass `-1` as the `limit` parameter to get all parts (useful if an `onPart`
13
+ * method is provided)
14
+ *
15
+ * If an `onPart` method is provided, and returns `undefined`, then the
16
+ * original string part is included in the result set.
17
+ *
18
+ * ```ts
19
+ * import { fastSplit } from '@vltpkg/fast-split'
20
+ *
21
+ * // say we want to split a string on '.' characters
22
+ * const str = getSomeStringSomehow()
23
+ *
24
+ * // basic usage, just like str.split('.'), gives us an array
25
+ * const parts = fastSplit(str, '.')
26
+ *
27
+ * // get just the first two parts, leave the rest intact
28
+ * // Note: unlike str.split('.', 3), the 'rest' here will
29
+ * // include the entire rest of the string.
30
+ * // If you do `str.split('.', 3)`, then the last item in the
31
+ * // returned array is truncated at the next delimiter
32
+ * const [first, second, rest] = fastSplit(str, '.', 3)
33
+ *
34
+ * // If you need to transform it, say if it's an IPv4 address
35
+ * // that you want to turn into numbers, you can do that by
36
+ * // providing the onPart method, which will be slightly faster
37
+ * // than getting an array and subsequently looping over it
38
+ * // pass `-1` as the limit to give us all parts
39
+ * const nums = fastSplit(str, '.', -1, (part, parts, index) => Number(s))
40
+ * ```
41
+ */
42
+ export declare function fastSplit<T = string>(str: string, delim: string, limit: number, onPart: (part: string, parts: NullToString<T>[], i: number) => T): NullToString<T>[];
43
+ export declare function fastSplit(str: string, delim: string, limit?: number): string[];
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAA;AAE5C,+DAA+D;AAC/D,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,IACnC,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AAEnD,qDAAqD;AACrD,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,IACnC,SAAS,SAAS,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GACxD,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,MAAM,EAClC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC,GAC/D,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;AACpB,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,EAAE,CAAA"}
@@ -0,0 +1,20 @@
1
+ export function fastSplit(str, delim, limit = -1, onPart) {
2
+ let i = 0;
3
+ let p = 0;
4
+ const l = delim.length;
5
+ const parts = [];
6
+ while (i !== -1) {
7
+ i = str.indexOf(delim, p);
8
+ const part = i === -1 || parts.length === limit - 1 ?
9
+ str.substring(p)
10
+ : str.substring(p, i);
11
+ parts.push((onPart?.(part, parts, i) ?? part));
12
+ if (parts.length === limit) {
13
+ // push the rest into the last part
14
+ return parts;
15
+ }
16
+ p = i + l;
17
+ }
18
+ return parts;
19
+ }
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA0DA,MAAM,UAAU,SAAS,CACvB,GAAW,EACX,KAAa,EACb,KAAK,GAAG,CAAC,CAAC,EACV,MAIkB;IAElB,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAA;IACtB,MAAM,KAAK,GAAsB,EAAE,CAAA;IACnC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACzB,MAAM,IAAI,GACR,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC;YACtC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;YAClB,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACvB,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,IAAI,CAAoB,CAAC,CAAA;QACjE,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC3B,mCAAmC;YACnC,OAAO,KAAK,CAAA;QACd,CAAC;QACD,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["/** utility types to turn a null/undefined/void return into string */\nexport type NullToString<T> = VoidReplace<T>\n\n/** Utility type to replace null/undefined with a given type */\nexport type NullReplace<T, R = string> =\n T extends NonNullable<T> ? T : NonNullable<T> | R\n\n/** Utility type to replace void with a given type */\nexport type VoidReplace<T, R = string> =\n undefined extends T ? NullReplace<Exclude<T, void>, R> | R\n : NullReplace<T, R>\n\n/**\n * Split a string by a string delimiter, optionally limiting the number\n * of parts parsed, and/or transforming the string parts into some other\n * type of value.\n *\n * Pass `-1` as the `limit` parameter to get all parts (useful if an `onPart`\n * method is provided)\n *\n * If an `onPart` method is provided, and returns `undefined`, then the\n * original string part is included in the result set.\n *\n * ```ts\n * import { fastSplit } from '@vltpkg/fast-split'\n *\n * // say we want to split a string on '.' characters\n * const str = getSomeStringSomehow()\n *\n * // basic usage, just like str.split('.'), gives us an array\n * const parts = fastSplit(str, '.')\n *\n * // get just the first two parts, leave the rest intact\n * // Note: unlike str.split('.', 3), the 'rest' here will\n * // include the entire rest of the string.\n * // If you do `str.split('.', 3)`, then the last item in the\n * // returned array is truncated at the next delimiter\n * const [first, second, rest] = fastSplit(str, '.', 3)\n *\n * // If you need to transform it, say if it's an IPv4 address\n * // that you want to turn into numbers, you can do that by\n * // providing the onPart method, which will be slightly faster\n * // than getting an array and subsequently looping over it\n * // pass `-1` as the limit to give us all parts\n * const nums = fastSplit(str, '.', -1, (part, parts, index) => Number(s))\n * ```\n */\nexport function fastSplit<T = string>(\n str: string,\n delim: string,\n limit: number,\n onPart: (part: string, parts: NullToString<T>[], i: number) => T,\n): NullToString<T>[]\nexport function fastSplit(\n str: string,\n delim: string,\n limit?: number,\n): string[]\nexport function fastSplit<T = string>(\n str: string,\n delim: string,\n limit = -1,\n onPart?: (\n part: string,\n parts: NullToString<T>[],\n i: number,\n ) => T | undefined,\n): NullToString<T>[] {\n let i = 0\n let p = 0\n const l = delim.length\n const parts: NullToString<T>[] = []\n while (i !== -1) {\n i = str.indexOf(delim, p)\n const part =\n i === -1 || parts.length === limit - 1 ?\n str.substring(p)\n : str.substring(p, i)\n parts.push((onPart?.(part, parts, i) ?? part) as NullToString<T>)\n if (parts.length === limit) {\n // push the rest into the last part\n return parts\n }\n p = i + l\n }\n return parts\n}\n"]}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@vltpkg/fast-split",
3
+ "description": "A fast way to split small-to-medium sized strings by small string delimiters",
4
+ "version": "0.0.0-0.1730239248325",
5
+ "tshy": {
6
+ "selfLink": false,
7
+ "dialects": [
8
+ "esm"
9
+ ],
10
+ "exports": {
11
+ "./package.json": "./package.json",
12
+ ".": "./src/index.ts"
13
+ }
14
+ },
15
+ "devDependencies": {
16
+ "@eslint/js": "^9.8.0",
17
+ "@types/eslint__js": "^8.42.3",
18
+ "@types/node": "^22.4.1",
19
+ "eslint": "^9.8.0",
20
+ "prettier": "^3.3.2",
21
+ "tap": "^21.0.1",
22
+ "tshy": "^3.0.2",
23
+ "typescript": "^5.5.4",
24
+ "typescript-eslint": "^8.0.1"
25
+ },
26
+ "license": "BSD-2-Clause-Patent",
27
+ "engines": {
28
+ "node": "20 || >=22"
29
+ },
30
+ "tap": {
31
+ "extends": "../../tap-config.yaml"
32
+ },
33
+ "prettier": "../../.prettierrc.js",
34
+ "module": "./dist/esm/index.js",
35
+ "type": "module",
36
+ "exports": {
37
+ "./package.json": "./package.json",
38
+ ".": {
39
+ "import": {
40
+ "types": "./dist/esm/index.d.ts",
41
+ "default": "./dist/esm/index.js"
42
+ }
43
+ }
44
+ },
45
+ "files": [
46
+ "dist"
47
+ ],
48
+ "scripts": {
49
+ "benchmark:split": "./test/fixtures/split-vs-fast-split.ts",
50
+ "format": "prettier --write . --log-level warn --ignore-path ../../.prettierignore --cache",
51
+ "format:check": "prettier --check . --ignore-path ../../.prettierignore --cache",
52
+ "lint": "eslint . --fix",
53
+ "lint:check": "eslint .",
54
+ "presnap": "tshy",
55
+ "snap": "tap",
56
+ "pretest": "tshy",
57
+ "test": "tap"
58
+ }
59
+ }