import * as Stream from 'stream' ; import Logger from '../../../tools/env.logger' ; export interface IMatch { row : number ; value : string [ ] | undefined ; } export const CGroupDelimiter = '\u0002' ; export default class Transform extends Stream . Transform { private _logger : Logger ; private _rest : string = '' ; private _matches : IMatch [ ] = [ ] ; private _groups : boolean = false ; private _stopped : boolean = false ; private _rowOffset : number = 0 ; constructor ( options , rowOffset = 0 , groups = false ) { super ( options ) ; this . _logger = new Logger ( `Transform.Charting` ) ; this . _groups = groups ; this . _rowOffset = rowOffset ; } public getMatches ( ) { return this . _matches ; } public _transform ( chunk , encoding , callback ) { let output = '' ; if ( typeof chunk === 'string' ) { output = this . _rest + chunk ; } else { output = this . _rest + chunk . toString ( 'utf8' ) ; } const rest = this . _getRest ( output ) ; this . _rest = rest . rest ; output = rest . cleared ; const lines = output . split ( /[\n\r]/gi ) ; lines . forEach ( ( line ) => { const parts = line . split ( ':' ) ; if ( parts . length < 2 ) { return ; } const num = parseFloat ( parts [ 0 ] ) ; if ( isNaN ( num ) || ! isFinite ( num ) ) { this . _logger . warn ( `Fail to detect line number for ${ line }` ) ; return ; } const match = { row : num + this . _rowOffset , value : this . _groups ? parts [ 1 ] . split ( CGroupDelimiter ) : undefined , } ; this . _matches . push ( match ) ; } ) ; if ( this . _stopped ) { return ; } if ( callback !== undefined ) { callback ( undefined , output ) ; } } public stop ( ) { this . _stopped = true ; } private _getRest ( str ) { const last = str . length - 1 ; for ( let i = last ; i >= 0 ; i -= 1 ) { if ( str [ i ] === '\n' && i > 0 ) { return { rest : str . substr ( i + 1 , last ) , cleared : str . substr ( 0 , i + 1 ) , } ; } } return { rest : '' , cleared : str } ; } }