1 var Writable = require('readable-stream').Writable
2 var inherits = require('inherits')
4 if (typeof Uint8Array === 'undefined') {
5 var U8 = require('typedarray').Uint8Array
10 function ConcatStream(opts, cb) {
11 if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb)
13 if (typeof opts === 'function') {
19 var encoding = opts.encoding
20 var shouldInferEncoding = false
23 shouldInferEncoding = true
25 encoding = String(encoding).toLowerCase()
26 if (encoding === 'u8' || encoding === 'uint8') {
27 encoding = 'uint8array'
31 Writable.call(this, { objectMode: true })
33 this.encoding = encoding
34 this.shouldInferEncoding = shouldInferEncoding
36 if (cb) this.on('finish', function () { cb(this.getBody()) })
40 module.exports = ConcatStream
41 inherits(ConcatStream, Writable)
43 ConcatStream.prototype._write = function(chunk, enc, next) {
48 ConcatStream.prototype.inferEncoding = function (buff) {
49 var firstBuffer = buff === undefined ? this.body[0] : buff;
50 if (Buffer.isBuffer(firstBuffer)) return 'buffer'
51 if (typeof Uint8Array !== 'undefined' && firstBuffer instanceof Uint8Array) return 'uint8array'
52 if (Array.isArray(firstBuffer)) return 'array'
53 if (typeof firstBuffer === 'string') return 'string'
54 if (Object.prototype.toString.call(firstBuffer) === "[object Object]") return 'object'
58 ConcatStream.prototype.getBody = function () {
59 if (!this.encoding && this.body.length === 0) return []
60 if (this.shouldInferEncoding) this.encoding = this.inferEncoding()
61 if (this.encoding === 'array') return arrayConcat(this.body)
62 if (this.encoding === 'string') return stringConcat(this.body)
63 if (this.encoding === 'buffer') return bufferConcat(this.body)
64 if (this.encoding === 'uint8array') return u8Concat(this.body)
68 var isArray = Array.isArray || function (arr) {
69 return Object.prototype.toString.call(arr) == '[object Array]'
72 function isArrayish (arr) {
73 return /Array\]$/.test(Object.prototype.toString.call(arr))
76 function isBufferish (p) {
77 return typeof p === 'string' || isArrayish(p) || (p && typeof p.subarray === 'function')
80 function stringConcat (parts) {
82 var needsToString = false
83 for (var i = 0; i < parts.length; i++) {
85 if (typeof p === 'string') {
87 } else if (Buffer.isBuffer(p)) {
89 } else if (isBufferish(p)) {
90 strings.push(new Buffer(p))
92 strings.push(new Buffer(String(p)))
95 if (Buffer.isBuffer(parts[0])) {
96 strings = Buffer.concat(strings)
97 strings = strings.toString('utf8')
99 strings = strings.join('')
104 function bufferConcat (parts) {
106 for (var i = 0; i < parts.length; i++) {
108 if (Buffer.isBuffer(p)) {
110 } else if (isBufferish(p)) {
111 bufs.push(new Buffer(p))
113 bufs.push(new Buffer(String(p)))
116 return Buffer.concat(bufs)
119 function arrayConcat (parts) {
121 for (var i = 0; i < parts.length; i++) {
122 res.push.apply(res, parts[i])
127 function u8Concat (parts) {
129 for (var i = 0; i < parts.length; i++) {
130 if (typeof parts[i] === 'string') {
131 parts[i] = new Buffer(parts[i])
133 len += parts[i].length
136 for (var i = 0, offset = 0; i < parts.length; i++) {
138 for (var j = 0; j < part.length; j++) {
139 u8[offset++] = part[j]