/**
* $Id: $
* $Date: $
*
*/
package org.xmlsh.util.text;
import java.io.IOException;
import java.io.Reader;
import org.xmlsh.core.InvalidArgumentException;
/*
* A TextLine parser based on a Scanner object thats preconfigured
* Trims trailing whitespace and reports comments and blank lines
*
*/
public abstract class TextLineScanner implements ITextLineParser
{
private String[] beginOfLineComments = { "#" , ";" } ; // Must start at SOL
private String[] lineComments = { "#" , ";" } ; // Comments rest of line
private String currentLine = null ;
private boolean escapeEOL = true ;
private boolean escapeLiteral = true ;
private boolean ignoreBlankLines = true ;
private boolean trimEnd = true ;
private boolean trimStart = false ;
public TextLineScanner()
{
}
void run(Reader r) throws InvalidArgumentException, IOException {
String line ;
while((line = readLine( r )) != null ) {
// Comments are before trimming
if( lineComments != null && line.length() > 0 ){
int pos = findFirst( line , lineComments );
if( pos >= 0 ){
String comment = line.substring(pos+1);
line = line.substring(0,pos);
onComment(comment);
}
}
if( beginOfLineComments != null && line.length() > 0 ){
int pos = startsWith( line , beginOfLineComments );
if( pos > 0 ){
String comment = line.substring(pos+1);
line = "" ;
onComment(comment);
continue ;
}
}
if( trimEnd )
line = trimEnd(line);
if( trimStart )
line = trimStart(line);
if( ignoreBlankLines && line.length() == 0 )
continue;
onLine( currentLine = line );
}
onEndOfFile();
}
private String trimStart(String line) {
int pos = 0;
while( pos < line.length() && Character.isWhitespace(line.charAt(pos)))
pos++;
if( pos > 0 )
return line.substring(pos);
return line ;
}
// Returns the position of a line *after* the longest substring initial match
private int startsWith(String line, String[] substrings) {
int len = -1;
for(String s : substrings ){
if( line.startsWith(s))
len = Math.max( len , s.length() );
}
return len ;
}
// Finds the first position of any substring
private int findFirst(String line, String[] substrings) {
int pos = -1;
for( String s : substrings ){
int spos = line.indexOf( s );
if( spos >= 0 ){
if( pos < 0 )
pos = spos;
else
pos = Math.min( spos , pos );
}
}
return pos ;
}
private String trimEnd(String line)
{
int pos = line.length() - 1;
while( pos >= 0 && Character.isWhitespace(line.charAt(pos) ))
pos--;
if( pos < line.length() - 1 )
return line.substring( 0 , pos + 1 );
return line ;
}
private String readLine(Reader r) throws IOException {
StringBuilder sb = null ;
int c ;
while(( c = r.read()) >= 0 ){
if( sb == null )
sb = new StringBuilder();
if( c == '\r')
continue ;
if( c == '\n')
break ;
if( c == '\\'){
c = r.read();
if( c == '\r' )
c = r.read();
if( c < 0 ){
sb.append( '\\');
break ;
}
if( escapeLiteral ){
switch( c ){
case 'b' : sb.append( '\b') ; continue ;
case 'n' : sb.append( '\n') ; continue ;
case 't' : sb.append( '\t') ; continue ;
case 'f' : sb.append( '\f') ; continue ;
default : break ;
}
}
if( escapeEOL && c == '\n' )
continue ;
}
sb.append( ( char) c );
}
return sb == null ? null : sb.toString();
}
protected String getCurrentLine() {
return currentLine;
}
}
/*
* Copyright (C) 2008-2012 David A. Lee.
*
* The contents of this file are subject to the "Simplified BSD License" (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy of the
* License at http://www.opensource.org/licenses/bsd-license.php
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights and limitations under the License.
*
* The Original Code is: all this file.
*
* The Initial Developer of the Original Code is David A. Lee
*
* Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
*
* Contributor(s): David A. Lee
*
*/