buffer: optimize hex_decode
PR-URL: https://github.com/nodejs/node/pull/7602 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
35e8c9481f
commit
151d316b99
26
benchmark/buffers/buffer-hex.js
Normal file
26
benchmark/buffers/buffer-hex.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common.js');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
len: [0, 1, 64, 1024],
|
||||||
|
n: [1e7]
|
||||||
|
});
|
||||||
|
|
||||||
|
function main(conf) {
|
||||||
|
const len = conf.len | 0;
|
||||||
|
const n = conf.n | 0;
|
||||||
|
const buf = Buffer.alloc(len);
|
||||||
|
|
||||||
|
for (let i = 0; i < buf.length; i++)
|
||||||
|
buf[i] = i & 0xff;
|
||||||
|
|
||||||
|
const hex = buf.toString('hex');
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (let i = 0; i < n; i += 1)
|
||||||
|
Buffer.from(hex, 'hex');
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
}
|
@ -143,16 +143,27 @@ const int8_t unbase64_table[256] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename TypeName>
|
static const int8_t unhex_table[256] =
|
||||||
unsigned hex2bin(TypeName c) {
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
if (c >= '0' && c <= '9')
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
return c - '0';
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
if (c >= 'A' && c <= 'F')
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||||
return 10 + (c - 'A');
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
if (c >= 'a' && c <= 'f')
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
return 10 + (c - 'a');
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
return static_cast<unsigned>(-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, -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
|
||||||
|
};
|
||||||
|
|
||||||
|
#define unhex(x) \
|
||||||
|
static_cast<unsigned>(unhex_table[static_cast<uint8_t>(x)])
|
||||||
|
|
||||||
|
|
||||||
template <typename TypeName>
|
template <typename TypeName>
|
||||||
@ -162,11 +173,11 @@ size_t hex_decode(char* buf,
|
|||||||
const size_t srcLen) {
|
const size_t srcLen) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
|
for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
|
||||||
unsigned a = hex2bin(src[i * 2 + 0]);
|
unsigned a = unhex(src[i * 2 + 0]);
|
||||||
unsigned b = hex2bin(src[i * 2 + 1]);
|
unsigned b = unhex(src[i * 2 + 1]);
|
||||||
if (!~a || !~b)
|
if (!~a || !~b)
|
||||||
return i;
|
return i;
|
||||||
buf[i] = a * 16 + b;
|
buf[i] = (a << 4) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
43
test/parallel/test-buffer-badhex.js
Normal file
43
test/parallel/test-buffer-badhex.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const Buffer = require('buffer').Buffer;
|
||||||
|
|
||||||
|
// Test hex strings and bad hex strings
|
||||||
|
{
|
||||||
|
const buf1 = Buffer.alloc(4);
|
||||||
|
assert.strictEqual(buf1.length, 4);
|
||||||
|
assert.deepStrictEqual(buf1, new Buffer([0, 0, 0, 0]));
|
||||||
|
assert.strictEqual(buf1.write('abcdxx', 0, 'hex'), 2);
|
||||||
|
assert.deepStrictEqual(buf1, new Buffer([0xab, 0xcd, 0x00, 0x00]));
|
||||||
|
assert.strictEqual(buf1.toString('hex'), 'abcd0000');
|
||||||
|
assert.strictEqual(buf1.write('abcdef01', 0, 'hex'), 4);
|
||||||
|
assert.deepStrictEqual(buf1, new Buffer([0xab, 0xcd, 0xef, 0x01]));
|
||||||
|
assert.strictEqual(buf1.toString('hex'), 'abcdef01');
|
||||||
|
|
||||||
|
const buf2 = Buffer.from(buf1.toString('hex'), 'hex');
|
||||||
|
assert.strictEqual(buf1.toString('hex'), buf2.toString('hex'));
|
||||||
|
|
||||||
|
const buf3 = Buffer.alloc(5);
|
||||||
|
assert.strictEqual(buf3.write('abcdxx', 1, 'hex'), 2);
|
||||||
|
assert.strictEqual(buf3.toString('hex'), '00abcd0000');
|
||||||
|
|
||||||
|
const buf4 = Buffer.alloc(4);
|
||||||
|
assert.deepStrictEqual(buf4, new Buffer([0, 0, 0, 0]));
|
||||||
|
assert.strictEqual(buf4.write('xxabcd', 0, 'hex'), 0);
|
||||||
|
assert.deepStrictEqual(buf4, new Buffer([0, 0, 0, 0]));
|
||||||
|
assert.strictEqual(buf4.write('xxab', 1, 'hex'), 0);
|
||||||
|
assert.deepStrictEqual(buf4, new Buffer([0, 0, 0, 0]));
|
||||||
|
assert.strictEqual(buf4.write('cdxxab', 0, 'hex'), 1);
|
||||||
|
assert.deepStrictEqual(buf4, new Buffer([0xcd, 0, 0, 0]));
|
||||||
|
|
||||||
|
const buf5 = Buffer.alloc(256);
|
||||||
|
for (let i = 0; i < 256; i++)
|
||||||
|
buf5[i] = i;
|
||||||
|
|
||||||
|
const hex = buf5.toString('hex');
|
||||||
|
assert.deepStrictEqual(Buffer.from(hex, 'hex'), buf5);
|
||||||
|
|
||||||
|
const badHex = hex.slice(0, 256) + 'xx' + hex.slice(256, 510);
|
||||||
|
assert.deepStrictEqual(Buffer.from(badHex, 'hex'), buf5.slice(0, 128));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user