67 lines
2.6 KiB
JavaScript
67 lines
2.6 KiB
JavaScript
const logger = require.main.require("./helper/logger.js")("RegexBlockStream");
|
|
const { Transform } = require('stream')
|
|
|
|
/**
|
|
* Matches whole blocks as regex and passes them on
|
|
*/
|
|
class RegexBlockStream extends Transform{
|
|
matcher;
|
|
withholdLastBlock;
|
|
matchAllOnFlush;
|
|
|
|
/**
|
|
* @param {RegExp} matcher Block-match
|
|
* @param {boolean} withholdLastBlock When true, the last matches block will not be submitted to prevent submitting incomplete blocks.
|
|
* @param {boolean} matchAllOnFlush (Only in combination with withholdLastBlock) When enabled, the buffer will be matched on last time on _flush (stream deconstruction) and write any, also incomplete, blocks
|
|
* @remarks WARNING: It should match a clean-block (including e.g. newline)! Otherwise buffer will get dirty and use more and more resources.
|
|
*/
|
|
constructor(matcher, withholdLastBlock = true, matchAllOnFlush = false){
|
|
super({
|
|
readableObjectMode: true,
|
|
writableObjectMode: true
|
|
});
|
|
|
|
this.matcher = matcher;
|
|
this.withholdLastBlock = withholdLastBlock;
|
|
this.matchAllOnFlush = matchAllOnFlush;
|
|
}
|
|
|
|
_transform(chunk, encoding, next){
|
|
chunk = this.readableBuffer.length? this.readableBuffer.join('') + chunk: chunk; // Add previous buffer to current chunk
|
|
this.readableBuffer.length && this.readableBuffer.clear(); // Clear buffer once we read it
|
|
|
|
let matches = chunk.match(this.matcher); // Match
|
|
if(matches){
|
|
if(this.withholdLastBlock) matches.pop(); // Remove last if we want to withhold it
|
|
chunk = this._writeMatches(matches, chunk);
|
|
}
|
|
|
|
this.readableBuffer.push(chunk); // Store remaining data in buffer
|
|
next(); // Get next chunk
|
|
}
|
|
|
|
_writeMatches(matches, chunk = null){
|
|
if(matches){
|
|
matches.forEach((match) => {
|
|
this.push(match); // Write match to stream
|
|
if(chunk) chunk = chunk.replace(match, ''); // Remove match from chunks
|
|
});
|
|
}
|
|
if(chunk) return chunk;
|
|
}
|
|
|
|
_flush(next){
|
|
if(matchAllOnFlush){ // When requested, we'll match one last time over the remaining buffer
|
|
let chunk = this.readableBuffer.join('');
|
|
let matches = chunk.match(this.matcher); // Match remaining buffer
|
|
_writeMatches(matches); // Write matches including last element
|
|
}
|
|
|
|
next(); // Tell system we are done
|
|
}
|
|
}
|
|
|
|
// Specify exports
|
|
module.exports = {
|
|
RegexBlockStream
|
|
}; |