querystring: improve unescapeBuffer performance
PR-URL: https://github.com/nodejs/node/pull/10837 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
05f38be556
commit
3bdcbdb1a0
23
benchmark/querystring/querystring-unescapebuffer.js
Normal file
23
benchmark/querystring/querystring-unescapebuffer.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
'use strict';
|
||||||
|
var common = require('../common.js');
|
||||||
|
var querystring = require('querystring');
|
||||||
|
|
||||||
|
var bench = common.createBenchmark(main, {
|
||||||
|
input: [
|
||||||
|
'there is nothing to unescape here',
|
||||||
|
'there%20are%20several%20spaces%20that%20need%20to%20be%20unescaped',
|
||||||
|
'there%2Qare%0-fake%escaped values in%%%%this%9Hstring',
|
||||||
|
'%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37'
|
||||||
|
],
|
||||||
|
n: [10e6],
|
||||||
|
});
|
||||||
|
|
||||||
|
function main(conf) {
|
||||||
|
var input = conf.input;
|
||||||
|
var n = conf.n | 0;
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
for (var i = 0; i < n; i += 1)
|
||||||
|
querystring.unescapeBuffer(input);
|
||||||
|
bench.end(n);
|
||||||
|
}
|
@ -22,15 +22,41 @@ const Buffer = require('buffer').Buffer;
|
|||||||
function ParsedQueryString() {}
|
function ParsedQueryString() {}
|
||||||
ParsedQueryString.prototype = Object.create(null);
|
ParsedQueryString.prototype = Object.create(null);
|
||||||
|
|
||||||
|
const unhexTable = [
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0 - 15
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16 - 31
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32 - 47
|
||||||
|
+0, +1, +2, +3, +4, +5, +6, +7, +8, +9, -1, -1, -1, -1, -1, -1, // 48 - 63
|
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64 - 79
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80 - 95
|
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96 - 111
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112 - 127
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128 ...
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // ... 255
|
||||||
|
];
|
||||||
// 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 state = 0;
|
||||||
var n, m, hexchar;
|
var n, m, hexchar, c;
|
||||||
|
|
||||||
for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) {
|
for (var inIndex = 0, outIndex = 0; ; inIndex++) {
|
||||||
var c = inIndex < s.length ? s.charCodeAt(inIndex) : NaN;
|
if (inIndex < s.length) {
|
||||||
|
c = s.charCodeAt(inIndex);
|
||||||
|
} else {
|
||||||
|
if (state > 0) {
|
||||||
|
out[outIndex++] = 37/*%*/;
|
||||||
|
if (state === 2)
|
||||||
|
out[outIndex++] = hexchar;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0: // Any character
|
case 0: // Any character
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -51,13 +77,8 @@ function unescapeBuffer(s, decodeSpaces) {
|
|||||||
|
|
||||||
case 1: // First hex digit
|
case 1: // First hex digit
|
||||||
hexchar = c;
|
hexchar = c;
|
||||||
if (c >= 48/*0*/ && c <= 57/*9*/) {
|
n = unhexTable[c];
|
||||||
n = c - 48/*0*/;
|
if (!(n >= 0)) {
|
||||||
} else if (c >= 65/*A*/ && c <= 70/*F*/) {
|
|
||||||
n = c - 65/*A*/ + 10;
|
|
||||||
} else if (c >= 97/*a*/ && c <= 102/*f*/) {
|
|
||||||
n = c - 97/*a*/ + 10;
|
|
||||||
} else {
|
|
||||||
out[outIndex++] = 37/*%*/;
|
out[outIndex++] = 37/*%*/;
|
||||||
out[outIndex++] = c;
|
out[outIndex++] = c;
|
||||||
state = 0;
|
state = 0;
|
||||||
@ -68,13 +89,8 @@ function unescapeBuffer(s, decodeSpaces) {
|
|||||||
|
|
||||||
case 2: // Second hex digit
|
case 2: // Second hex digit
|
||||||
state = 0;
|
state = 0;
|
||||||
if (c >= 48/*0*/ && c <= 57/*9*/) {
|
m = unhexTable[c];
|
||||||
m = c - 48/*0*/;
|
if (!(m >= 0)) {
|
||||||
} else if (c >= 65/*A*/ && c <= 70/*F*/) {
|
|
||||||
m = c - 65/*A*/ + 10;
|
|
||||||
} else if (c >= 97/*a*/ && c <= 102/*f*/) {
|
|
||||||
m = c - 97/*a*/ + 10;
|
|
||||||
} else {
|
|
||||||
out[outIndex++] = 37/*%*/;
|
out[outIndex++] = 37/*%*/;
|
||||||
out[outIndex++] = hexchar;
|
out[outIndex++] = hexchar;
|
||||||
out[outIndex++] = c;
|
out[outIndex++] = c;
|
||||||
@ -87,7 +103,7 @@ function unescapeBuffer(s, decodeSpaces) {
|
|||||||
|
|
||||||
// TODO support returning arbitrary buffers.
|
// TODO support returning arbitrary buffers.
|
||||||
|
|
||||||
return out.slice(0, outIndex - 1);
|
return out.slice(0, outIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -271,6 +271,13 @@ assert.strictEqual(0xd8, b[17]);
|
|||||||
assert.strictEqual(0xa2, b[18]);
|
assert.strictEqual(0xa2, b[18]);
|
||||||
assert.strictEqual(0xe6, b[19]);
|
assert.strictEqual(0xe6, b[19]);
|
||||||
|
|
||||||
|
assert.strictEqual(qs.unescapeBuffer('a+b', true).toString(), 'a b');
|
||||||
|
assert.strictEqual(qs.unescapeBuffer('a%').toString(), 'a%');
|
||||||
|
assert.strictEqual(qs.unescapeBuffer('a%2').toString(), 'a%2');
|
||||||
|
assert.strictEqual(qs.unescapeBuffer('a%20').toString(), 'a ');
|
||||||
|
assert.strictEqual(qs.unescapeBuffer('a%2g').toString(), 'a%2g');
|
||||||
|
assert.strictEqual(qs.unescapeBuffer('a%%').toString(), 'a%%');
|
||||||
|
|
||||||
|
|
||||||
// Test custom decode
|
// Test custom decode
|
||||||
function demoDecode(str) {
|
function demoDecode(str) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user