001: /*
002: * gnu/regexp/CharIndexedReader.java
003: * Copyright (C) 1998 Wes Biggs
004: *
005: * This library is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU Library General Public License as published
007: * by the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU Library General Public License for more details.
014: *
015: * You should have received a copy of the GNU Library General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
018: */
019:
020: package gnu.regexp;
021:
022: import java.io.InputStream;
023: import java.io.BufferedInputStream;
024: import java.io.IOException;
025:
026: // FIXME: Integer.MAX_VALUE is a hack
027: // TODO: move(x) shouldn't rely on calling next() x times
028:
029: class CharIndexedInputStream implements CharIndexed {
030: private static final int BUFFER_INCREMENT = 1024;
031:
032: private BufferedInputStream br;
033: private int m_index, m_end, m_bufsize;
034: private char cached;
035:
036: CharIndexedInputStream(InputStream str, int index) {
037: if (str instanceof BufferedInputStream)
038: br = (BufferedInputStream) str;
039: else
040: br = new BufferedInputStream(str, BUFFER_INCREMENT);
041: m_bufsize = BUFFER_INCREMENT;
042: m_index = -1;
043: m_end = Integer.MAX_VALUE; // end is unknown
044: next();
045: if (index > 0)
046: move(index);
047: }
048:
049: private boolean next() {
050: if (m_end == 1)
051: return false;
052: m_end--; // closer to end
053: try {
054: if (m_index != -1) {
055: br.reset();
056: }
057: int i = br.read();
058: br.mark(m_bufsize);
059: if (i == -1) {
060: m_end = 1;
061: cached = CharIndexed.OUT_OF_BOUNDS;
062: return false;
063: }
064: cached = (char) i;
065: m_index = 1;
066: } catch (IOException e) {
067: e.printStackTrace();
068: cached = CharIndexed.OUT_OF_BOUNDS;
069: return false;
070: }
071: return true;
072: }
073:
074: public char charAt(int index) {
075: if (index == 0)
076: return cached;
077: if (index >= m_end)
078: return CharIndexed.OUT_OF_BOUNDS;
079: if (index >= m_bufsize) {
080: // Allocate more space in the buffer.
081: try {
082: while (m_bufsize <= index)
083: m_bufsize += BUFFER_INCREMENT;
084: br.reset();
085: br.mark(m_bufsize);
086: br.skip(index - 1);
087: } catch (IOException e) {
088: }
089: } else if (m_index != index) {
090: try {
091: br.reset();
092: br.skip(index - 1);
093: } catch (IOException e) {
094: }
095: }
096: char ch = CharIndexed.OUT_OF_BOUNDS;
097:
098: try {
099: int i = br.read();
100: m_index = index + 1; // m_index is index of next pos relative to charAt(0)
101: if (i == -1) {
102: // set flag that next should fail next time?
103: m_end = index;
104: return ch;
105: }
106: ch = (char) i;
107: } catch (IOException ie) {
108: }
109:
110: return ch;
111: }
112:
113: public boolean move(int index) {
114: // move read position [index] clicks from 'charAt(0)'
115: boolean retval = true;
116: while (retval && (index-- > 0))
117: retval = next();
118: return retval;
119: }
120:
121: public boolean isValid() {
122: return (cached != CharIndexed.OUT_OF_BOUNDS);
123: }
124: }
|