001: /*
002: * gnu/regexp/CharIndexedReader.java
003: * Copyright (C) 1998-2001 Wes Biggs
004: *
005: * This library is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU Lesser General Public License as published
007: * by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser 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: // TODO: move(x) shouldn't rely on calling next() x times
027:
028: class CharIndexedInputStream implements CharIndexed {
029: private static final int BUFFER_INCREMENT = 1024;
030: private static final int UNKNOWN = Integer.MAX_VALUE; // value for end
031:
032: private BufferedInputStream br;
033:
034: // so that we don't try to reset() right away
035: private int index = -1;
036:
037: private int bufsize = BUFFER_INCREMENT;
038:
039: private int end = UNKNOWN;
040:
041: private char cached = OUT_OF_BOUNDS;
042:
043: // Big enough for a \r\n pair
044: // lookBehind[0] = most recent
045: // lookBehind[1] = second most recent
046: private char[] lookBehind = new char[] { OUT_OF_BOUNDS,
047: OUT_OF_BOUNDS };
048:
049: CharIndexedInputStream(InputStream str, int index) {
050: if (str instanceof BufferedInputStream)
051: br = (BufferedInputStream) str;
052: else
053: br = new BufferedInputStream(str, BUFFER_INCREMENT);
054: next();
055: if (index > 0)
056: move(index);
057: }
058:
059: private boolean next() {
060: if (end == 1)
061: return false;
062: end--; // closer to end
063:
064: try {
065: if (index != -1) {
066: br.reset();
067: }
068: int i = br.read();
069: br.mark(bufsize);
070: if (i == -1) {
071: end = 1;
072: cached = OUT_OF_BOUNDS;
073: return false;
074: }
075: cached = (char) i;
076: index = 1;
077: } catch (IOException e) {
078: e.printStackTrace();
079: cached = OUT_OF_BOUNDS;
080: return false;
081: }
082: return true;
083: }
084:
085: public char charAt(int index) {
086: if (index == 0) {
087: return cached;
088: } else if (index >= end) {
089: return OUT_OF_BOUNDS;
090: } else if (index == -1) {
091: return lookBehind[0];
092: } else if (index == -2) {
093: return lookBehind[1];
094: } else if (index < -2) {
095: return OUT_OF_BOUNDS;
096: } else if (index >= bufsize) {
097: // Allocate more space in the buffer.
098: try {
099: while (bufsize <= index)
100: bufsize += BUFFER_INCREMENT;
101: br.reset();
102: br.mark(bufsize);
103: br.skip(index - 1);
104: } catch (IOException e) {
105: }
106: } else if (this .index != index) {
107: try {
108: br.reset();
109: br.skip(index - 1);
110: } catch (IOException e) {
111: }
112: }
113: char ch = OUT_OF_BOUNDS;
114:
115: try {
116: int i = br.read();
117: this .index = index + 1; // this.index is index of next pos relative to charAt(0)
118: if (i == -1) {
119: // set flag that next should fail next time?
120: end = index;
121: return ch;
122: }
123: ch = (char) i;
124: } catch (IOException ie) {
125: }
126:
127: return ch;
128: }
129:
130: public boolean move(int index) {
131: // move read position [index] clicks from 'charAt(0)'
132: boolean retval = true;
133: while (retval && (index-- > 0))
134: retval = next();
135: return retval;
136: }
137:
138: public boolean isValid() {
139: return (cached != OUT_OF_BOUNDS);
140: }
141: }
|