pax_global_header00006660000000000000000000000064133376057500014523gustar00rootroot0000000000000052 comment=8d330f20101c9fb3a0f979e1cf3993606918d895 StringStream-1.0.0/000077500000000000000000000000001333760575000141435ustar00rootroot00000000000000StringStream-1.0.0/.gitignore000066400000000000000000000001401333760575000161260ustar00rootroot00000000000000lib-cov *.seed *.log *.csv *.dat *.out *.pid *.gz pids logs results node_modules npm-debug.logStringStream-1.0.0/.travis.yml000066400000000000000000000000641333760575000162540ustar00rootroot00000000000000language: node_js node_js: - 4 - 6 - 8 - 10 StringStream-1.0.0/LICENSE000066400000000000000000000020341333760575000151470ustar00rootroot00000000000000Copyright 2018 Michael Hart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. StringStream-1.0.0/README.md000066400000000000000000000037051333760575000154270ustar00rootroot00000000000000# Decode streams into strings without setEncoding ```js const fs = require('fs') const zlib = require('zlib') const strs = require('stringstream') const utf8Stream = fs.createReadStream('massiveLogFile.gz') .pipe(zlib.createGunzip()) .pipe(strs('utf8')) utf8Stream.on('data', str => console.log(`This will be a string: ${str}`)) ``` ## API - `strs(to, [options])` – creates a transform stream that converts the input into strings in `to` encoding (eg, `utf8`, `hex`, `base64`) - `strs(from, to, [options])` – creates a transform stream converts the input from strings in `from` encoding to strings in `to` encoding `options` can be anything compatible with the standard Node.js [`new stream.Transform([options])` constructor](https://nodejs.org/api/stream.html#stream_new_stream_transform_options) ## NB: This library was originally written before Node.js [correctly encoded base64 strings from streams](https://github.com/nodejs/node/commit/061f2075cf81017cdb40de80533ba18746743c94) Back in the day, calling `.setEncoding('base64')` on a readable stream didn't align correctly, which was one of the main reasons I wrote this library – however this hasn't been the case for a long time, so this library is now really only useful in scenarios where you don't want to call `.setEncoding()` for whatever reason. It also handles input and output text encodings: ```js // Stream from utf8 to hex to base64... Why not, ay. const hex64Stream = fs.createReadStream('myFile.txt') .pipe(strs('utf8', 'hex')) .pipe(strs('hex', 'base64')) ``` Also deals with `base64` output correctly by aligning each emitted data chunk so that there are no dangling `=` characters: ```js const stream = fs.createReadStream('myFile.jpg').pipe(strs('base64')) let base64Str = '' stream.on('data', data => base64Str += data) stream.on('end', () => { console.log('My base64 encoded file is: ' + base64Str) console.log('Original file is: ' + Buffer.from(base64Str, 'base64')) }) ``` StringStream-1.0.0/example.js000066400000000000000000000014261333760575000161370ustar00rootroot00000000000000const fs = require('fs') const zlib = require('zlib') const strs = require('stringstream') const utf8Stream = fs.createReadStream('massiveLogFile.gz') .pipe(zlib.createGunzip()) .pipe(strs('utf8')) utf8Stream.pipe(process.stdout) // Stream from utf8 to hex to base64... Why not, ay. const hex64Stream = fs.createReadStream('myFile.txt') .pipe(strs('utf8', 'hex')) .pipe(strs('hex', 'base64')) hex64Stream.pipe(process.stdout) // Deals with base64 correctly by aligning chunks const stream = fs.createReadStream('myFile.jpg').pipe(strs('base64')) let base64Str = '' stream.on('data', data => base64Str += data) stream.on('end', () => { console.log('My base64 encoded file is: ' + base64Str) console.log('Original file size: ' + Buffer.from(base64Str, 'base64').length) }) StringStream-1.0.0/package.json000066400000000000000000000005351333760575000164340ustar00rootroot00000000000000{ "name": "stringstream", "version": "1.0.0", "description": "Encode and decode streams into string streams", "repository": "mhart/StringStream", "author": "Michael Hart ", "license": "MIT", "main": "stringstream.js", "engines": { "node": ">=4.0.0" }, "scripts": { "test": "node test.js" } } StringStream-1.0.0/stringstream.js000066400000000000000000000025341333760575000172270ustar00rootroot00000000000000'use strict' const util = require('util') const Transform = require('stream').Transform module.exports = StringStream const CHAR_ALIGN = { 'hex': 2, 'base64': 4, } function StringStream(from, to, options) { if (!(this instanceof StringStream)) return new StringStream(from, to, options) Transform.call(this, options) if (typeof to !== 'string') { options = to to = from || 'utf8' from = null } this.setEncoding(to) this.fromEncoding = from this.fromBuffer = '' this.fromAlign = CHAR_ALIGN[this.fromEncoding] } util.inherits(StringStream, Transform) StringStream.prototype._transform = function(chunk, encoding, cb) { if (!this.fromEncoding) { return cb(null, chunk) } let str = '' + chunk if (!this.fromAlign) { return cb(null, Buffer.from(str, this.fromEncoding)) } this.fromBuffer += str if (this.fromBuffer.length < this.fromAlign) { return cb() } const len = this.fromBuffer.length - (this.fromBuffer.length % this.fromAlign) str = this.fromBuffer.slice(0, len) this.fromBuffer = this.fromBuffer.slice(len) cb(null, Buffer.from(str, this.fromEncoding)) } StringStream.prototype._flush = function(cb) { if (this.fromBuffer) { const str = Buffer.from(this.fromBuffer, this.fromEncoding) str && this.push(str) } cb() // Can only supply data to callback from Node.js v7.0 onwards } StringStream-1.0.0/test.js000066400000000000000000000126041333760575000154630ustar00rootroot00000000000000'use strict' /* eslint-disable no-return-assign */ const assert = require('assert') const Readable = require('stream').Readable const strs = require('.') const HIGH = new Readable().readableHighWaterMark || 16384 function assertStream(vals, streams, expected) { const readable = [new Readable({read() { vals.concat(null).forEach(c => this.push(c)) }})] let actual = '' readable.concat(streams).reduce((readable, stream) => readable.pipe(stream)).on('data', str => actual += str).on('end', () => { assert.strictEqual(actual, expected, `Failed for ${vals}: '${actual}' === '${expected}'`) console.log('ok') }) } assertStream(['a'], strs(), 'a') assertStream(['a'], strs('utf8'), 'a') assertStream(['a'], strs('hex'), '61') assertStream(['a'], strs('base64'), 'YQ==') assertStream(['aa'], strs('utf8'), 'aa') assertStream(['aa'], strs('hex'), '6161') assertStream(['aa'], strs('base64'), 'YWE=') assertStream(['aaa'], strs('base64'), 'YWFh') assertStream(['aaaa'], strs('base64'), 'YWFhYQ==') assertStream(['aaaaa'], strs('base64'), 'YWFhYWE=') assertStream(['aaaaaa'], strs('base64'), 'YWFhYWFh') assertStream(['abcb'], strs('base64', 'base64'), 'abcb') assertStream(['abc', 'b'], strs('base64', 'base64'), 'abcb') assertStream(['ab'], strs('hex', 'hex'), 'ab') assertStream(['a', 'b'], strs('hex', 'hex'), 'ab') assertStream(['a', 'b', 'ab'], strs('hex', 'hex'), 'abab') assertStream(['61'], strs('hex', 'utf8'), 'a') assertStream(['6', '1'], strs('hex', 'utf8'), 'a') assertStream(['6', '1', '6', '1'], strs('hex', 'utf8'), 'aa') assertStream(['abcbb', 'bbb'], strs('base64', 'base64'), 'abcbbbbb') assertStream(['YQ'], strs('base64', 'utf8'), 'a') assertStream(['YQ='], strs('base64', 'utf8'), 'a') assertStream(['YQ=='], strs('base64', 'utf8'), 'a') assertStream(['YWE'], strs('base64', 'utf8'), 'aa') assertStream(['YWE='], strs('base64', 'utf8'), 'aa') assertStream(['YWFh'], strs('base64', 'utf8'), 'aaa') assertStream(['YWFhYQ'], strs('base64', 'utf8'), 'aaaa') assertStream(['YWFhYQ='], strs('base64', 'utf8'), 'aaaa') assertStream(['YWFhYQ=='], strs('base64', 'utf8'), 'aaaa') assertStream(['YWFhYWE'], strs('base64', 'utf8'), 'aaaaa') assertStream(['YWFhYWE='], strs('base64', 'utf8'), 'aaaaa') assertStream(['YWFhYWFh'], strs('base64', 'utf8'), 'aaaaaa') assertStream([new Array(HIGH).join('a')], strs('utf8'), new Array(HIGH).join('a')) assertStream([new Array(HIGH + 1).join('a')], strs('utf8'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 2).join('a')], strs('utf8'), new Array(HIGH + 2).join('a')) assertStream([new Array(HIGH).join('a'), 'a'], strs('utf8'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 1).join('a'), 'a'], strs('utf8'), new Array(HIGH + 2).join('a')) assertStream([new Array(HIGH + 2).join('a'), 'a'], strs('utf8'), new Array(HIGH + 3).join('a')) assertStream([new Array(HIGH + 1).join('a')], strs('hex', 'hex'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 3).join('a')], strs('hex', 'hex'), new Array(HIGH + 3).join('a')) assertStream([new Array(HIGH).join('a'), 'a'], strs('hex', 'hex'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 2).join('a'), 'a'], strs('hex', 'hex'), new Array(HIGH + 3).join('a')) assertStream([new Array(HIGH).join('a')], strs('base64', 'base64'), new Array(HIGH - 1).join('a') + 'Y=') assertStream([new Array(HIGH + 1).join('a')], strs('base64', 'base64'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 2).join('a')], strs('base64', 'base64'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 3).join('a')], strs('base64', 'base64'), new Array(HIGH + 2).join('a') + 'Q==') assertStream([new Array(HIGH + 4).join('a')], strs('base64', 'base64'), new Array(HIGH + 3).join('a') + 'Y=') assertStream([new Array(HIGH + 5).join('a')], strs('base64', 'base64'), new Array(HIGH + 5).join('a')) assertStream([new Array(HIGH).join('a'), 'a'], strs('base64', 'base64'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 1).join('a'), 'a'], strs('base64', 'base64'), new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 2).join('a'), 'a'], strs('base64', 'base64'), new Array(HIGH + 2).join('a') + 'Q==') assertStream([new Array(HIGH + 3).join('a'), 'a'], strs('base64', 'base64'), new Array(HIGH + 3).join('a') + 'Y=') assertStream([new Array(HIGH + 4).join('a'), 'a'], strs('base64', 'base64'), new Array(HIGH + 5).join('a')) assertStream(['a'], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], 'a') assertStream(['a', 'a'], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], 'aa') assertStream([new Array(HIGH).join('a')], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], new Array(HIGH).join('a')) assertStream([new Array(HIGH + 1).join('a')], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 2).join('a')], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], new Array(HIGH + 2).join('a')) assertStream([new Array(HIGH).join('a'), 'a'], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], new Array(HIGH + 1).join('a')) assertStream([new Array(HIGH + 1).join('a'), 'a'], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], new Array(HIGH + 2).join('a')) assertStream([new Array(HIGH + 2).join('a'), 'a'], [strs('utf8', 'hex'), strs('hex', 'base64'), strs('base64', 'utf8')], new Array(HIGH + 3).join('a'))