"use strict" ; import { _ } from "streamline-runtime" ; import { Reader } from "../reader" ; import { Writer } from "../writer" ; export interface ParserOptions { size ? : number ; encoding ? : string ; reviver ? : ( key : any , value : any ) => any ; unbounded ? : boolean ; } export function parser ( options ? ) { const opts = options || { } ; return ( _ , reader , writer ) => { function read ( _ ) { const data = reader . read ( _ ) ; return Buffer . isBuffer ( data ) ? data . toString ( opts . encoding || 'utf8' ) : data ; } var pos = 0 , chunk = read ( _ ) , beg , collected = "" , line = 1 , depth = 1 , quoted = false , escape = false , ch ; function error ( msg ) { throw new Error ( line + ": " + msg + " near " + ( chunk ? chunk . substring ( pos , pos + 20 ) : "<EOF>" ) ) ; } function peekch ( _ ) { if ( ! chunk ) return undefined ; if ( pos >= chunk . length ) { if ( beg !== undefined ) { collected += chunk . substring ( beg ) ; beg = 0 ; } chunk = read ( _ ) ; if ( ! chunk ) return undefined ; pos = 0 ; } return chunk [ pos ] ; } function skipSpaces ( _ ) { var ch ; while ( ( ch = peekch ( _ ) ) !== undefined && /^\s/ . test ( ch ) ) { line += ch === '\n' ? 1 : 0 ; pos ++ ; } return ch ; } function flush ( _ ) { if ( chunk === undefined || beg === undefined ) return ; collected += chunk . substring ( beg , pos ) ; const val = JSON . parse ( collected , opts . reviver ) ; writer . write ( _ , val ) ; beg = undefined ; collected = "" ; } ch = skipSpaces ( _ ) ; if ( ! opts . unbounded ) { if ( ch !== '[' ) throw error ( "expected [, got " + ch ) ; pos ++ ; } else { if ( ch === undefined ) return ; } while ( true ) { ch = peekch ( _ ) ; if ( escape ) { escape = false ; } else if ( quoted ) { if ( ch === '\\' ) escape = true ; else if ( ch === '"' ) { quoted = false ; } } else { switch ( ch ) { case undefined : if ( depth === 1 && opts . unbounded && beg === undefined ) return ; else throw error ( "unexpected EOF" ) ; case '"' : if ( depth === 1 && beg === undefined ) beg = pos ; quoted = true ; break ; case '{' : case '[' : if ( depth === 1 && beg === undefined ) beg = pos ; depth ++ ; break ; case '}' : depth -- ; if ( depth === 0 ) throw error ( "unexpected }" ) ; break ; case ']' : depth -- ; if ( depth === 0 ) { if ( opts . unbounded ) throw error ( "unexpected ]" ) ; if ( beg !== undefined ) flush ( _ ) ; return ; } break ; case ',' : if ( depth === 1 ) { if ( beg === undefined ) throw error ( "unexpected comma" ) ; flush ( _ ) ; } break ; default : if ( /^\s/ . test ( ch ) ) line += ( ch === '\n' ) ? 1 : 0 ; else if ( depth === 1 && beg === undefined ) beg = pos ; } } pos ++ ; } } ; } export interface FormatterOptions { unbounded ? : boolean ; replacer ? : ( key : string , value : any ) => any ; space ? : string ; } export function formatter ( options ? ) { const opts = options || { } ; return ( _ , reader , writer ) => { if ( ! opts . unbounded ) writer . write ( _ , '[' ) ; reader . forEach ( _ , ( _ , obj , i ) => { if ( i > 0 ) writer . write ( _ , ',\n' ) ; writer . write ( _ , JSON . stringify ( obj , opts . replacer , opts . space ) ) ; } ) ; writer . write ( _ , opts . unbounded ? ',' : ']' ) ; writer . write ( _ , undefined ) ; } ; }