-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
buffer: add swap16() and swap32() methods
Adds Buffer.prototype.swap16() and Buffer.prototype.swap32() methods that mutate the Buffer instance in-place by swapping the 16-bit and 32-bit byte-order. Example: ```js const buf = Buffer([0x1, 0x2, 0x3, 0x4]); buf.swap16(); console.log(buf); // prints Buffer(0x2, 0x1, 0x4, 0x3); buf.swap32(); console.log(buf); // prints Buffer(0x3, 0x4, 0x1, 0x2); ``` PR-URL: #5724 Reviewed-By: Trevor Norris <trev.norris@gmail.com>
- Loading branch information
Showing
5 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
'use strict'; | ||
|
||
const common = require('../common.js'); | ||
|
||
const bench = common.createBenchmark(main, { | ||
method: ['swap16', 'swap32', 'htons', 'htonl'], | ||
len: [4, 64, 512, 768, 1024, 1536, 2056, 4096, 8192], | ||
n: [1e6] | ||
}); | ||
|
||
// The htons and htonl methods below are used to benchmark the | ||
// performance difference between doing the byteswap in pure | ||
// javascript regardless of Buffer size as opposed to dropping | ||
// down to the native layer for larger Buffer sizes. | ||
|
||
Buffer.prototype.htons = function htons() { | ||
if (this.length % 2 !== 0) | ||
throw new RangeError(); | ||
for (var i = 0, n = 0; i < this.length; i += 2) { | ||
n = this[i]; | ||
this[i] = this[i + 1]; | ||
this[i + 1] = n; | ||
} | ||
return this; | ||
}; | ||
|
||
Buffer.prototype.htonl = function htonl() { | ||
if (this.length % 2 !== 0) | ||
throw new RangeError(); | ||
for (var i = 0, n = 0; i < this.length; i += 4) { | ||
n = this[i]; | ||
this[i] = this[i + 3]; | ||
this[i + 3] = n; | ||
n = this[i + 1]; | ||
this[i + 1] = this[i + 2]; | ||
this[i + 2] = n; | ||
} | ||
return this; | ||
}; | ||
|
||
function createBuffer(len) { | ||
const buf = Buffer.allocUnsafe(len); | ||
for (var i = 1; i <= len; i++) | ||
buf[i - 1] = i; | ||
return buf; | ||
} | ||
|
||
function bufferSwap(n, buf, method) { | ||
for (var i = 1; i <= n; i++) | ||
buf[method](); | ||
} | ||
|
||
function main(conf) { | ||
const method = conf.method; | ||
const len = conf.len | 0; | ||
const n = conf.n | 0; | ||
const buf = createBuffer(len); | ||
bench.start(); | ||
bufferSwap(n, buf, method); | ||
bench.end(n); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
'use strict'; | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
|
||
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4]); | ||
|
||
assert.strictEqual(buf, buf.swap16()); | ||
assert.deepStrictEqual(buf, Buffer.from([0x2, 0x1, 0x4, 0x3])); | ||
|
||
assert.strictEqual(buf, buf.swap32()); | ||
assert.deepStrictEqual(buf, Buffer.from([0x3, 0x4, 0x1, 0x2])); | ||
|
||
const buf_array = []; | ||
for (var i = 1; i < 33; i++) | ||
buf_array.push(i); | ||
const buf2 = Buffer.from(buf_array); | ||
buf2.swap32(); | ||
assert.deepStrictEqual(buf2, | ||
Buffer.from([0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05, 0x0c, | ||
0x0b, 0x0a, 0x09, 0x10, 0x0f, 0x0e, 0x0d, 0x14, 0x13, | ||
0x12, 0x11, 0x18, 0x17, 0x16, 0x15, 0x1c, 0x1b, 0x1a, | ||
0x19, 0x20, 0x1f, 0x1e, 0x1d])); | ||
buf2.swap16(); | ||
assert.deepStrictEqual(buf2, | ||
Buffer.from([0x03, 0x04, 0x01, 0x02, 0x07, 0x08, 0x05, 0x06, 0x0b, | ||
0x0c, 0x09, 0x0a, 0x0f, 0x10, 0x0d, 0x0e, 0x13, 0x14, | ||
0x11, 0x12, 0x17, 0x18, 0x15, 0x16, 0x1b, 0x1c, 0x19, | ||
0x1a, 0x1f, 0x20, 0x1d, 0x1e])); | ||
|
||
const buf3 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7]); | ||
buf3.slice(1, 5).swap32(); | ||
assert.deepStrictEqual(buf3, Buffer.from([0x1, 0x5, 0x4, 0x3, 0x2, 0x6, 0x7])); | ||
|
||
buf3.slice(1, 5).swap16(); | ||
assert.deepStrictEqual(buf3, Buffer.from([0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7])); | ||
|
||
// Force use of native code (Buffer size above threshold limit for js impl) | ||
const buf4 = Buffer.allocUnsafe(1024).fill([0x1, 0x2, 0x3, 0x4]); | ||
const buf5 = Buffer.allocUnsafe(1024).fill([0x2, 0x1, 0x4, 0x3]); | ||
const buf6 = Buffer.allocUnsafe(1024) | ||
.fill([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); | ||
const buf7 = Buffer.allocUnsafe(1024) | ||
.fill([0x4, 0x3, 0x2, 0x1, 0x8, 0x7, 0x6, 0x5]); | ||
|
||
buf4.swap16(); | ||
assert.deepStrictEqual(buf4, buf5); | ||
|
||
buf6.swap32(); | ||
assert.deepStrictEqual(buf6, buf7); | ||
|
||
|
||
const re16 = /Buffer size must be a multiple of 16-bits/; | ||
const re32 = /Buffer size must be a multiple of 32-bits/; | ||
|
||
assert.throws(() => Buffer.from(buf3).swap16(), re16); | ||
assert.throws(() => Buffer.alloc(1025).swap16(), re16); | ||
assert.throws(() => Buffer.from(buf3).swap32(), re32); | ||
assert.throws(() => buf3.slice(1, 3).swap32(), re32); | ||
assert.throws(() => Buffer.alloc(1025).swap32(), re32); |