Skip to content

Commit ff16295

Browse files
committed
feat: initial commit
0 parents  commit ff16295

7 files changed

Lines changed: 915 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

lib/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
3+
const parse = require("./parse");
4+
5+
module.exports = {
6+
parse,
7+
};

lib/parse.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"use strict";
2+
3+
/**
4+
* @callback parse
5+
* @param {string} input
6+
*/
7+
function parse(input) {
8+
let result = {};
9+
10+
let currentKey = [""];
11+
let currentValue = "";
12+
let currentPairIsArray = false;
13+
let seenEqualOperator = false;
14+
15+
// Have a boundary of input.length + 1 to access last pair inside the loop.
16+
for (let i = 0; i < input.length + 1; i++) {
17+
let currentCharacter = input.charCodeAt(i);
18+
let currentKeyLength = currentKey.length;
19+
20+
if (isNaN(currentCharacter)) {
21+
currentCharacter = 38;
22+
}
23+
24+
switch (currentCharacter) {
25+
// &
26+
case 38: {
27+
let root = result;
28+
29+
for (let k = 0; k < currentKeyLength; k++) {
30+
let key = currentKey[k];
31+
32+
if (typeof root[key] === "undefined") {
33+
if (k === currentKeyLength - 1) {
34+
if (currentPairIsArray) {
35+
root[key] = [currentValue];
36+
} else {
37+
root[key] = currentValue;
38+
}
39+
} else {
40+
root[key] = {};
41+
root = root[key];
42+
}
43+
} else if (Array.isArray(root[key])) {
44+
root[key].push(currentValue);
45+
} else {
46+
root[key] = [root[key], currentValue];
47+
}
48+
}
49+
50+
// Reset reading key value pairs
51+
currentKey = [""];
52+
currentValue = "";
53+
seenEqualOperator = false;
54+
currentPairIsArray = false;
55+
break;
56+
}
57+
// ']'
58+
case 93: {
59+
// Ignore ']' character, since it's already handled inside '['.
60+
break;
61+
}
62+
// '['
63+
case 91: {
64+
let nextCharacter = input.charCodeAt(i + 1);
65+
66+
// Check if input is an array. Example: hello[]=world equals to { hello: ['world'] }
67+
if (nextCharacter === 93) {
68+
currentPairIsArray = true;
69+
i++;
70+
}
71+
// Check push a new key to keys. Only applicable when key is not an array, but consists of length > 0.
72+
else {
73+
currentKey.push("");
74+
}
75+
76+
break;
77+
}
78+
// '='
79+
case 61: {
80+
seenEqualOperator = true;
81+
break;
82+
}
83+
default: {
84+
if (seenEqualOperator) {
85+
currentValue += input[i];
86+
} else {
87+
currentKey[currentKeyLength - 1] += input[i];
88+
}
89+
}
90+
}
91+
}
92+
93+
return result;
94+
}
95+
96+
module.exports = parse;

package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "fast-querystring",
3+
"version": "0.1.0",
4+
"description": "",
5+
"main": "lib/index.js",
6+
"type": "commonjs",
7+
"scripts": {
8+
"format": "rome format . --indent-style space --write",
9+
"test": "vitest",
10+
"test:watch": "vitest --watch",
11+
"coverage": "vitest run --coverage",
12+
"benchmark": "node test/benchmark.mjs"
13+
},
14+
"keywords": ["querystring", "qs", "parser"],
15+
"author": "Yagiz Nizipli <yagiz@nizipli.com>",
16+
"license": "MIT",
17+
"devDependencies": {
18+
"cronometro": "^1.1.2",
19+
"qs": "^6.11.0",
20+
"rome": "0.8.0-next.ff4153b",
21+
"url-state-machine": "^0.5.1",
22+
"vitest": "^0.22.1"
23+
},
24+
"repository": {
25+
"url": "git+https://github.com/anonrig/fast-querystring.git",
26+
"type": "git"
27+
}
28+
}

0 commit comments

Comments
 (0)