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:
Родитель
3cbb5cdfdb
Коммит
45d8d9f826
|
@ -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);
|
||||
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
|
||||
|
||||
* Number, Default: 50
|
||||
|
@ -807,6 +820,22 @@ be overridden by user modules.
|
|||
Note that this is a property on the buffer module returned by
|
||||
`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
|
||||
|
||||
Returns an un-pooled `Buffer`.
|
||||
|
|
|
@ -930,3 +930,80 @@ Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
|
|||
internal.writeDoubleBE(this, val, offset);
|
||||
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;
|
||||
|
|
|
@ -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]
|
||||
]);
|
Загрузка…
Ссылка в новой задаче