Skip to content
Permalink
Browse files

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 <luigipinca@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
  • Loading branch information...
jseijas authored and jasnell committed Apr 19, 2017
1 parent d0dbd53 commit 776028c46b5841a97130a6bb4b67ee31926e3403
Showing with 34 additions and 57 deletions.
  1. +34 −57 lib/querystring.js
@@ -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;
}
break;
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;
}
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;
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;
}
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;
}


0 comments on commit 776028c

Please sign in to comment.
You can’t perform that action at this time.