/*
* gnu/regexp/CharIndexedReader.java
* Copyright (C) 1998 Wes Biggs
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library 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 Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package gnu.regexp;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
// FIXME: Integer.MAX_VALUE is a hack
// TODO: move(x) shouldn't rely on calling next() x times
class CharIndexedInputStream implements CharIndexed {
private static final int BUFFER_INCREMENT = 1024;
private BufferedInputStream br;
private int m_index, m_end, m_bufsize;
private char cached;
CharIndexedInputStream(InputStream str, int index) {
if (str instanceof BufferedInputStream) br = (BufferedInputStream) str;
else br = new BufferedInputStream(str,BUFFER_INCREMENT);
m_bufsize = BUFFER_INCREMENT;
m_index = -1;
m_end = Integer.MAX_VALUE; // end is unknown
next();
if (index > 0) move(index);
}
private boolean next() {
if (m_end == 1) return false;
m_end--; // closer to end
try {
if (m_index != -1) {
br.reset();
}
int i = br.read();
br.mark(m_bufsize);
if (i == -1) {
m_end = 1;
cached = CharIndexed.OUT_OF_BOUNDS;
return false;
}
cached = (char) i;
m_index = 1;
} catch (IOException e) {
e.printStackTrace();
cached = CharIndexed.OUT_OF_BOUNDS;
return false;
}
return true;
}
public char charAt(int index) {
if (index == 0) return cached;
if (index >= m_end) return CharIndexed.OUT_OF_BOUNDS;
if (index >= m_bufsize) {
// Allocate more space in the buffer.
try {
while (m_bufsize <= index) m_bufsize += BUFFER_INCREMENT;
br.reset();
br.mark(m_bufsize);
br.skip(index-1);
} catch (IOException e) { }
} else if (m_index != index) {
try {
br.reset();
br.skip(index-1);
} catch (IOException e) { }
}
char ch = CharIndexed.OUT_OF_BOUNDS;
try {
int i = br.read();
m_index = index+1; // m_index is index of next pos relative to charAt(0)
if (i == -1) {
// set flag that next should fail next time?
m_end = index;
return ch;
}
ch = (char) i;
} catch (IOException ie) { }
return ch;
}
public boolean move(int index) {
// move read position [index] clicks from 'charAt(0)'
boolean retval = true;
while (retval && (index-- > 0)) retval = next();
return retval;
}
public boolean isValid() {
return (cached != CharIndexed.OUT_OF_BOUNDS);
}
}