Skip to content

Commit 776028c

Browse files
jesus-seijas-spjasnell
authored andcommitted
querystring: improve unescapeBuffer() performance
Refactored the `unescapeBuffer` function in order to simplify it, and also to improve the performance. PR-URL: #12525 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Brian White <[email protected]>
1 parent d0dbd53 commit 776028c

File tree

1 file changed

+34
-57
lines changed

1 file changed

+34
-57
lines changed

lib/querystring.js

+34-57
Original file line numberDiff line numberDiff line change
@@ -64,67 +64,44 @@ const unhexTable = [
6464
// a safe fast alternative to decodeURIComponent
6565
function unescapeBuffer(s, decodeSpaces) {
6666
var out = Buffer.allocUnsafe(s.length);
67-
var state = 0;
68-
var n, m, hexchar, c;
69-
70-
for (var inIndex = 0, outIndex = 0; ; inIndex++) {
71-
if (inIndex < s.length) {
72-
c = s.charCodeAt(inIndex);
73-
} else {
74-
if (state > 0) {
75-
out[outIndex++] = 37/*%*/;
76-
if (state === 2)
77-
out[outIndex++] = hexchar;
78-
}
79-
break;
67+
var index = 0;
68+
var outIndex = 0;
69+
var currentChar;
70+
var nextChar;
71+
var hexHigh;
72+
var hexLow;
73+
var maxLength = s.length - 2;
74+
// Flag to know if some hex chars have been decoded
75+
var hasHex = false;
76+
while (index < s.length) {
77+
currentChar = s.charCodeAt(index);
78+
if (currentChar === 43 /*'+'*/ && decodeSpaces) {
79+
out[outIndex++] = 32; // ' '
80+
index++;
81+
continue;
8082
}
81-
switch (state) {
82-
case 0: // Any character
83-
switch (c) {
84-
case 37: // '%'
85-
n = 0;
86-
m = 0;
87-
state = 1;
88-
break;
89-
case 43: // '+'
90-
if (decodeSpaces)
91-
c = 32; // ' '
92-
// falls through
93-
default:
94-
out[outIndex++] = c;
95-
break;
96-
}
97-
break;
98-
99-
case 1: // First hex digit
100-
hexchar = c;
101-
n = unhexTable[c];
102-
if (!(n >= 0)) {
103-
out[outIndex++] = 37/*%*/;
104-
out[outIndex++] = c;
105-
state = 0;
106-
break;
107-
}
108-
state = 2;
109-
break;
110-
111-
case 2: // Second hex digit
112-
state = 0;
113-
m = unhexTable[c];
114-
if (!(m >= 0)) {
115-
out[outIndex++] = 37/*%*/;
116-
out[outIndex++] = hexchar;
117-
out[outIndex++] = c;
118-
break;
83+
if (currentChar === 37 /*'%'*/ && index < maxLength) {
84+
currentChar = s.charCodeAt(++index);
85+
hexHigh = unhexTable[currentChar];
86+
if (!(hexHigh >= 0)) {
87+
out[outIndex++] = 37; // '%'
88+
} else {
89+
nextChar = s.charCodeAt(++index);
90+
hexLow = unhexTable[nextChar];
91+
if (!(hexLow >= 0)) {
92+
out[outIndex++] = 37; // '%'
93+
out[outIndex++] = currentChar;
94+
currentChar = nextChar;
95+
} else {
96+
hasHex = true;
97+
currentChar = hexHigh * 16 + hexLow;
11998
}
120-
out[outIndex++] = 16 * n + m;
121-
break;
99+
}
122100
}
101+
out[outIndex++] = currentChar;
102+
index++;
123103
}
124-
125-
// TODO support returning arbitrary buffers.
126-
127-
return out.slice(0, outIndex);
104+
return hasHex ? out.slice(0, outIndex) : out;
128105
}
129106

130107

0 commit comments

Comments
 (0)