1 | public class REFilterInputStream extends FilterInputStream {↵ | | 1 | public class REFilterReader extends FilterReader {↵
|
|
2 | private RE expr;↵ | | 2 | private RE expr;↵
|
3 | private String replace;↵ | | 3 | private String replace;↵
|
4 | private String buffer;↵ | | 4 | private String buffer;↵
|
5 | private int bufpos;↵ | | 5 | private int bufpos;↵
|
6 | private int offset;↵ | | 6 | private int offset;↵
|
7 | private CharIndexedInputStream stream;↵ | | 7 | private CharIndexedReader stream;↵
|
|
8 | /**↵ | | 8 | /**↵
|
9 | * Creates an REFilterInputStream. When reading from this stream,↵ | | 9 | * Creates an REFilterReader. When reading from this stream,↵
|
10 | * occurrences of patterns matching the supplied regular expression↵ | | 10 | * occurrences of patterns matching the supplied regular expression↵
|
11 | * will be replaced with the supplied replacement text (the↵ | | 11 | * will be replaced with the supplied replacement text (the↵
|
12 | * metacharacters $0 through $9 may be used to refer to the full↵ | | 12 | * metacharacters $0 through $9 may be used to refer to the full↵
|
13 | * match or subexpression matches).↵ | | 13 | * match or subexpression matches.↵
|
14 | *↵ | | 14 | *↵
|
15 | * @param stream The InputStream to be filtered.↵ | | 15 | * @param stream The Reader to be filtered.↵
|
16 | * @param expr The regular expression to search for.↵ | | 16 | * @param expr The regular expression to search for.↵
|
17 | * @param replace The text pattern to replace matches with. ↵ | | 17 | * @param replace The text pattern to replace matches with. ↵
|
18 | */↵ | | 18 | */↵
|
19 | public REFilterInputStream(InputStream stream, RE expr, String replace) {↵ | | 19 | public REFilterReader(Reader stream, RE expr, String replace) {↵
|
20 | super(stream);↵ | | 20 | super(stream);↵
|
21 | this.stream = new CharIndexedInputStream(stream,0);↵ | | 21 | this.stream = new CharIndexedReader(stream,0);↵
|
22 | this.expr = expr;↵ | | 22 | this.expr = expr;↵
|
23 | this.replace = replace;↵ | | 23 | this.replace = replace;↵
|
24 | }↵ | | 24 | }↵
|
|
25 | /**↵ | | 25 | /**↵
|
26 | * Reads the next byte from the stream per the general contract of↵ | | 26 | * Reads the next character from the stream per the general contract of↵
|
27 | * InputStream.read(). Returns -1 on error or end of stream.↵ | | 27 | * Reader.read(). Returns -1 on error or end of stream.↵
|
28 | */↵ | | 28 | */↵
|
29 | public int read() {↵ | | 29 | public int read() {↵
|
30 | // If we have buffered replace data, use it.↵ | | 30 | // If we have buffered replace data, use it.↵
|
31 | if ((buffer != null) && (bufpos < buffer.length())) {↵ | | 31 | if ((buffer != null) && (bufpos < buffer.length())) {↵
|
32 | return (int) buffer.charAt(bufpos++);↵ | | 32 | return (int) buffer.charAt(bufpos++);↵
|
33 | }↵ | | 33 | }↵
|
|
34 | // check if input is at a valid position↵ | | 34 | // check if input is at a valid position↵
|
35 | if (!stream.isValid()) return -1;↵ | | 35 | if (!stream.isValid()) return -1;↵
|
|
36 | REMatch mymatch = new REMatch(expr.getNumSubs(),offset,0);↵ | | 36 | REMatch mymatch = new REMatch(expr.getNumSubs(),offset,0);↵
|
37 | if (expr.match(stream, mymatch)) {↵ | | 37 | if (expr.match(stream,mymatch)) {↵
|
38 | mymatch.end[0] = mymatch.index;↵ | | 38 | mymatch.end[0] = mymatch.index;↵
|
39 | mymatch.finish(stream);↵ | | 39 | mymatch.finish(stream);↵
|
40 | stream.move(mymatch.toString().length());↵ | | 40 | stream.move(mymatch.toString().length());↵
|
41 | offset += mymatch.toString().length();↵ | | 41 | offset += mymatch.toString().length();↵
|
42 | buffer = mymatch.substituteInto(replace);↵ | | 42 | buffer = mymatch.substituteInto(replace);↵
|
43 | bufpos = 1;↵ | | 43 | bufpos = 1;↵
|
|
44 | // This is prone to infinite loops if replace string turns out empty.↵ | | |
|
45 | if (buffer.length() > 0) {↵ | | 44 | if (buffer.length() > 0) {↵
|
46 | return buffer.charAt(0);↵ | | 45 | return buffer.charAt(0);↵
|
47 | }↵ | | 46 | }↵
|
48 | }↵ | | 47 | }↵
|
49 | char ch = stream.charAt(0);↵ | | 48 | char ch = stream.charAt(0);↵
|
50 | if (ch == CharIndexed.OUT_OF_BOUNDS) return -1;↵ | | 49 | if (ch == CharIndexed.OUT_OF_BOUNDS) return -1;↵
|
51 | stream.move(1);↵ | | 50 | stream.move(1);↵
|
52 | offset++;↵ | | 51 | offset++;↵
|
53 | return ch;↵ | | 52 | return ch;↵
|
54 | }↵ | | 53 | }↵
|
|
55 | /** ↵ | | 54 | /** ↵
|
56 | * Returns false. REFilterInputStream does not support mark() and↵ | | 55 | * Returns false. REFilterReader does not support mark() and↵
|
57 | * reset() methods. ↵ | | 56 | * reset() methods. ↵
|
58 | */↵ | | 57 | */↵
|
59 | public boolean markSupported() {↵ | | 58 | public boolean markSupported() {↵
|
60 | return false;↵ | | 59 | return false;↵
|
61 | }↵ | | 60 | }↵
|
|
62 | /** Reads from the stream into the provided array. */↵ | | 61 | /** Reads from the stream into the provided array. */↵
|
63 | public int read(byte[] b, int off, int len) {↵ | | 62 | public int read(char[] b, int off, int len) {↵
|
64 | int i;↵ | | 63 | int i;↵
|
65 | int ok = 0;↵ | | 64 | int ok = 0;↵
|
66 | while (len-- > 0) {↵ | | 65 | while (len-- > 0) {↵
|
67 | i = read();↵ | | 66 | i = read();↵
|
68 | if (i == -1) return (ok == 0) ? -1 : ok;↵ | | 67 | if (i == -1) return (ok == 0) ? -1 : ok;↵
|
69 | b[off++] = (byte) i;↵ | | 68 | b[off++] = (char) i;↵
|
70 | ok++;↵ | | 69 | ok++;↵
|
71 | }↵ | | 70 | }↵
|
72 | return ok;↵ | | 71 | return ok;↵
|
73 | }↵ | | 72 | }↵
|
|
74 | /** Reads from the stream into the provided array. */↵ | | 73 | /** Reads from the stream into the provided array. */↵
|
75 | public int read(byte[] b) {↵ | | 74 | public int read(char[] b) {↵
|
76 | return read(b,0,b.length);↵ | | 75 | return read(b,0,b.length);↵
|
77 | | | 76 |
|