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;
12 import com.stevesoft.pat.wrap.*;
15 * A basic extension of FilterWriter that uses Transformer to make replacements
16 * in data as it is written out. It attempts to transform a string whenever the
17 * End-of-Line (EOL) character is written (which is, by default, the carriage
18 * return '\n'). Only the transformed portion of the line is written out,
19 * allowing the RegexWriter to wait until a complete pattern is present before
20 * attempting to write out info. Until a pattern completes, data is stored in a
21 * StringBuffer -- which can be accessed through the length() and charAt()
22 * methods of this class.
24 * Note a subtlety here -- while a Transformer normally matches at higher
25 * priority against the pattern added to it first, this will not necessarily be
26 * true when a multi-line match is in progress because one of the complete
27 * multi-line patterns may not be completely loaded in RegexWriter's buffer. For
28 * this reason, the Transformer class is equipped with a way to add a pattern
29 * and replacement rule in three pieces -- a beginning (once this matches,
30 * nothing else in the Transformer can match until the whole pattern matches),
31 * an ending (the whole pattern is a String formed by adding the beginning and
32 * ending), and a ReplaceRule.
34 * An illustration of this is given in the this <a
35 * href="../test/trans.java">example.</a>
37 public class RegexWriter extends Writer
45 StringBuffer sb = new StringBuffer();
47 PartialBuffer wrap = new PartialBuffer(sb);
53 int bufferSize = 2 * 1024;
55 public RegexWriter(Transformer t, Writer w)
58 ww = new WriterWrap(w);
59 repr = t.getReplacer();
60 repr.setBuffer(new StringBufferLike(ww));
64 public RegexWriter(Regex r, Writer w)
67 ww = new WriterWrap(w);
68 repr = r.getReplacer();
69 repr.setBuffer(new StringBufferLike(ww));
76 * This method no longer serves any purpose.
80 public char getEOLchar()
86 * This method no longer serves any purpose.
90 public void setEOLchar(char c)
98 * This method no longer serves any purpose.
102 public int getMaxLines()
108 * This method no longer serves any purpose.
112 public void setMaxLines(int ml)
117 void write() throws IOException
119 Regex rex = repr.getRegex();
121 if (rex.matchAt(wrap, epos) && !wrap.overRun)
125 w.write(sb.charAt(pos++));
127 int to = rex.matchedTo();
129 repr.apply(rex, rex.getReplaceRule());
131 if (epos == eposOld && epos < sb.length())
136 else if (!wrap.overRun && epos < sb.length())
142 w.write(sb.charAt(pos++));
144 if (epos == sb.length())
149 else if (pos > bufferSize)
151 for (int i = bufferSize; i < sb.length(); i++)
153 sb.setCharAt(i - bufferSize, sb.charAt(i));
157 sb.setLength(sb.length() - bufferSize);
161 public void write(char[] ca, int b, int n) throws IOException
164 for (int i = b; i < m; i++)
167 if (sb.length() % interval == interval - 1)
169 wrap.overRun = false;
170 while (epos + interval < sb.length() && !wrap.overRun)
178 public void flush() throws IOException
182 public void close() throws IOException
184 wrap.allowOverRun = false;
185 wrap.overRun = false;
186 while (epos < sb.length())
194 /** The current size of the StringBuffer in use by RegexWriter. */
200 /** The character at location i in the StringBuffer. */
201 public char charAt(int i)
206 /** Set the interval at which regex patterns are checked. */
207 public void setInterval(int i)
212 /** Get the interval at which regex matches are checked. */
213 public int getInterval()
218 /** Get the buffer size. */
219 public int getBufferSize()
224 /** Set the buffer size. */
225 public void setBufferSize(int i)
230 static void test(String re, String inp, int n) throws Exception
232 StringWriter sw = new StringWriter();
233 Regex rex = Regex.perlCode(re);
234 String res1 = rex.replaceAll(inp);
235 RegexWriter rw = new RegexWriter(rex, sw);
236 for (int i = 0; i < inp.length(); i++)
238 rw.write(inp.charAt(i));
241 String res2 = sw.toString();
242 if (!res1.equals(res2))
244 System.out.println("nmax=" + n);
245 System.out.println("re=" + re);
246 System.out.println("inp=" + inp);
247 System.out.println("res1=" + res1);
248 System.out.println("res2=" + res2);
253 public static void main(String[] args) throws Exception
255 for (int n = 1; n <= 1; n++)
257 test("s/x/y/", "-----x123456789", n);
258 test("s/x/y/", "x123456789", n);
259 test("s/x/y/", "-----x", n);
260 test("s/x.*?x/y/", ".xx..x..x...x...x....x....x", n);
261 test("s/x.*x/[$&]/", "--x........x--xx", n);
262 test("s/x.*x/[$&]/", "--x........x------", n);
263 test("s/.$/a/m", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb", n);
264 test("s/.$/a/", "123", n);
265 test("s/.$/a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n);
266 test("s/^./a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n);
267 test("s/$/a/", "bbb", n);
268 test("s/^/a/", "bbb", n);
269 test("s/^/a/", "", n);
270 test("s{.*}{N}", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", n);
271 test("s/.{0,7}/y/", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", n);
272 test("s/x/$&/", "xxx", n);
274 System.out.println("Success!!!");