buffer: implement iterable
interface
This makes possible to use `for..of` loop with buffers. Also related `keys`, `values` and `entries` methods are added for feature parity with `Uint8Array`. PR-URL: https://github.com/iojs/io.js/pull/525 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
3cbb5cdfdb
commit
45d8d9f826
63
benchmark/buffers/buffer-iterate.js
Normal file
63
benchmark/buffers/buffer-iterate.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
var SlowBuffer = require('buffer').SlowBuffer;
|
||||||
|
var common = require('../common.js');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var bench = common.createBenchmark(main, {
|
||||||
|
size: [16, 512, 1024, 4096, 16386],
|
||||||
|
type: ['fast', 'slow'],
|
||||||
|
method: ['for', 'forOf', 'iterator'],
|
||||||
|
n: [1e3]
|
||||||
|
});
|
||||||
|
|
||||||
|
var methods = {
|
||||||
|
'for': benchFor,
|
||||||
|
'forOf': benchForOf,
|
||||||
|
'iterator': benchIterator
|
||||||
|
};
|
||||||
|
|
||||||
|
function main(conf) {
|
||||||
|
var len = +conf.size;
|
||||||
|
var clazz = conf.type === 'fast' ? Buffer : SlowBuffer;
|
||||||
|
var buffer = new clazz(len);
|
||||||
|
buffer.fill(0);
|
||||||
|
|
||||||
|
methods[conf.method](buffer, conf.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function benchFor(buffer, n) {
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (var k = 0; k < n; k++)
|
||||||
|
for (var i = 0; i < buffer.length; i++)
|
||||||
|
assert(buffer[i] === 0);
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
function benchForOf(buffer, n) {
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (var k = 0; k < n; k++)
|
||||||
|
for (var b of buffer)
|
||||||
|
assert(b === 0);
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
function benchIterator(buffer, n) {
|
||||||
|
bench.start();
|
||||||
|
|
||||||
|
for (var k = 0; k < n; k++) {
|
||||||
|
var iter = buffer[Symbol.iterator]();
|
||||||
|
var cur = iter.next();
|
||||||
|
|
||||||
|
while (!cur.done) {
|
||||||
|
assert(cur.value === 0);
|
||||||
|
cur = iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.end(n);
|
||||||
|
}
|
@ -797,6 +797,19 @@ buffer.
|
|||||||
var b = new Buffer(50);
|
var b = new Buffer(50);
|
||||||
b.fill("h");
|
b.fill("h");
|
||||||
|
|
||||||
|
### buffer.values()
|
||||||
|
|
||||||
|
Creates iterator for buffer values (bytes). This function is called automatically
|
||||||
|
when `buffer` is used in a `for..of` statement.
|
||||||
|
|
||||||
|
### buffer.keys()
|
||||||
|
|
||||||
|
Creates iterator for buffer keys (indices).
|
||||||
|
|
||||||
|
### buffer.entries()
|
||||||
|
|
||||||
|
Creates iterator for `[index, byte]` arrays.
|
||||||
|
|
||||||
## buffer.INSPECT_MAX_BYTES
|
## buffer.INSPECT_MAX_BYTES
|
||||||
|
|
||||||
* Number, Default: 50
|
* Number, Default: 50
|
||||||
@ -807,6 +820,22 @@ be overridden by user modules.
|
|||||||
Note that this is a property on the buffer module returned by
|
Note that this is a property on the buffer module returned by
|
||||||
`require('buffer')`, not on the Buffer global, or a buffer instance.
|
`require('buffer')`, not on the Buffer global, or a buffer instance.
|
||||||
|
|
||||||
|
## ES6 iteration
|
||||||
|
|
||||||
|
Buffers can be iterated over using `for..of` syntax:
|
||||||
|
|
||||||
|
var buf = new Buffer([1, 2, 3]);
|
||||||
|
|
||||||
|
for (var b of buf)
|
||||||
|
console.log(b)
|
||||||
|
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
|
||||||
|
Additionally, `buffer.values()`, `buffer.keys()` and `buffer.entries()`
|
||||||
|
methods can be used to create iterators.
|
||||||
|
|
||||||
## Class: SlowBuffer
|
## Class: SlowBuffer
|
||||||
|
|
||||||
Returns an un-pooled `Buffer`.
|
Returns an un-pooled `Buffer`.
|
||||||
|
@ -930,3 +930,80 @@ Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
|
|||||||
internal.writeDoubleBE(this, val, offset);
|
internal.writeDoubleBE(this, val, offset);
|
||||||
return offset + 8;
|
return offset + 8;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ES6 iterator
|
||||||
|
|
||||||
|
var ITERATOR_KIND_KEYS = 1;
|
||||||
|
var ITERATOR_KIND_ENTRIES = 3;
|
||||||
|
|
||||||
|
function BufferIteratorResult(value, done) {
|
||||||
|
this.value = value;
|
||||||
|
this.done = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultCache = new Array(256);
|
||||||
|
|
||||||
|
for (var i = 0; i < 256; i++)
|
||||||
|
resultCache[i] = Object.freeze(new BufferIteratorResult(i, false));
|
||||||
|
|
||||||
|
var finalResult = Object.freeze(new BufferIteratorResult(undefined, true));
|
||||||
|
|
||||||
|
function BufferIterator(buffer, kind) {
|
||||||
|
this._buffer = buffer;
|
||||||
|
this._kind = kind;
|
||||||
|
this._index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferIterator.prototype.next = function() {
|
||||||
|
var buffer = this._buffer;
|
||||||
|
var kind = this._kind;
|
||||||
|
var index = this._index;
|
||||||
|
|
||||||
|
if (index >= buffer.length)
|
||||||
|
return finalResult;
|
||||||
|
|
||||||
|
this._index++;
|
||||||
|
|
||||||
|
if (kind === ITERATOR_KIND_ENTRIES)
|
||||||
|
return new BufferIteratorResult([index, buffer[index]], false);
|
||||||
|
|
||||||
|
return new BufferIteratorResult(index, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
function BufferValueIterator(buffer) {
|
||||||
|
BufferIterator.call(this, buffer, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferValueIterator.prototype.next = function() {
|
||||||
|
var buffer = this._buffer;
|
||||||
|
var index = this._index;
|
||||||
|
|
||||||
|
if (index >= buffer.length)
|
||||||
|
return finalResult;
|
||||||
|
|
||||||
|
this._index++;
|
||||||
|
|
||||||
|
return resultCache[buffer[index]];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BufferIterator.prototype[Symbol.iterator] = function() {
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
BufferValueIterator.prototype[Symbol.iterator] =
|
||||||
|
BufferIterator.prototype[Symbol.iterator];
|
||||||
|
|
||||||
|
Buffer.prototype.keys = function() {
|
||||||
|
return new BufferIterator(this, ITERATOR_KIND_KEYS);
|
||||||
|
};
|
||||||
|
|
||||||
|
Buffer.prototype.entries = function() {
|
||||||
|
return new BufferIterator(this, ITERATOR_KIND_ENTRIES);
|
||||||
|
};
|
||||||
|
|
||||||
|
Buffer.prototype.values = function() {
|
||||||
|
return new BufferValueIterator(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Buffer.prototype[Symbol.iterator] = Buffer.prototype.values;
|
||||||
|
61
test/parallel/test-buffer-iterator.js
Normal file
61
test/parallel/test-buffer-iterator.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
var common = require('../common');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var buffer = new Buffer([1, 2, 3, 4, 5]);
|
||||||
|
var arr;
|
||||||
|
var b;
|
||||||
|
|
||||||
|
// buffers should be iterable
|
||||||
|
|
||||||
|
arr = [];
|
||||||
|
|
||||||
|
for (b of buffer)
|
||||||
|
arr.push(b);
|
||||||
|
|
||||||
|
assert.deepEqual(arr, [1, 2, 3, 4, 5]);
|
||||||
|
|
||||||
|
|
||||||
|
// buffer iterators should be iterable
|
||||||
|
|
||||||
|
arr = [];
|
||||||
|
|
||||||
|
for (b of buffer[Symbol.iterator]())
|
||||||
|
arr.push(b);
|
||||||
|
|
||||||
|
assert.deepEqual(arr, [1, 2, 3, 4, 5]);
|
||||||
|
|
||||||
|
|
||||||
|
// buffer#values() should return iterator for values
|
||||||
|
|
||||||
|
arr = [];
|
||||||
|
|
||||||
|
for (b of buffer.values())
|
||||||
|
arr.push(b);
|
||||||
|
|
||||||
|
assert.deepEqual(arr, [1, 2, 3, 4, 5]);
|
||||||
|
|
||||||
|
|
||||||
|
// buffer#keys() should return iterator for keys
|
||||||
|
|
||||||
|
arr = [];
|
||||||
|
|
||||||
|
for (b of buffer.keys())
|
||||||
|
arr.push(b);
|
||||||
|
|
||||||
|
assert.deepEqual(arr, [0, 1, 2, 3, 4]);
|
||||||
|
|
||||||
|
|
||||||
|
// buffer#entries() should return iterator for entries
|
||||||
|
|
||||||
|
arr = [];
|
||||||
|
|
||||||
|
for (var b of buffer.entries())
|
||||||
|
arr.push(b);
|
||||||
|
|
||||||
|
assert.deepEqual(arr, [
|
||||||
|
[0, 1],
|
||||||
|
[1, 2],
|
||||||
|
[2, 3],
|
||||||
|
[3, 4],
|
||||||
|
[4, 5]
|
||||||
|
]);
|
Loading…
x
Reference in New Issue
Block a user