/*
* MemoryStreamReader.java
* (FScape)
*
* Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de
*/
package de.sciss.fscape.io;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class MemoryStreamReader
extends BufferedReader {
// -------- private variables --------
protected char buf[];
protected int bufSize; // = buf.length
protected int bufOff = 0;
protected static final String ERR_NOMARKS = "Requested marks not found";
// -------- public methods --------
public MemoryStreamReader( InputStream stream )
throws IOException
{
super( new InputStreamReader( stream ));
bufSize = 1024;
buf = new char[ bufSize ];
}
public int skipTo( String[] stopMarks )
throws IOException
{
return readTo( stopMarks, null, 0 );
}
public int skipTo( String[] stopMarks, long timeOut )
throws IOException
{
return readTo( stopMarks, null, timeOut );
}
public int readTo( String[] stopMarks, StringBuffer content )
throws IOException
{
return readTo( stopMarks, content, 0 );
}
/**
* Read ahead until one of the passend mark strings is encountered
*
* @param stopMarks if anyone of these is found the method will return and
* the next read starts at the first character of that
* mark string
* @param content all content from the last read position to the stop mark
* will be appended to this buffer; clearing the buffer
* must be done outside this method!
* @param timeOut millisecs - method will return approximately after this
* interval if no stopMark has yet been encountered; returns
* -1 in this case, so you may probably retry after some interaction
* @return index of the mark; -1 in case of timeout
*/
public int readTo( String[] stopMarks, StringBuffer content, long timeOut )
throws IOException
{
int maxMark, numRead, markLen, i, j, k, m, n;
String mark;
boolean checkTime = timeOut > 0;
long stopTime = timeOut;
boolean saveContent = content != null;
maxMark = checkBufSize( stopMarks ); // bufSize must exceed max of stopMark lengths!
if( checkTime ) {
stopTime += System.currentTimeMillis();
}
do {
numRead = read( buf, bufOff, bufSize - bufOff );
j = Math.max( 0, numRead );
bufOff += j;
for( i = 0; i < stopMarks.length; i++ ) {
mark = stopMarks[ i ];
markLen = mark.length();
bufLp: for( k = markLen; k < bufOff; k++ ) {
for( m = k, n = markLen; n > 0; ) {
if( mark.charAt( --n ) != buf[ --m ]) continue bufLp;
}
// Strings are matching
bufOff -= m;
if( saveContent ) {
content.append( buf, 0, m );
}
System.arraycopy( buf, m, buf, 0, bufOff );
return i;
}
}
// Shift buffer
m = Math.max( 0, bufOff - maxMark );
bufOff -= m;
if( saveContent ) {
content.append( buf, 0, m );
}
System.arraycopy( buf, m, buf, 0, bufOff );
if( checkTime ) {
if( System.currentTimeMillis() > stopTime ) return -1;
}
} while( numRead > 0 );
throw new EOFException( ERR_NOMARKS );
}
// -------- private methods --------
protected int checkBufSize( String[] stopMarks )
{
int i, j, k;
for( i = 0, j = 0; i < stopMarks.length; i++ ) {
k = stopMarks[ i ].length();
if( k > j ) {
j = k;
}
}
if( j > bufSize ) {
bufSize = j + (j >> 1);
buf = new char[ bufSize ];
}
return j;
}
}