Uh oh!
There was an error while loading. Please reload this page.
buffer: add swap16() and swap32() methods - #5724
Conversation
mscdex
commented
Mar 15, 2016
I think Just how common are these anyway? |
jasnell
commented
Mar 15, 2016
I can live with The |
jasnell
commented
Mar 15, 2016
Methods renamed to swap16/swap32 |
There was a problem hiding this comment.
While case differs, generally the names are the same between c++ and js. Would Swap{16,32} work?
jasnell
commented
Mar 15, 2016
@trevnorris ... ok, updated! PTAL |
jasnell
commented
Mar 15, 2016
Fishrock123
commented
Mar 15, 2016
Does this belong in core? |
There was a problem hiding this comment.
nit: wrap multi-line statements in conditionals with {}, and double indent with multi-line statements. another thing lint should be catching.
trevnorris
commented
Mar 15, 2016
@Fishrock123 Asked myself the same thing. I believe it may just fit within the parameters of what functionality belongs in core. For example: // Read in utf16be fileconstfile=fs.readFileSync(path).swap16().toString('utf16le');// Write it back to diskfs.writeFileSync(path,Buffer(file,'utf16le').swap16());Though additional input is welcome. @jasnell have a nit, but LGTM otherwise. Let's leave this open though for at least a couple days for others to respond. |
jasnell
commented
Mar 15, 2016
@Fishrock123 ... it is certainly possible to do in userland but there's a bit of a performance penalty if it's done in pure javascript... I'll post some benchmark numbers in a couple of minutes that compares the performance of swap16/swap32 to equivalent pure javascript code. I went back and forth on this one also but I landed in the same @trevnorris did... that it likely fits just inside that boundary. |
jasnell
commented
Mar 15, 2016
Benchmarks ... the |
There was a problem hiding this comment.
Maybe avoid using apply inside the bench start/end?
In buffer-iterate.js it just calls off the instance...
constname=conf.method;//...for(i=0;i<n;i+=1)method[name](buf);jasnell
commented
Mar 15, 2016
@trevnorris@williamkapke ... nits addressed. I also updated the implementation such that if Buffer length is below a certain threshold, a pure javascript version of the swap will be used rather than dropping down to the native layer. Based on the benchmarks, when the Buffer is below a certain size, it's far more efficient to swap in js. We may be able to further tweak the threshold but the current limits appear to be within the margin of error. |
There was a problem hiding this comment.
you already have len above... you might as well use it here too! :D
(Same for swap32)
There was a problem hiding this comment.
doh! missed that one. good catch :-)
williamkapke
commented
Mar 16, 2016
If we're doing this, what about (also) including a more generic I think it makes the JS side cleaner... Buffer.prototype.swap=functionswap(a,b){varx=this[a];this[a]=this[b];this[b]=x;returnthis;};Buffer.prototype.swap32=functionswap32(){for(vari=0;i<buf.length;i+=2){this.swap(i++,i+1);this.swap(i++,i+1);}returnthis;};Buffer.prototype.swap16=functionswap16(){for(vari=0;i<buf.length;i++){this.swap(i,++i);}returnthis;};constbuf=Buffer([0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8]);console.log(buf.swap(1,2));//orconsole.log(buf.swap16());//orconsole.log(buf.swap32()); |
jasnell
commented
Mar 16, 2016
Having a swap function makes sense but I wouldn't expose it as part of the Buffer API. Nits addressed! |
williamkapke
commented
Mar 16, 2016
heh- that's how I originally wrote it and then decided to put swap on the prototype ;) LGTM! |
There was a problem hiding this comment.
mind throwing these (the for loop) in their own function? when profiling it's easier to look for execution of a named function that only contains the code actually being profiled.
74769f0 to
26b4ffdComparejasnell
commented
Mar 17, 2016
@trevnorris ... done! also squashed the commits and rebased to pick up the buffer api changes also |
ofrobots
commented
Mar 22, 2016
What are the semantics when the size of the buffer is not a multiple of 2 / 4? EDIT: found the answer by looking at the test-case. |
jasnell
commented
Mar 22, 2016
It's also covered in the documentation addition. A |
| binding.setupBufferJS(Buffer.prototype, bindingObj); | ||
| const swap16n = Buffer.prototype.swap16; | ||
| const swap32n = Buffer.prototype.swap32; |
There was a problem hiding this comment.
Why are we doing this instead of attaching the native implementation to binding.swap*()?
There was a problem hiding this comment.
Just an artifact of how it was originally written. You're right, attaching directly to binding.swap*() is better.
trevnorris
commented
Mar 22, 2016
Nice tests. Left two comments. Other than that LGTM. |
jasnell
commented
Mar 22, 2016
@trevnorris .. thanks .. updated to address those nits! |
trevnorris
commented
Mar 23, 2016
@jasnell Thanks much. LGTM |
| // dropping down to the native code is faster. | ||
| const len = this.length; | ||
| if (len % 2 !== 0) | ||
| throw new RangeError('Buffer length must be a multiple of 16-bits'); |
There was a problem hiding this comment.
Incredible nitpicking, but nonetheless I would opt for one of these:
Buffer size must be a multiple of 16 bits
or:
Buffer length must be a multiple of 2
I hope you understand the nuance difference I'm getting at.
There was a problem hiding this comment.
Will change to Buffer size must be a multiple of 16 bits when I land.
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>
jasnell
commented
Mar 23, 2016
Landed in 7d73e60. Thanks all! |
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>
Notable changes: * buffer: * make byteLength work with ArrayBuffer & DataView (Jackson Tian) [#5255](#5255) * backport --zero-fill-buffers command line option (James M Snell) [#5744](#5744) * backport new buffer constructor APIs (James M Snell) [#5763](#5763) * add swap16() and swap32() methods (James M Snell) [#5724](#5724) * fs: add the fs.mkdtemp() function. (Florian MARGAINE) [#5333](#5333) * net: emit host in lookup event (HUANG Wei) [#5598](#5598) * node: --no-browser-globals configure flag (Fedor Indutny) [#5853](#5853) * npm: Upgrade to v3.8.3. (Forrest L Norvell) * repl: support standalone blocks (Prince J Wesley) [#5581](#5581) * src: override v8 thread defaults using cli options (Tom Gallacher) [#4344](#4344)
Notable changes: * buffer: * make byteLength work with ArrayBuffer & DataView (Jackson Tian) [#5255](#5255) * backport --zero-fill-buffers command line option (James M Snell) [#5744](#5744) * backport new buffer constructor APIs (James M Snell) [#5763](#5763) * add swap16() and swap32() methods (James M Snell) [#5724](#5724) * fs: add the fs.mkdtemp() function. (Florian MARGAINE) [#5333](#5333) * net: emit host in lookup event (HUANG Wei) [#5598](#5598) * node: --no-browser-globals configure flag (Fedor Indutny) [#5853](#5853) * npm: Upgrade to v3.8.3. Fixes a security flaw in the use of authentication tokens in HTTP requests that would allow an attacker to set up a server that could collect tokens from users of the command-line interface. Authentication tokens have previously been sent with every request made by the CLI for logged-in users, regardless of the destination of the request. This update fixes this by only including those tokens for requests made against the registry or registries used for the current install. (Forrest L Norvell) [npm#6](npm#6) * repl: support standalone blocks (Prince J Wesley) [#5581](#5581) * src: override v8 thread defaults using cli options (Tom Gallacher) [#4344](#4344)
Notable changes: * buffer: * make byteLength work with ArrayBuffer & DataView (Jackson Tian) [#5255](#5255) * backport --zero-fill-buffers command line option (James M Snell) [#5744](#5744) * backport new buffer constructor APIs (James M Snell) [#5763](#5763) * add swap16() and swap32() methods (James M Snell) [#5724](#5724) * fs: add the fs.mkdtemp() function. (Florian MARGAINE) [#5333](#5333) * net: emit host in lookup event (HUANG Wei) [#5598](#5598) * node: --no-browser-globals configure flag (Fedor Indutny) [#5853](#5853) * npm: Upgrade to v3.8.3. Fixes a security flaw in the use of authentication tokens in HTTP requests that would allow an attacker to set up a server that could collect tokens from users of the command-line interface. Authentication tokens have previously been sent with every request made by the CLI for logged-in users, regardless of the destination of the request. This update fixes this by only including those tokens for requests made against the registry or registries used for the current install. (Forrest L Norvell) [npm#6](npm#6) * repl: support standalone blocks (Prince J Wesley) [#5581](#5581) * src: override v8 thread defaults using cli options (Tom Gallacher) [#4344](#4344)
Notable changes: * buffer: * make byteLength work with ArrayBuffer & DataView (Jackson Tian) [#5255](#5255) * backport --zero-fill-buffers command line option (James M Snell) [#5744](#5744) * backport new buffer constructor APIs (James M Snell) [#5763](#5763) * add swap16() and swap32() methods (James M Snell) [#5724](#5724) * fs: add the fs.mkdtemp() function. (Florian MARGAINE) [#5333](#5333) * net: emit host in lookup event (HUANG Wei) [#5598](#5598) * node: --no-browser-globals configure flag (Fedor Indutny) [#5853](#5853) * npm: Upgrade to v3.8.3. Fixes a security flaw in the use of authentication tokens in HTTP requests that would allow an attacker to set up a server that could collect tokens from users of the command-line interface. Authentication tokens have previously been sent with every request made by the CLI for logged-in users, regardless of the destination of the request. This update fixes this by only including those tokens for requests made against the registry or registries used for the current install. (Forrest L Norvell) [npm#6](npm#6) * repl: support standalone blocks (Prince J Wesley) [#5581](#5581) * src: override v8 thread defaults using cli options (Tom Gallacher) [#4344](#4344) PR-URL: #5970
Pull Request check-list
make -j8 test(UNIX) orvcbuild test nosign(Windows) pass withthis change (including linting)?
test (or a benchmark) included?
existing APIs, or introduces new ones)?
Affected core subsystem(s)
buffer
Description of change
Adds
Buffer.prototype.swapShort()Buffer.prototype.swap16() andBuffer.prototype.swapLong()Buffer.prototype.swap32() methods thatmutate the Buffer instance in-place by swapping the 16-bit and 32-bit
byte-order.
Example:
Was looking at a number of use cases recently around reading in UTF16BE data and converting that to UTF8 and realized that we really didn't expose an efficient mechanism for doing a byte-swap in Buffer. This seemed like a useful API addition.
/cc @trevnorris@srl295