mirror of https://github.com/nodejs/node.git
querystring: improve unescapeBuffer() performance
Refactored the `unescapeBuffer` function in order to simplify it, and also to improve the performance. PR-URL: https://github.com/nodejs/node/pull/12525 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>
This commit is contained in:
parent
6a18c1d8dd
commit
19685eac65
|
@ -64,67 +64,44 @@ const unhexTable = [
|
|||
// a safe fast alternative to decodeURIComponent
|
||||
function unescapeBuffer(s, decodeSpaces) {
|
||||
var out = Buffer.allocUnsafe(s.length);
|
||||
var state = 0;
|
||||
var n, m, hexchar, c;
|
||||
|
||||
for (var inIndex = 0, outIndex = 0; ; inIndex++) {
|
||||
if (inIndex < s.length) {
|
||||
c = s.charCodeAt(inIndex);
|
||||
} else {
|
||||
if (state > 0) {
|
||||
out[outIndex++] = 37/*%*/;
|
||||
if (state === 2)
|
||||
out[outIndex++] = hexchar;
|
||||
var index = 0;
|
||||
var outIndex = 0;
|
||||
var currentChar;
|
||||
var nextChar;
|
||||
var hexHigh;
|
||||
var hexLow;
|
||||
var maxLength = s.length - 2;
|
||||
// Flag to know if some hex chars have been decoded
|
||||
var hasHex = false;
|
||||
while (index < s.length) {
|
||||
currentChar = s.charCodeAt(index);
|
||||
if (currentChar === 43 /*'+'*/ && decodeSpaces) {
|
||||
out[outIndex++] = 32; // ' '
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
if (currentChar === 37 /*'%'*/ && index < maxLength) {
|
||||
currentChar = s.charCodeAt(++index);
|
||||
hexHigh = unhexTable[currentChar];
|
||||
if (!(hexHigh >= 0)) {
|
||||
out[outIndex++] = 37; // '%'
|
||||
} else {
|
||||
nextChar = s.charCodeAt(++index);
|
||||
hexLow = unhexTable[nextChar];
|
||||
if (!(hexLow >= 0)) {
|
||||
out[outIndex++] = 37; // '%'
|
||||
out[outIndex++] = currentChar;
|
||||
currentChar = nextChar;
|
||||
} else {
|
||||
hasHex = true;
|
||||
currentChar = hexHigh * 16 + hexLow;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (state) {
|
||||
case 0: // Any character
|
||||
switch (c) {
|
||||
case 37: // '%'
|
||||
n = 0;
|
||||
m = 0;
|
||||
state = 1;
|
||||
break;
|
||||
case 43: // '+'
|
||||
if (decodeSpaces)
|
||||
c = 32; // ' '
|
||||
// falls through
|
||||
default:
|
||||
out[outIndex++] = c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // First hex digit
|
||||
hexchar = c;
|
||||
n = unhexTable[c];
|
||||
if (!(n >= 0)) {
|
||||
out[outIndex++] = 37/*%*/;
|
||||
out[outIndex++] = c;
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2: // Second hex digit
|
||||
state = 0;
|
||||
m = unhexTable[c];
|
||||
if (!(m >= 0)) {
|
||||
out[outIndex++] = 37/*%*/;
|
||||
out[outIndex++] = hexchar;
|
||||
out[outIndex++] = c;
|
||||
break;
|
||||
}
|
||||
out[outIndex++] = 16 * n + m;
|
||||
break;
|
||||
}
|
||||
out[outIndex++] = currentChar;
|
||||
index++;
|
||||
}
|
||||
|
||||
// TODO support returning arbitrary buffers.
|
||||
|
||||
return out.slice(0, outIndex);
|
||||
return hasHex ? out.slice(0, outIndex) : out;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue