2 // This software is now distributed according to
\r
3 // the Lesser Gnu Public License. Please see
\r
4 // http://www.gnu.org/copyleft/lesser.txt for
\r
6 // -- Happy Computing!
\r
8 package com.stevesoft.pat;
\r
12 import com.stevesoft.pat.wrap.*;
\r
14 /** A basic extension of FilterWriter that uses Transformer
\r
15 to make replacements in data as it is written out. It attempts
\r
16 to transform a string whenever the End-of-Line (EOL) character
\r
17 is written (which is, by default, the carriage return '\n').
\r
18 Only the transformed portion of the line is written out, allowing
\r
19 the RegexWriter to wait until a complete pattern is present before
\r
20 attempting to write out info. Until a pattern completes, data is
\r
21 stored in a StringBuffer -- which can be accessed through the
\r
22 length() and charAt() methods of this class.
\r
24 Note a subtlety here -- while a Transformer normally matches
\r
25 at higher priority against the pattern added to it first, this
\r
26 will not necessarily be true when a multi-line match is in progress
\r
27 because one of the complete multi-line patterns may not be completely
\r
28 loaded in RegexWriter's buffer. For this reason, the Transformer
\r
29 class is equipped with a way to add a pattern and replacement rule
\r
30 in three pieces -- a beginning (once this matches, nothing else in
\r
31 the Transformer can match until the whole pattern matches), an
\r
32 ending (the whole pattern is a String formed by adding the beginning
\r
33 and ending), and a ReplaceRule.
\r
35 An illustration of this is given in the this
\r
36 <a href="../test/trans.java">example.</a>
\r
38 public class RegexWriter
\r
44 StringBuffer sb = new StringBuffer();
\r
45 PartialBuffer wrap = new PartialBuffer(sb);
\r
48 int bufferSize = 2 * 1024;
\r
50 public RegexWriter(Transformer t, Writer w)
\r
53 ww = new WriterWrap(w);
\r
54 repr = t.getReplacer();
\r
55 repr.setBuffer(new StringBufferLike(ww));
\r
56 repr.setSource(wrap);
\r
59 public RegexWriter(Regex r, Writer w)
\r
62 ww = new WriterWrap(w);
\r
63 repr = r.getReplacer();
\r
64 repr.setBuffer(new StringBufferLike(ww));
\r
65 repr.setSource(wrap);
\r
68 char EOLchar = '\n';
\r
69 /** This method no longer serves any purpose.
\r
72 public char getEOLchar()
\r
77 /** This method no longer serves any purpose.
\r
80 public void setEOLchar(char c)
\r
86 /** This method no longer serves any purpose.
\r
89 public int getMaxLines()
\r
94 /** This method no longer serves any purpose.
\r
97 public void setMaxLines(int ml)
\r
105 Regex rex = repr.getRegex();
\r
106 int eposOld = epos;
\r
107 if (rex.matchAt(wrap, epos) && !wrap.overRun)
\r
111 w.write(sb.charAt(pos++));
\r
113 int to = rex.matchedTo();
\r
115 repr.apply(rex, rex.getReplaceRule());
\r
117 if (epos == eposOld && epos < sb.length())
\r
122 else if (!wrap.overRun && epos < sb.length())
\r
128 w.write(sb.charAt(pos++));
\r
130 if (epos == sb.length())
\r
135 else if (pos > bufferSize)
\r
137 for (int i = bufferSize; i < sb.length(); i++)
\r
139 sb.setCharAt(i - bufferSize, sb.charAt(i));
\r
142 epos -= bufferSize;
\r
143 sb.setLength(sb.length() - bufferSize);
\r
147 public void write(char[] ca, int b, int n)
\r
151 for (int i = b; i < m; i++)
\r
154 if (sb.length() % interval == interval - 1)
\r
156 wrap.overRun = false;
\r
157 while (epos + interval < sb.length() && !wrap.overRun)
\r
165 public void flush()
\r
170 public void close()
\r
173 wrap.allowOverRun = false;
\r
174 wrap.overRun = false;
\r
175 while (epos < sb.length())
\r
183 /** The current size of the StringBuffer in use by RegexWriter. */
\r
184 public int length()
\r
186 return sb.length();
\r
189 /** The character at location i in the StringBuffer. */
\r
190 public char charAt(int i)
\r
192 return sb.charAt(i);
\r
195 /** Set the interval at which regex patterns are checked. */
\r
196 public void setInterval(int i)
\r
201 /** Get the interval at which regex matches are checked. */
\r
202 public int getInterval()
\r
207 /** Get the buffer size. */
\r
208 public int getBufferSize()
\r
213 /** Set the buffer size. */
\r
214 public void setBufferSize(int i)
\r
219 static void test(String re, String inp, int n)
\r
222 StringWriter sw = new StringWriter();
\r
223 Regex rex = Regex.perlCode(re);
\r
224 String res1 = rex.replaceAll(inp);
\r
225 RegexWriter rw = new RegexWriter(rex, sw);
\r
226 for (int i = 0; i < inp.length(); i++)
\r
228 rw.write(inp.charAt(i));
\r
231 String res2 = sw.toString();
\r
232 if (!res1.equals(res2))
\r
234 System.out.println("nmax=" + n);
\r
235 System.out.println("re=" + re);
\r
236 System.out.println("inp=" + inp);
\r
237 System.out.println("res1=" + res1);
\r
238 System.out.println("res2=" + res2);
\r
243 public static void main(String[] args)
\r
246 for (int n = 1; n <= 1; n++)
\r
248 test("s/x/y/", "-----x123456789", n);
\r
249 test("s/x/y/", "x123456789", n);
\r
250 test("s/x/y/", "-----x", n);
\r
251 test("s/x.*?x/y/", ".xx..x..x...x...x....x....x", n);
\r
252 test("s/x.*x/[$&]/", "--x........x--xx", n);
\r
253 test("s/x.*x/[$&]/", "--x........x------", n);
\r
254 test("s/.$/a/m", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb", n);
\r
255 test("s/.$/a/", "123", n);
\r
256 test("s/.$/a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n);
\r
257 test("s/^./a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n);
\r
258 test("s/$/a/", "bbb", n);
\r
259 test("s/^/a/", "bbb", n);
\r
260 test("s/^/a/", "", n);
\r
261 test("s{.*}{N}", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", n);
\r
262 test("s/.{0,7}/y/", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", n);
\r
263 test("s/x/$&/", "xxx", n);
\r
265 System.out.println("Success!!!");
\r