Files

Return to Package Diff Home.
Brought to you by Intrinsic.

Package Diff: concat-stream @ 1.2.1 .. 1.3.0

index.js

@@ -1,52 +1,104 @@
-var stream = require('stream')
-var bops = require('bops')
-var util = require('util')
-
-function ConcatStream(cb) {
- stream.Stream.call(this)
- this.writable = true
- if (cb) this.cb = cb
- this.body = []
- this.on('error', function(err) {
- // no-op
- })
-}
+var Writable = require('stream').Writable
+var inherits = require('inherits')
+var TA = require('typedarray')
+var U8 = typeof Uint8Array !== 'undefined' ? Uint8Array : TA.Uint8Array
+
+function ConcatStream(opts, cb) {
+ if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb)
+
+ if (typeof opts === 'function') {
+ cb = opts
+ opts = {}
+ }
+ if (!opts) opts = {}
+
+ var encoding = String(opts.encoding || 'buffer').toLowerCase()
+ if (encoding === 'u8' || encoding === 'uint8') {
+ encoding = 'uint8array'
+ }
+ Writable.call(this, { objectMode: true })
-util.inherits(ConcatStream, stream.Stream)
+ this.encoding = encoding
-ConcatStream.prototype.write = function(chunk) {
- this.emit('data', chunk)
- this.body.push(chunk)
+ if (cb) this.on('finish', function () { cb(this.getBody()) })
+ this.body = []
}
-ConcatStream.prototype.destroy = function() {}
-
-ConcatStream.prototype.arrayConcat = function(arrs) {
- if (arrs.length === 0) return []
- if (arrs.length === 1) return arrs[0]
- return arrs.reduce(function (a, b) { return a.concat(b) })
-}
+module.exports = ConcatStream
+inherits(ConcatStream, Writable)
-ConcatStream.prototype.isArray = function(arr) {
- return Object.prototype.toString.call(arr) == '[object Array]'
+ConcatStream.prototype._write = function(chunk, enc, next) {
+ this.body.push(chunk)
+ next()
}
ConcatStream.prototype.getBody = function () {
- if (this.body.length === 0) return bops.from(0)
- if (typeof(this.body[0]) === "string") return this.body.join('')
- if (this.isArray(this.body[0])) return this.arrayConcat(this.body)
- if (bops.is(this.body[0])) return bops.join(this.body)
+ if (this.encoding === 'array') return arrayConcat(this.body)
+ if (this.encoding === 'string') return stringConcat(this.body)
+ if (this.encoding === 'buffer') return bufferConcat(this.body)
+ if (this.encoding === 'uint8array') return u8Concat(this.body)
return this.body
}
-ConcatStream.prototype.end = function(chunk) {
- if (chunk) this.write(chunk)
- this.emit('end')
- if (this.cb) this.cb(this.getBody())
+var isArray = Array.isArray || function (arr) {
+ return Object.prototype.toString.call(arr) == '[object Array]'
}
-module.exports = function(cb) {
- return new ConcatStream(cb)
+function isArrayish (arr) {
+ return /Array\]$/.test(Object.prototype.toString.call(arr))
}
-module.exports.ConcatStream = ConcatStream
+function stringConcat (parts) {
+ var strings = []
+ for (var i = 0; i < parts.length; i++) {
+ var p = parts[i]
+ if (typeof p === 'string') {
+ strings.push(p)
+ } else if (Buffer.isBuffer(p)) {
+ strings.push(p.toString('utf8'))
+ } else {
+ strings.push(Buffer(p).toString('utf8'))
+ }
+ }
+ return strings.join('')
+}
+
+function bufferConcat (parts) {
+ var bufs = []
+ for (var i = 0; i < parts.length; i++) {
+ var p = parts[i]
+ if (Buffer.isBuffer(p)) {
+ bufs.push(p)
+ } else if (typeof p === 'string' || isArrayish(p)
+ || (p && typeof p.subarray === 'function')) {
+ bufs.push(Buffer(p))
+ } else bufs.push(Buffer(String(p)))
+ }
+ return Buffer.concat(bufs)
+}
+
+function arrayConcat (parts) {
+ var res = []
+ for (var i = 0; i < parts.length; i++) {
+ res.push.apply(res, parts[i])
+ }
+ return res
+}
+
+function u8Concat (parts) {
+ var len = 0
+ for (var i = 0; i < parts.length; i++) {
+ if (typeof parts[i] === 'string') {
+ parts[i] = Buffer(parts[i])
+ }
+ len += parts[i].length
+ }
+ var u8 = new U8(len)
+ for (var i = 0, offset = 0; i < parts.length; i++) {
+ var part = parts[i]
+ for (var j = 0; j < part.length; j++) {
+ u8[offset++] = part[j]
+ }
+ }
+ return u8
+}

package.json

@@ -7,7 +7,7 @@
"util",
"utility"
],
- "version": "1.2.1",
+ "version": "1.3.0",
"author": "Max Ogden <max@maxogden.com>",
"repository": {
"type": "git",
@@ -21,10 +21,30 @@
],
"main": "index.js",
"scripts": {
- "test": "node test.js"
+ "test": "tape test/*.js test/server/*.js"
},
"license": "MIT",
"dependencies": {
- "bops": "0.0.6"
+ "inherits": "~2.0.1",
+ "typedarray": "~0.0.5"
+ },
+ "devDependencies": {
+ "tape": "~2.3.2"
+ },
+ "testling": {
+ "files": "test/*.js",
+ "browsers": [
+ "ie/8..latest",
+ "firefox/17..latest",
+ "firefox/nightly",
+ "chrome/22..latest",
+ "chrome/canary",
+ "opera/12..latest",
+ "opera/next",
+ "safari/5.1..latest",
+ "ipad/6.0..latest",
+ "iphone/6.0..latest",
+ "android-browser/4.2..latest"
+ ]
}
}

readme.md

@@ -1,10 +1,12 @@
# concat-stream
-```sh
-$ npm install concat-stream
-```
+Writable stream that concatenates strings or binary data and calls a callback with the result. Not a transform stream -- more of a stream sink.
+
+[![NPM](https://nodei.co/npm/concat-stream.png)](https://nodei.co/npm/concat-stream/)
+
+[![browser support](https://ci.testling.com/maxogden/node-concat-stream.png)](https://ci.testling.com/maxogden/node-concat-stream)
-then
+### examples
```js
var concat = require('concat-stream')
@@ -19,7 +21,7 @@
works with arrays too!
```js
-var write = concat(function(data) {})
+var write = concat({ encoding: 'array' }, function(data) {})
write.write([1,2,3])
write.write([4,5,6])
write.end()
@@ -36,4 +38,36 @@
// data will be a buffer that toString()s to 'hello world' in the above callback
```
+or if you want a Uint8Array, you can have those too!
+
+```js
+var write = concat({ encoding: 'u8' }, function(data) {})
+var a = new Uint8Array(3)
+a[0] = 97; a[1] = 98; a[2] = 99
+write.write(a)
+write.write('!')
+write.end(Buffer('!!1'))
+```
+
+# methods
+
+```js
+var concat = require('concat-stream')
+```
+
+## var writable = concat(opts={}, cb)
+
+Return a `writable` stream that will fire `cb(data)` with all of the data that
+was written to the stream. Data can be written to `writable` as strings,
+Buffers, arrays of byte integers, and Uint8Arrays.
+
+Use `opts.encoding` to control what format `data` should be:
+
+* string - get a string
+* buffer - get back a Buffer (this is the default encoding)
+* array - get an array of byte integers
+* uint8array, u8, uint8 - get back a Uint8Array
+
+# license
+
MIT LICENSE
\ No newline at end of file

test/array.js

@@ -0,0 +1,12 @@
+var concat = require('../')
+var test = require('tape')
+
+test('array stream', function (t) {
+ t.plan(1)
+ var arrays = concat({ encoding: 'array' }, function(out) {
+ t.deepEqual(out, [1,2,3,4,5,6])
+ })
+ arrays.write([1,2,3])
+ arrays.write([4,5,6])
+ arrays.end()
+})

test/buffer.js

@@ -0,0 +1,31 @@
+var concat = require('../')
+var test = require('tape')
+var TA = require('typedarray')
+var U8 = typeof Uint8Array !== 'undefined' ? Uint8Array : TA.Uint8Array
+
+test('buffer stream', function (t) {
+ t.plan(2)
+ var buffers = concat(function(out) {
+ t.ok(Buffer.isBuffer(out))
+ t.equal(out.toString('utf8'), 'pizza Array is not a stringy cat')
+ })
+ buffers.write(new Buffer('pizza Array is not a ', 'utf8'))
+ buffers.write(new Buffer('stringy cat'))
+ buffers.end()
+})
+
+test('buffer mixed writes', function (t) {
+ t.plan(2)
+ var buffers = concat(function(out) {
+ t.ok(Buffer.isBuffer(out))
+ t.equal(out.toString('utf8'), 'pizza Array is not a stringy cat555')
+ })
+ buffers.write(new Buffer('pizza'))
+ buffers.write(' Array is not a ')
+ buffers.write([ 115, 116, 114, 105, 110, 103, 121 ])
+ var u8 = new U8(4)
+ u8[0] = 32; u8[1] = 99; u8[2] = 97; u8[3] = 116
+ buffers.write(u8)
+ buffers.write(555)
+ buffers.end()
+})

test/nothing.js

@@ -0,0 +1,9 @@
+var concat = require('../')
+var test = require('tape')
+
+test('no callback stream', function (t) {
+ var stream = concat()
+ stream.write('space')
+ stream.end(' cats')
+ t.end()
+})

test/server/ls.js

@@ -0,0 +1,16 @@
+var concat = require('../../')
+var spawn = require('child_process').spawn
+var exec = require('child_process').exec
+var test = require('tape')
+
+test('ls command', function (t) {
+ t.plan(1)
+ var cmd = spawn('ls', [ __dirname ])
+ cmd.stdout.pipe(
+ concat(function(out) {
+ exec('ls ' + __dirname, function (err, body) {
+ t.equal(out.toString('utf8'), body.toString('utf8'))
+ })
+ })
+ )
+})

test/string.js

@@ -0,0 +1,50 @@
+var concat = require('../')
+var test = require('tape')
+var TA = require('typedarray')
+var U8 = typeof Uint8Array !== 'undefined' ? Uint8Array : TA.Uint8Array
+
+test('string -> buffer stream', function (t) {
+ t.plan(2)
+ var strings = concat(function(out) {
+ t.ok(Buffer.isBuffer(out))
+ t.equal(out.toString('utf8'), 'nacho dogs')
+ })
+ strings.write("nacho ")
+ strings.write("dogs")
+ strings.end()
+})
+
+test('string stream', function (t) {
+ t.plan(2)
+ var strings = concat({ encoding: 'string' }, function(out) {
+ t.equal(typeof out, 'string')
+ t.equal(out, 'nacho dogs')
+ })
+ strings.write("nacho ")
+ strings.write("dogs")
+ strings.end()
+})
+
+test('end chunk', function (t) {
+ t.plan(1)
+ var endchunk = concat({ encoding: 'string' }, function(out) {
+ t.equal(out, 'this is the end')
+ })
+ endchunk.write("this ")
+ endchunk.write("is the ")
+ endchunk.end("end")
+})
+
+test('string from mixed write encodings', function (t) {
+ t.plan(2)
+ var strings = concat({ encoding: 'string' }, function(out) {
+ t.equal(typeof out, 'string')
+ t.equal(out, 'nacho dogs')
+ })
+ strings.write('na')
+ strings.write(Buffer('cho'))
+ strings.write([ 32, 100 ])
+ var u8 = new U8(3)
+ u8[0] = 111; u8[1] = 103; u8[2] = 115;
+ strings.end(u8)
+})

test/typedarray.js

@@ -0,0 +1,33 @@
+var concat = require('../')
+var test = require('tape')
+var TA = require('typedarray')
+var U8 = typeof Uint8Array !== 'undefined' ? Uint8Array : TA.Uint8Array
+
+test('typed array stream', function (t) {
+ t.plan(2)
+ var a = new U8(5)
+ a[0] = 97; a[1] = 98; a[2] = 99; a[3] = 100; a[4] = 101;
+ var b = new U8(3)
+ b[0] = 32; b[1] = 102; b[2] = 103;
+ var c = new U8(4)
+ c[0] = 32; c[1] = 120; c[2] = 121; c[3] = 122;
+
+ var arrays = concat({ encoding: 'Uint8Array' }, function(out) {
+ t.equal(typeof out.subarray, 'function')
+ t.deepEqual(Buffer(out).toString('utf8'), 'abcde fg xyz')
+ })
+ arrays.write(a)
+ arrays.write(b)
+ arrays.end(c)
+})
+
+test('typed array from strings, buffers, and arrays', function (t) {
+ t.plan(2)
+ var arrays = concat({ encoding: 'Uint8Array' }, function(out) {
+ t.equal(typeof out.subarray, 'function')
+ t.deepEqual(Buffer(out).toString('utf8'), 'abcde fg xyz')
+ })
+ arrays.write('abcde')
+ arrays.write(Buffer(' fg '))
+ arrays.end([ 120, 121, 122 ])
+})

test.js

@@ -1,52 +0,0 @@
-var spawn = require('child_process').spawn
-var concat = require('./')
-
-// real world example
-var cmd = spawn('ls')
-cmd.stdout.pipe(
- concat(function(out) {
- console.log('`ls`', out.toString())
- })
-)
-
-// array stream
-var arrays = concat(function(out) {
- console.log('arrays', out)
-})
-arrays.write([1,2,3])
-arrays.write([4,5,6])
-arrays.end()
-
-// buffer stream
-var buffers = concat(function(out) {
- console.log('buffers', out.toString())
-})
-buffers.write(new Buffer('pizza Array is not a ', 'utf8'))
-buffers.write(new Buffer('stringy cat'))
-buffers.end()
-
-// string stream
-var strings = concat(function(out) {
- console.log('strings', out)
-})
-strings.write("nacho ")
-strings.write("dogs")
-strings.end()
-
-// reemit
-var emitter = concat()
-var receiver = concat(function (out) {
- console.log('strings', out)
-})
-emitter.pipe(receiver)
-emitter.write('pizza')
-emitter.write(' is dope')
-emitter.end()
-
-// chunk passed to end
-var endchunk = concat(function(out) {
- console.log('strings', out)
-})
-endchunk.write("this ")
-endchunk.write("is the ")
-endchunk.end("end")