You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					103 lines
				
				2.8 KiB
			
		
		
			
		
	
	
					103 lines
				
				2.8 KiB
			| 
											3 years ago
										 | var util = require('util') | ||
|  | var Stream = require('stream') | ||
|  | var StringDecoder = require('string_decoder').StringDecoder | ||
|  | 
 | ||
|  | module.exports = StringStream | ||
|  | module.exports.AlignedStringDecoder = AlignedStringDecoder | ||
|  | 
 | ||
|  | function StringStream(from, to) { | ||
|  |   if (!(this instanceof StringStream)) return new StringStream(from, to) | ||
|  | 
 | ||
|  |   Stream.call(this) | ||
|  | 
 | ||
|  |   if (from == null) from = 'utf8' | ||
|  | 
 | ||
|  |   this.readable = this.writable = true | ||
|  |   this.paused = false | ||
|  |   this.toEncoding = (to == null ? from : to) | ||
|  |   this.fromEncoding = (to == null ? '' : from) | ||
|  |   this.decoder = new AlignedStringDecoder(this.toEncoding) | ||
|  | } | ||
|  | util.inherits(StringStream, Stream) | ||
|  | 
 | ||
|  | StringStream.prototype.write = function(data) { | ||
|  |   if (!this.writable) { | ||
|  |     var err = new Error('stream not writable') | ||
|  |     err.code = 'EPIPE' | ||
|  |     this.emit('error', err) | ||
|  |     return false | ||
|  |   } | ||
|  |   if (this.fromEncoding) { | ||
|  |     if (Buffer.isBuffer(data) || typeof data === 'number') data = data.toString() | ||
|  |     data = new Buffer(data, this.fromEncoding) | ||
|  |   } | ||
|  |   var string = this.decoder.write(data) | ||
|  |   if (string.length) this.emit('data', string) | ||
|  |   return !this.paused | ||
|  | } | ||
|  | 
 | ||
|  | StringStream.prototype.flush = function() { | ||
|  |   if (this.decoder.flush) { | ||
|  |     var string = this.decoder.flush() | ||
|  |     if (string.length) this.emit('data', string) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | StringStream.prototype.end = function() { | ||
|  |   if (!this.writable && !this.readable) return | ||
|  |   this.flush() | ||
|  |   this.emit('end') | ||
|  |   this.writable = this.readable = false | ||
|  |   this.destroy() | ||
|  | } | ||
|  | 
 | ||
|  | StringStream.prototype.destroy = function() { | ||
|  |   this.decoder = null | ||
|  |   this.writable = this.readable = false | ||
|  |   this.emit('close') | ||
|  | } | ||
|  | 
 | ||
|  | StringStream.prototype.pause = function() { | ||
|  |   this.paused = true | ||
|  | } | ||
|  | 
 | ||
|  | StringStream.prototype.resume = function () { | ||
|  |   if (this.paused) this.emit('drain') | ||
|  |   this.paused = false | ||
|  | } | ||
|  | 
 | ||
|  | function AlignedStringDecoder(encoding) { | ||
|  |   StringDecoder.call(this, encoding) | ||
|  | 
 | ||
|  |   switch (this.encoding) { | ||
|  |     case 'base64': | ||
|  |       this.write = alignedWrite | ||
|  |       this.alignedBuffer = new Buffer(3) | ||
|  |       this.alignedBytes = 0 | ||
|  |       break | ||
|  |   } | ||
|  | } | ||
|  | util.inherits(AlignedStringDecoder, StringDecoder) | ||
|  | 
 | ||
|  | AlignedStringDecoder.prototype.flush = function() { | ||
|  |   if (!this.alignedBuffer || !this.alignedBytes) return '' | ||
|  |   var leftover = this.alignedBuffer.toString(this.encoding, 0, this.alignedBytes) | ||
|  |   this.alignedBytes = 0 | ||
|  |   return leftover | ||
|  | } | ||
|  | 
 | ||
|  | function alignedWrite(buffer) { | ||
|  |   var rem = (this.alignedBytes + buffer.length) % this.alignedBuffer.length | ||
|  |   if (!rem && !this.alignedBytes) return buffer.toString(this.encoding) | ||
|  | 
 | ||
|  |   var returnBuffer = new Buffer(this.alignedBytes + buffer.length - rem) | ||
|  | 
 | ||
|  |   this.alignedBuffer.copy(returnBuffer, 0, 0, this.alignedBytes) | ||
|  |   buffer.copy(returnBuffer, this.alignedBytes, 0, buffer.length - rem) | ||
|  | 
 | ||
|  |   buffer.copy(this.alignedBuffer, 0, buffer.length - rem, buffer.length) | ||
|  |   this.alignedBytes = rem | ||
|  | 
 | ||
|  |   return returnBuffer.toString(this.encoding) | ||
|  | } |