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:
Jesus Seijas 2017-04-20 00:37:56 +02:00 committed by Luigi Pinca
parent 6a18c1d8dd
commit 19685eac65

View File

@ -64,67 +64,44 @@ const unhexTable = [
// a safe fast alternative to decodeURIComponent // a safe fast alternative to decodeURIComponent
function unescapeBuffer(s, decodeSpaces) { function unescapeBuffer(s, decodeSpaces) {
var out = Buffer.allocUnsafe(s.length); var out = Buffer.allocUnsafe(s.length);
var state = 0; var index = 0;
var n, m, hexchar, c; var outIndex = 0;
var currentChar;
for (var inIndex = 0, outIndex = 0; ; inIndex++) { var nextChar;
if (inIndex < s.length) { var hexHigh;
c = s.charCodeAt(inIndex); var hexLow;
} else { var maxLength = s.length - 2;
if (state > 0) { // Flag to know if some hex chars have been decoded
out[outIndex++] = 37/*%*/; var hasHex = false;
if (state === 2) while (index < s.length) {
out[outIndex++] = hexchar; 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++;
} }
return hasHex ? out.slice(0, outIndex) : out;
// TODO support returning arbitrary buffers.
return out.slice(0, outIndex);
} }