/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2009 Pentaho Corporation. All rights reserved.
*/
package org.w3c.flute.parser;
/**
* An implementation of interface CharStream, where the stream is assumed to contain only ASCII characters (without
* unicode processing).
*/
public final class Generic_CharStream implements CharStream {
public static final boolean staticFlag = false;
int bufsize;
int available;
int tokenBegin;
public int bufpos = -1;
private int bufline[];
private int bufcolumn[];
private int column = 0;
private int line = 1;
private boolean prevCharIsCR = false;
private boolean prevCharIsLF = false;
private java.io.Reader reader;
private char[] buffer;
private int maxNextCharInd = 0;
private int inBuf = 0;
private final void ExpandBuff( boolean wrapAround ) {
char[] newbuffer = new char[ bufsize + 2048 ];
int newbufline[] = new int[ bufsize + 2048 ];
int newbufcolumn[] = new int[ bufsize + 2048 ];
try {
if ( wrapAround ) {
System.arraycopy( buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin );
System.arraycopy( buffer, 0, newbuffer,
bufsize - tokenBegin, bufpos );
buffer = newbuffer;
System.arraycopy( bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin );
System.arraycopy( bufline, 0, newbufline, bufsize - tokenBegin, bufpos );
bufline = newbufline;
System.arraycopy( bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin );
System.arraycopy( bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos );
bufcolumn = newbufcolumn;
maxNextCharInd = ( bufpos += ( bufsize - tokenBegin ) );
} else {
System.arraycopy( buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin );
buffer = newbuffer;
System.arraycopy( bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin );
bufline = newbufline;
System.arraycopy( bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin );
bufcolumn = newbufcolumn;
maxNextCharInd = ( bufpos -= tokenBegin );
}
} catch ( Throwable t ) {
throw new Error( t.getMessage() );
}
bufsize += 2048;
available = bufsize;
tokenBegin = 0;
}
private final void FillBuff() throws java.io.IOException {
if ( maxNextCharInd == available ) {
if ( available == bufsize ) {
if ( tokenBegin > 2048 ) {
bufpos = maxNextCharInd = 0;
available = tokenBegin;
} else if ( tokenBegin < 0 ) {
bufpos = maxNextCharInd = 0;
} else {
ExpandBuff( false );
}
} else if ( available > tokenBegin ) {
available = bufsize;
} else if ( ( tokenBegin - available ) < 2048 ) {
ExpandBuff( true );
} else {
available = tokenBegin;
}
}
int i;
try {
if ( ( i = reader.read( buffer, maxNextCharInd,
available - maxNextCharInd ) ) == -1 ) {
reader.close();
throw new java.io.IOException();
} else {
maxNextCharInd += i;
}
return;
} catch ( java.io.IOException e ) {
--bufpos;
backup( 0 );
if ( tokenBegin == -1 ) {
tokenBegin = bufpos;
}
throw e;
}
}
public final char BeginToken() throws java.io.IOException {
tokenBegin = -1;
char c = readChar();
tokenBegin = bufpos;
return c;
}
private final void UpdateLineColumn( char c ) {
column++;
if ( prevCharIsLF ) {
prevCharIsLF = false;
line += ( column = 1 );
} else if ( prevCharIsCR ) {
prevCharIsCR = false;
if ( c == '\n' ) {
prevCharIsLF = true;
} else {
line += ( column = 1 );
}
}
switch( c ) {
case '\r':
prevCharIsCR = true;
break;
case '\n':
prevCharIsLF = true;
break;
case '\t':
column--;
column += ( 8 - ( column & 07 ) );
break;
default:
break;
}
bufline[ bufpos ] = line;
bufcolumn[ bufpos ] = column;
}
public final char readChar() throws java.io.IOException {
if ( inBuf > 0 ) {
--inBuf;
return (char) ( (char) 0xff & buffer[ ( bufpos == bufsize - 1 ) ? ( bufpos = 0 ) : ++bufpos ] );
}
if ( ++bufpos >= maxNextCharInd ) {
FillBuff();
}
char c = (char) ( (char) 0xff & buffer[ bufpos ] );
UpdateLineColumn( c );
return ( c );
}
/**
* @see #getEndColumn
* @deprecated
*/
public final int getColumn() {
return bufcolumn[ bufpos ];
}
/**
* @see #getEndLine
* @deprecated
*/
public final int getLine() {
return bufline[ bufpos ];
}
public final int getEndColumn() {
return bufcolumn[ bufpos ];
}
public final int getEndLine() {
return bufline[ bufpos ];
}
public final int getBeginColumn() {
return bufcolumn[ tokenBegin ];
}
public final int getBeginLine() {
return bufline[ tokenBegin ];
}
public final void backup( int amount ) {
inBuf += amount;
if ( ( bufpos -= amount ) < 0 ) {
bufpos += bufsize;
}
}
public Generic_CharStream( java.io.Reader dstream, int startline,
int startcolumn, int buffersize ) {
reader = dstream;
line = startline;
column = startcolumn - 1;
available = bufsize = buffersize;
buffer = new char[ buffersize ];
bufline = new int[ buffersize ];
bufcolumn = new int[ buffersize ];
}
public Generic_CharStream( java.io.Reader dstream, int startline,
int startcolumn ) {
this( dstream, startline, startcolumn, 4096 );
}
public void ReInit( java.io.Reader dstream, int startline,
int startcolumn, int buffersize ) {
reader = dstream;
line = startline;
column = startcolumn - 1;
if ( buffer == null || buffersize != buffer.length ) {
available = bufsize = buffersize;
buffer = new char[ buffersize ];
bufline = new int[ buffersize ];
bufcolumn = new int[ buffersize ];
}
prevCharIsLF = prevCharIsCR = false;
tokenBegin = inBuf = maxNextCharInd = 0;
bufpos = -1;
}
public void ReInit( java.io.Reader dstream, int startline,
int startcolumn ) {
ReInit( dstream, startline, startcolumn, 4096 );
}
public final String GetImage() {
if ( bufpos >= tokenBegin ) {
return new String( buffer, tokenBegin, bufpos - tokenBegin + 1 );
} else {
return new String( buffer, tokenBegin, bufsize - tokenBegin ) +
new String( buffer, 0, bufpos + 1 );
}
}
public final char[] GetSuffix( int len ) {
char[] ret = new char[ len ];
if ( ( bufpos + 1 ) >= len ) {
System.arraycopy( buffer, bufpos - len + 1, ret, 0, len );
} else {
System.arraycopy( buffer, bufsize - ( len - bufpos - 1 ), ret, 0,
len - bufpos - 1 );
System.arraycopy( buffer, 0, ret, len - bufpos - 1, bufpos + 1 );
}
return ret;
}
public void Done() {
buffer = null;
bufline = null;
bufcolumn = null;
}
/**
* Method to adjust line and column numbers for the start of a token.<BR>
*/
public void adjustBeginLineColumn( int newLine, int newCol ) {
int start = tokenBegin;
int len;
if ( bufpos >= tokenBegin ) {
len = bufpos - tokenBegin + inBuf + 1;
} else {
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
}
int i = 0, j = 0, k = 0;
int nextColDiff = 0, columnDiff = 0;
while ( i < len &&
bufline[ j = start % bufsize ] == bufline[ k = ++start % bufsize ] ) {
bufline[ j ] = newLine;
nextColDiff = columnDiff + bufcolumn[ k ] - bufcolumn[ j ];
bufcolumn[ j ] = newCol + columnDiff;
columnDiff = nextColDiff;
i++;
}
if ( i < len ) {
bufline[ j ] = newLine++;
bufcolumn[ j ] = newCol + columnDiff;
while ( i++ < len ) {
if ( bufline[ j = start % bufsize ] != bufline[ ++start % bufsize ] ) {
bufline[ j ] = newLine++;
} else {
bufline[ j ] = newLine;
}
}
}
line = bufline[ j ];
column = bufcolumn[ j ];
}
}