001: /*
002: * gnu/regexp/REFilterReader.java
003: * Copyright (C) 2001 Lee Sau Dan
004: * Based on gnu.regexp.REFilterInputStream by Wes Biggs
005: *
006: * This library is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License as published
008: * by the Free Software Foundation; either version 2.1 of the License, or
009: * (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
019: */
020:
021: package gnu.regexp;
022:
023: import java.io.FilterReader;
024: import java.io.Reader;
025:
026: /**
027: * Replaces instances of a given RE with replacement text.
028: *
029: * @author <A HREF="http://www.csis.hku.hk/~sdlee/">Lee Sau Dan</A>
030: * @since gnu.regexp 1.1.0
031: */
032:
033: public class REFilterReader extends FilterReader {
034:
035: private RE expr;
036: private String replace;
037: private String buffer;
038: private int bufpos;
039: private int offset;
040: private CharIndexedReader stream;
041:
042: /**
043: * Creates an REFilterReader. When reading from this stream,
044: * occurrences of patterns matching the supplied regular expression
045: * will be replaced with the supplied replacement text (the
046: * metacharacters $0 through $9 may be used to refer to the full
047: * match or subexpression matches.
048: *
049: * @param stream The Reader to be filtered.
050: * @param expr The regular expression to search for.
051: * @param replace The text pattern to replace matches with.
052: */
053: public REFilterReader(Reader stream, RE expr, String replace) {
054: super (stream);
055: this .stream = new CharIndexedReader(stream, 0);
056: this .expr = expr;
057: this .replace = replace;
058: }
059:
060: /**
061: * Reads the next character from the stream per the general contract of
062: * Reader.read(). Returns -1 on error or end of stream.
063: */
064: public int read() {
065: // If we have buffered replace data, use it.
066: if ((buffer != null) && (bufpos < buffer.length())) {
067: return (int) buffer.charAt(bufpos++);
068: }
069:
070: // check if input is at a valid position
071: if (!stream.isValid())
072: return -1;
073:
074: REMatch mymatch = new REMatch(expr.getNumSubs(), offset, 0);
075: if (expr.match(stream, mymatch)) {
076: mymatch.end[0] = mymatch.index;
077: mymatch.finish(stream);
078: stream.move(mymatch.toString().length());
079: offset += mymatch.toString().length();
080: buffer = mymatch.substituteInto(replace);
081: bufpos = 1;
082:
083: if (buffer.length() > 0) {
084: return buffer.charAt(0);
085: }
086: }
087: char ch = stream.charAt(0);
088: if (ch == CharIndexed.OUT_OF_BOUNDS)
089: return -1;
090: stream.move(1);
091: offset++;
092: return ch;
093: }
094:
095: /**
096: * Returns false. REFilterReader does not support mark() and
097: * reset() methods.
098: */
099: public boolean markSupported() {
100: return false;
101: }
102:
103: /** Reads from the stream into the provided array. */
104: public int read(char[] b, int off, int len) {
105: int i;
106: int ok = 0;
107: while (len-- > 0) {
108: i = read();
109: if (i == -1)
110: return (ok == 0) ? -1 : ok;
111: b[off++] = (char) i;
112: ok++;
113: }
114: return ok;
115: }
116:
117: /** Reads from the stream into the provided array. */
118: public int read(char[] b) {
119: return read(b, 0, b.length);
120: }
121: }
|