109 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| const stream = require('stream');
 | |
| const Transform = stream.Transform;
 | |
| 
 | |
| /**
 | |
|  * Escapes dots in the beginning of lines. Ends the stream with <CR><LF>.<CR><LF>
 | |
|  * Also makes sure that only <CR><LF> sequences are used for linebreaks
 | |
|  *
 | |
|  * @param {Object} options Stream options
 | |
|  */
 | |
| class DataStream extends Transform {
 | |
|     constructor(options) {
 | |
|         super(options);
 | |
|         // init Transform
 | |
|         this.options = options || {};
 | |
|         this._curLine = '';
 | |
| 
 | |
|         this.inByteCount = 0;
 | |
|         this.outByteCount = 0;
 | |
|         this.lastByte = false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Escapes dots
 | |
|      */
 | |
|     _transform(chunk, encoding, done) {
 | |
|         let chunks = [];
 | |
|         let chunklen = 0;
 | |
|         let i,
 | |
|             len,
 | |
|             lastPos = 0;
 | |
|         let buf;
 | |
| 
 | |
|         if (!chunk || !chunk.length) {
 | |
|             return done();
 | |
|         }
 | |
| 
 | |
|         if (typeof chunk === 'string') {
 | |
|             chunk = Buffer.from(chunk);
 | |
|         }
 | |
| 
 | |
|         this.inByteCount += chunk.length;
 | |
| 
 | |
|         for (i = 0, len = chunk.length; i < len; i++) {
 | |
|             if (chunk[i] === 0x2e) {
 | |
|                 // .
 | |
|                 if ((i && chunk[i - 1] === 0x0a) || (!i && (!this.lastByte || this.lastByte === 0x0a))) {
 | |
|                     buf = chunk.slice(lastPos, i + 1);
 | |
|                     chunks.push(buf);
 | |
|                     chunks.push(Buffer.from('.'));
 | |
|                     chunklen += buf.length + 1;
 | |
|                     lastPos = i + 1;
 | |
|                 }
 | |
|             } else if (chunk[i] === 0x0a) {
 | |
|                 // .
 | |
|                 if ((i && chunk[i - 1] !== 0x0d) || (!i && this.lastByte !== 0x0d)) {
 | |
|                     if (i > lastPos) {
 | |
|                         buf = chunk.slice(lastPos, i);
 | |
|                         chunks.push(buf);
 | |
|                         chunklen += buf.length + 2;
 | |
|                     } else {
 | |
|                         chunklen += 2;
 | |
|                     }
 | |
|                     chunks.push(Buffer.from('\r\n'));
 | |
|                     lastPos = i + 1;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (chunklen) {
 | |
|             // add last piece
 | |
|             if (lastPos < chunk.length) {
 | |
|                 buf = chunk.slice(lastPos);
 | |
|                 chunks.push(buf);
 | |
|                 chunklen += buf.length;
 | |
|             }
 | |
| 
 | |
|             this.outByteCount += chunklen;
 | |
|             this.push(Buffer.concat(chunks, chunklen));
 | |
|         } else {
 | |
|             this.outByteCount += chunk.length;
 | |
|             this.push(chunk);
 | |
|         }
 | |
| 
 | |
|         this.lastByte = chunk[chunk.length - 1];
 | |
|         done();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Finalizes the stream with a dot on a single line
 | |
|      */
 | |
|     _flush(done) {
 | |
|         let buf;
 | |
|         if (this.lastByte === 0x0a) {
 | |
|             buf = Buffer.from('.\r\n');
 | |
|         } else if (this.lastByte === 0x0d) {
 | |
|             buf = Buffer.from('\n.\r\n');
 | |
|         } else {
 | |
|             buf = Buffer.from('\r\n.\r\n');
 | |
|         }
 | |
|         this.outByteCount += buf.length;
 | |
|         this.push(buf);
 | |
|         done();
 | |
|     }
 | |
| }
 | |
| 
 | |
| module.exports = DataStream;
 |