2 // This software is now distributed according to
3 // the Lesser Gnu Public License. Please see
4 // http://www.gnu.org/copyleft/lesser.txt for
8 package com.stevesoft.pat;
10 import java.io.IOException;
11 import java.io.StringWriter;
12 import java.io.Writer;
14 import com.stevesoft.pat.wrap.WriterWrap;
17 * A basic extension of FilterWriter that uses Transformer to make replacements
18 * in data as it is written out. It attempts to transform a string whenever the
19 * End-of-Line (EOL) character is written (which is, by default, the carriage
20 * return '\n'). Only the transformed portion of the line is written out,
21 * allowing the RegexWriter to wait until a complete pattern is present before
22 * attempting to write out info. Until a pattern completes, data is stored in a
23 * StringBuffer -- which can be accessed through the length() and charAt()
24 * methods of this class.
26 * Note a subtlety here -- while a Transformer normally matches at higher
27 * priority against the pattern added to it first, this will not necessarily be
28 * true when a multi-line match is in progress because one of the complete
29 * multi-line patterns may not be completely loaded in RegexWriter's buffer. For
30 * this reason, the Transformer class is equipped with a way to add a pattern
31 * and replacement rule in three pieces -- a beginning (once this matches,
32 * nothing else in the Transformer can match until the whole pattern matches),
33 * an ending (the whole pattern is a String formed by adding the beginning and
34 * ending), and a ReplaceRule.
36 * An illustration of this is given in the this <a
37 * href="../test/trans.java">example.</a>
39 public class RegexWriter extends Writer
47 StringBuffer sb = new StringBuffer();
49 PartialBuffer wrap = new PartialBuffer(sb);
55 int bufferSize = 2 * 1024;
57 public RegexWriter(Transformer t, Writer w)
60 ww = new WriterWrap(w);
61 repr = t.getReplacer();
62 repr.setBuffer(new StringBufferLike(ww));
66 public RegexWriter(Regex r, Writer w)
69 ww = new WriterWrap(w);
70 repr = r.getReplacer();
71 repr.setBuffer(new StringBufferLike(ww));
78 * This method no longer serves any purpose.
83 public char getEOLchar()
89 * This method no longer serves any purpose.
94 public void setEOLchar(char c)
102 * This method no longer serves any purpose.
107 public int getMaxLines()
113 * This method no longer serves any purpose.
118 public void setMaxLines(int ml)
123 void write() throws IOException
125 Regex rex = repr.getRegex();
127 if (rex.matchAt(wrap, epos) && !wrap.overRun)
131 w.write(sb.charAt(pos++));
133 int to = rex.matchedTo();
135 repr.apply(rex, rex.getReplaceRule());
137 if (epos == eposOld && epos < sb.length())
142 else if (!wrap.overRun && epos < sb.length())
148 w.write(sb.charAt(pos++));
150 if (epos == sb.length())
155 else if (pos > bufferSize)
157 for (int i = bufferSize; i < sb.length(); i++)
159 sb.setCharAt(i - bufferSize, sb.charAt(i));
163 sb.setLength(sb.length() - bufferSize);
167 public void write(char[] ca, int b, int n) throws IOException
170 for (int i = b; i < m; i++)
173 if (sb.length() % interval == interval - 1)
175 wrap.overRun = false;
176 while (epos + interval < sb.length() && !wrap.overRun)
184 public void flush() throws IOException
188 public void close() throws IOException
190 wrap.allowOverRun = false;
191 wrap.overRun = false;
192 while (epos < sb.length())
200 /** The current size of the StringBuffer in use by RegexWriter. */
206 /** The character at location i in the StringBuffer. */
207 public char charAt(int i)
212 /** Set the interval at which regex patterns are checked. */
213 public void setInterval(int i)
218 /** Get the interval at which regex matches are checked. */
219 public int getInterval()
224 /** Get the buffer size. */
225 public int getBufferSize()
230 /** Set the buffer size. */
231 public void setBufferSize(int i)
236 static void test(String re, String inp, int n) throws Exception
238 StringWriter sw = new StringWriter();
239 Regex rex = Regex.perlCode(re);
240 String res1 = rex.replaceAll(inp);
241 RegexWriter rw = new RegexWriter(rex, sw);
242 for (int i = 0; i < inp.length(); i++)
244 rw.write(inp.charAt(i));
247 String res2 = sw.toString();
248 if (!res1.equals(res2))
250 System.out.println("nmax=" + n);
251 System.out.println("re=" + re);
252 System.out.println("inp=" + inp);
253 System.out.println("res1=" + res1);
254 System.out.println("res2=" + res2);
259 public static void main(String[] args) throws Exception
261 for (int n = 1; n <= 1; n++)
263 test("s/x/y/", "-----x123456789", n);
264 test("s/x/y/", "x123456789", n);
265 test("s/x/y/", "-----x", n);
266 test("s/x.*?x/y/", ".xx..x..x...x...x....x....x", n);
267 test("s/x.*x/[$&]/", "--x........x--xx", n);
268 test("s/x.*x/[$&]/", "--x........x------", n);
269 test("s/.$/a/m", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb", n);
270 test("s/.$/a/", "123", n);
271 test("s/.$/a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n);
272 test("s/^./a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n);
273 test("s/$/a/", "bbb", n);
274 test("s/^/a/", "bbb", n);
275 test("s/^/a/", "", n);
276 test("s{.*}{N}", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", n);
277 test("s/.{0,7}/y/", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", n);
278 test("s/x/$&/", "xxx", n);
280 System.out.println("Success!!!");