diff --git a/README.md b/README.md
index 4d87866..f7044db 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@ bl.pipe(fs.createWriteStream('gibberish.txt'))
--------------------------------------------------------
-### new BufferList([ callback | buffer | buffer array ])
+### new BufferList([ callback | Buffer | Buffer array | BufferList | BufferList array | String ])
The constructor takes an optional callback, if supplied, the callback will be called with an error argument followed by a reference to the **bl** instance, when `bl.end()` is called (i.e. from a piped stream). This is a convenient method of collecting the entire contents of a stream, particularly when the stream is *chunky*, such as a network stream.
Normally, no arguments are required for the constructor, but you can initialise the list by passing in a single `Buffer` object or an array of `Buffer` object.
@@ -120,8 +120,8 @@ Get the length of the list in bytes. This is the sum of the lengths of all of th
--------------------------------------------------------
-### bl.append(buffer)
-`append(buffer)` adds an additional buffer or BufferList to the internal list.
+### bl.append(Buffer | Buffer array | BufferList | BufferList array | String)
+`append(buffer)` adds an additional buffer or BufferList to the internal list. `this` is returned so it can be chained.
--------------------------------------------------------
diff --git a/bl.js b/bl.js
index 6f27330..b3325f0 100644
--- a/bl.js
+++ b/bl.js
@@ -24,13 +24,8 @@ function BufferList (callback) {
this.on('unpipe', function (src) {
src.removeListener('error', piper)
})
- }
- else if (Buffer.isBuffer(callback))
+ } else {
this.append(callback)
- else if (Array.isArray(callback)) {
- callback.forEach(function (b) {
- Buffer.isBuffer(b) && this.append(b)
- }.bind(this))
}
DuplexStream.call(this)
@@ -49,20 +44,25 @@ BufferList.prototype._offset = function (offset) {
}
BufferList.prototype.append = function (buf) {
- var isBuffer = Buffer.isBuffer(buf) ||
- buf instanceof BufferList
-
- // coerce number arguments to strings, since Buffer(number) does
- // uninitialized memory allocation
- if (typeof buf == 'number')
- buf = buf.toString()
-
- if (buf instanceof BufferList) {
- this._bufs.push.apply(this._bufs, buf._bufs)
- this.length += buf.length
- } else {
- this._bufs.push(isBuffer ? buf : new Buffer(buf))
- this.length += buf.length
+ var i = 0
+ , newBuf
+
+ if (Array.isArray(buf)) {
+ for (; i < buf.length; i++)
+ this.append(buf[i])
+ } else if (buf instanceof BufferList) {
+ // unwrap argument into individual BufferLists
+ for (; i < buf._bufs.length; i++)
+ this.append(buf._bufs[i])
+ } else if (buf != null) {
+ // coerce number arguments to strings, since Buffer(number) does
+ // uninitialized memory allocation
+ if (typeof buf == 'number')
+ buf = buf.toString()
+
+ newBuf = Buffer.isBuffer(buf) ? buf : new Buffer(buf)
+ this._bufs.push(newBuf)
+ this.length += newBuf.length
}
return this
diff --git a/test/test.js b/test/test.js
index 2f0c6d3..c95b1ba 100644
--- a/test/test.js
+++ b/test/test.js
@@ -79,12 +79,39 @@ tape('multiple bytes from multiple buffers', function (t) {
tape('multiple bytes from multiple buffer lists', function (t) {
var bl = new BufferList()
- bl.append(new BufferList([new Buffer('abcd'), new Buffer('efg')]))
- bl.append(new BufferList([new Buffer('hi'), new Buffer('j')]))
+ bl.append(new BufferList([ new Buffer('abcd'), new Buffer('efg') ]))
+ bl.append(new BufferList([ new Buffer('hi'), new Buffer('j') ]))
t.equal(bl.length, 10)
t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij')
+
+ t.equal(bl.slice(3, 10).toString('ascii'), 'defghij')
+ t.equal(bl.slice(3, 6).toString('ascii'), 'def')
+ t.equal(bl.slice(3, 8).toString('ascii'), 'defgh')
+ t.equal(bl.slice(5, 10).toString('ascii'), 'fghij')
+
+ t.end()
+})
+
+// same data as previous test, just using nested constructors
+tape('multiple bytes from crazy nested buffer lists', function (t) {
+ var bl = new BufferList()
+
+ bl.append(new BufferList([
+ new BufferList([
+ new BufferList(new Buffer('abc'))
+ , new Buffer('d')
+ , new BufferList(new Buffer('efg'))
+ ])
+ , new BufferList([ new Buffer('hi') ])
+ , new BufferList(new Buffer('j'))
+ ]))
+
+ t.equal(bl.length, 10)
+
+ t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij')
+
t.equal(bl.slice(3, 10).toString('ascii'), 'defghij')
t.equal(bl.slice(3, 6).toString('ascii'), 'def')
t.equal(bl.slice(3, 8).toString('ascii'), 'defgh')
@@ -93,6 +120,48 @@ tape('multiple bytes from multiple buffer lists', function (t) {
t.end()
})
+tape('append accepts arrays of Buffers', function (t) {
+ var bl = new BufferList()
+ bl.append(new Buffer('abc'))
+ bl.append([ new Buffer('def') ])
+ bl.append([ new Buffer('ghi'), new Buffer('jkl') ])
+ bl.append([ new Buffer('mnop'), new Buffer('qrstu'), new Buffer('vwxyz') ])
+ t.equal(bl.length, 26)
+ t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz')
+ t.end()
+})
+
+tape('append accepts arrays of BufferLists', function (t) {
+ var bl = new BufferList()
+ bl.append(new Buffer('abc'))
+ bl.append([ new BufferList('def') ])
+ bl.append(new BufferList([ new Buffer('ghi'), new BufferList('jkl') ]))
+ bl.append([ new Buffer('mnop'), new BufferList([ new Buffer('qrstu'), new Buffer('vwxyz') ]) ])
+ t.equal(bl.length, 26)
+ t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz')
+ t.end()
+})
+
+tape('append chainable', function (t) {
+ var bl = new BufferList()
+ t.ok(bl.append(new Buffer('abcd')) === bl)
+ t.ok(bl.append([ new Buffer('abcd') ]) === bl)
+ t.ok(bl.append(new BufferList(new Buffer('abcd'))) === bl)
+ t.ok(bl.append([ new BufferList(new Buffer('abcd')) ]) === bl)
+ t.end()
+})
+
+tape('append chainable (test results)', function (t) {
+ var bl = new BufferList('abc')
+ .append([ new BufferList('def') ])
+ .append(new BufferList([ new Buffer('ghi'), new BufferList('jkl') ]))
+ .append([ new Buffer('mnop'), new BufferList([ new Buffer('qrstu'), new Buffer('vwxyz') ]) ])
+
+ t.equal(bl.length, 26)
+ t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz')
+ t.end()
+})
+
tape('consuming from multiple buffers', function (t) {
var bl = new BufferList()