From 64744a282e661a426d2092901bb7f4f02a0cb746 Mon Sep 17 00:00:00 2001 From: garygsc Date: Mon, 11 Nov 2019 11:59:07 -0700 Subject: [PATCH] buffer: add {read|write}Big[U]Int64{BE|LE} methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/30361 PR-URL: https://github.com/nodejs/node/pull/19691 Reviewed-By: Ben Noordhuis Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Joyee Cheung Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Tobias Nießen Reviewed-By: Matteo Collina --- benchmark/buffers/buffer-read.js | 4 + benchmark/buffers/buffer-write.js | 21 ++++ doc/api/buffer.md | 91 ++++++++++++++++ lib/internal/buffer.js | 146 ++++++++++++++++++++++++++ test/parallel/test-buffer-bigint64.js | 51 +++++++++ 5 files changed, 313 insertions(+) create mode 100644 test/parallel/test-buffer-bigint64.js diff --git a/benchmark/buffers/buffer-read.js b/benchmark/buffers/buffer-read.js index eccbdc507d6fa2..f2609f3f352b09 100644 --- a/benchmark/buffers/buffer-read.js +++ b/benchmark/buffers/buffer-read.js @@ -2,6 +2,10 @@ const common = require('../common.js'); const types = [ + 'BigUInt64LE', + 'BigUInt64BE', + 'BigInt64LE', + 'BigInt64BE', 'UInt8', 'UInt16LE', 'UInt16BE', diff --git a/benchmark/buffers/buffer-write.js b/benchmark/buffers/buffer-write.js index 556423a15c1c91..8cf5d3a40b519d 100644 --- a/benchmark/buffers/buffer-write.js +++ b/benchmark/buffers/buffer-write.js @@ -2,6 +2,10 @@ const common = require('../common.js'); const types = [ + 'BigUInt64LE', + 'BigUInt64BE', + 'BigInt64LE', + 'BigInt64BE', 'UInt8', 'UInt16LE', 'UInt16BE', @@ -32,11 +36,17 @@ const INT8 = 0x7f; const INT16 = 0x7fff; const INT32 = 0x7fffffff; const INT48 = 0x7fffffffffff; +const INT64 = 0x7fffffffffffffffn; const UINT8 = 0xff; const UINT16 = 0xffff; const UINT32 = 0xffffffff; +const UINT64 = 0xffffffffffffffffn; const mod = { + writeBigInt64BE: INT64, + writeBigInt64LE: INT64, + writeBigUInt64BE: UINT64, + writeBigUInt64LE: UINT64, writeInt8: INT8, writeInt16BE: INT16, writeInt16LE: INT16, @@ -67,12 +77,23 @@ function main({ n, buf, type }) { if (!/\d/.test(fn)) benchSpecialInt(buff, fn, n); + else if (/BigU?Int/.test(fn)) + benchBigInt(buff, fn, BigInt(n)); else if (/Int/.test(fn)) benchInt(buff, fn, n); else benchFloat(buff, fn, n); } +function benchBigInt(buff, fn, n) { + const m = mod[fn]; + bench.start(); + for (var i = 0n; i !== n; i++) { + buff[fn](i & m, 0); + } + bench.end(Number(n)); +} + function benchInt(buff, fn, n) { const m = mod[fn]; bench.start(); diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 8379e5b2187540..862620e5815b13 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -1529,6 +1529,47 @@ deprecated: v8.0.0 The `buf.parent` property is a deprecated alias for `buf.buffer`. +### buf.readBigInt64BE(offset) +### buf.readBigInt64LE(offset) + + +* `offset` {integer} Number of bytes to skip before starting to read. Must + satisfy: `0 <= offset <= buf.length - 8`. **Default:** `0`. +* Returns: {bigint} + +Reads a signed 64-bit integer from `buf` at the specified `offset` with +the specified endian format (`readBigInt64BE()` returns big endian, +`readBigInt64LE()` returns little endian). + +Integers read from a `Buffer` are interpreted as two's complement signed values. + +### buf.readBigUInt64BE(offset) +### buf.readBigUInt64LE(offset) + + +* `offset` {integer} Number of bytes to skip before starting to read. Must + satisfy: `0 <= offset <= buf.length - 8`. **Default:** `0`. +* Returns: {bigint} + +Reads an unsigned 64-bit integer from `buf` at the specified `offset` with +specified endian format (`readBigUInt64BE()` returns big endian, +`readBigUInt64LE()` returns little endian). + +```js +const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); + +console.log(buf.readBigUInt64BE(0)); +// Prints: 4294967295n + +console.log(buf.readBigUInt64LE(0)); +// Prints: 18446744069414584320n +``` + + ### buf.readDoubleBE(offset) ### buf.readDoubleLE(offset) + +* `value` {bigint} Number to be written to `buf`. +* `offset` {integer} Number of bytes to skip before starting to write. Must + satisfy: `0 <= offset <= buf.length - 8`. **Default:** `0`. +* Returns: {integer} `offset` plus the number of bytes written. + +Writes `value` to `buf` at the specified `offset` with specified endian +format (`writeBigInt64BE()` writes big endian, `writeBigInt64LE()` writes little +endian). + +`value` is interpreted and written as a two's complement signed integer. + +```js +const buf = Buffer.allocUnsafe(8); + +buf.writeBigInt64BE(0x0102030405060708n, 0); + +console.log(buf); +// Prints: +``` + +### buf.writeBigUInt64BE(value, offset) +### buf.writeBigUInt64LE(value, offset) + + +* `value` {bigint} Number to be written to `buf`. +* `offset` {integer} Number of bytes to skip before starting to write. Must + satisfy: `0 <= offset <= buf.length - 8`. **Default:** `0`. +* Returns: {integer} `offset` plus the number of bytes written. + +Writes `value` to `buf` at the specified `offset` with specified endian +format (`writeBigUInt64BE()` writes big endian, `writeBigUInt64LE()` writes +little endian). + +```js +const buf = Buffer.allocUnsafe(8); + +buf.writeBigUInt64LE(0xdecafafecacefaden, 0); + +console.log(buf); +// Prints: +``` + ### buf.writeDoubleBE(value, offset) ### buf.writeDoubleLE(value, offset)