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
11 import com.stevesoft.pat.wrap.*;
\r
13 /** A basic extension of FilterWriter that uses Transformer
\r
14 to make replacements in data as it is written out. It attempts
\r
15 to transform a string whenever the End-of-Line (EOL) character
\r
16 is written (which is, by default, the carriage return '\n').
\r
17 Only the transformed portion of the line is written out, allowing
\r
18 the RegexWriter to wait until a complete pattern is present before
\r
19 attempting to write out info. Until a pattern completes, data is
\r
20 stored in a StringBuffer -- which can be accessed through the
\r
21 length() and charAt() methods of this class.
\r
23 Note a subtlety here -- while a Transformer normally matches
\r
24 at higher priority against the pattern added to it first, this
\r
25 will not necessarily be true when a multi-line match is in progress
\r
26 because one of the complete multi-line patterns may not be completely
\r
27 loaded in RegexWriter's buffer. For this reason, the Transformer
\r
28 class is equipped with a way to add a pattern and replacement rule
\r
29 in three pieces -- a beginning (once this matches, nothing else in
\r
30 the Transformer can match until the whole pattern matches), an
\r
31 ending (the whole pattern is a String formed by adding the beginning
\r
32 and ending), and a ReplaceRule.
\r
34 An illustration of this is given in the this
\r
35 <a href="../test/trans.java">example.</a>
\r
37 public class RegexWriter extends Writer {
\r
41 StringBuffer sb = new StringBuffer();
\r
42 PartialBuffer wrap = new PartialBuffer(sb);
\r
45 int bufferSize = 2*1024;
\r
47 public RegexWriter(Transformer t,Writer w) {
\r
49 ww = new WriterWrap(w);
\r
50 repr = t.getReplacer();
\r
51 repr.setBuffer(new StringBufferLike(ww));
\r
52 repr.setSource(wrap);
\r
54 public RegexWriter(Regex r,Writer w) {
\r
56 ww = new WriterWrap(w);
\r
57 repr = r.getReplacer();
\r
58 repr.setBuffer(new StringBufferLike(ww));
\r
59 repr.setSource(wrap);
\r
62 char EOLchar = '\n';
\r
63 /** This method no longer serves any purpose.
\r
66 public char getEOLchar() {
\r
69 /** This method no longer serves any purpose.
\r
72 public void setEOLchar(char c) {
\r
77 /** This method no longer serves any purpose.
\r
80 public int getMaxLines() { return max_lines; }
\r
81 /** This method no longer serves any purpose.
\r
84 public void setMaxLines(int ml) { max_lines = ml; }
\r
86 void write() throws IOException {
\r
87 Regex rex = repr.getRegex();
\r
89 if(rex.matchAt(wrap,epos) && !wrap.overRun) {
\r
91 w.write(sb.charAt(pos++));
\r
92 int to = rex.matchedTo();
\r
94 repr.apply(rex,rex.getReplaceRule());
\r
96 if(epos == eposOld && epos < sb.length())
\r
98 } else if(!wrap.overRun && epos < sb.length()) {
\r
102 w.write(sb.charAt(pos++));
\r
103 if(epos == sb.length()) {
\r
106 } else if(pos > bufferSize) {
\r
107 for(int i=bufferSize;i<sb.length();i++)
\r
108 sb.setCharAt(i-bufferSize,sb.charAt(i));
\r
110 epos -= bufferSize;
\r
111 sb.setLength(sb.length()-bufferSize);
\r
115 public void write(char[] ca,int b,int n) throws IOException {
\r
117 for(int i=b;i<m;i++) {
\r
119 if(sb.length() % interval == interval - 1) {
\r
120 wrap.overRun = false;
\r
121 while(epos+interval < sb.length() && !wrap.overRun) {
\r
128 public void flush() throws IOException {
\r
131 public void close() throws IOException {
\r
132 wrap.allowOverRun = false;
\r
133 wrap.overRun = false;
\r
134 while(epos < sb.length())
\r
140 /** The current size of the StringBuffer in use by RegexWriter. */
\r
141 public int length() { return sb.length(); }
\r
143 /** The character at location i in the StringBuffer. */
\r
144 public char charAt(int i) { return sb.charAt(i); }
\r
146 /** Set the interval at which regex patterns are checked. */
\r
147 public void setInterval(int i) {
\r
151 /** Get the interval at which regex matches are checked. */
\r
152 public int getInterval() {
\r
156 /** Get the buffer size. */
\r
157 public int getBufferSize() {
\r
161 /** Set the buffer size. */
\r
162 public void setBufferSize(int i) {
\r
166 static void test(String re,String inp,int n) throws Exception {
\r
167 StringWriter sw = new StringWriter();
\r
168 Regex rex = Regex.perlCode(re);
\r
169 String res1 = rex.replaceAll(inp);
\r
170 RegexWriter rw = new RegexWriter(rex,sw);
\r
171 for(int i=0;i<inp.length();i++)
\r
172 rw.write(inp.charAt(i));
\r
174 String res2 = sw.toString();
\r
175 if(!res1.equals(res2)) {
\r
176 System.out.println("nmax="+n);
\r
177 System.out.println("re="+re);
\r
178 System.out.println("inp="+inp);
\r
179 System.out.println("res1="+res1);
\r
180 System.out.println("res2="+res2);
\r
184 public static void main(String[] args) throws Exception {
\r
185 for(int n=1;n<=1;n++) {
\r
186 test("s/x/y/","-----x123456789",n);
\r
187 test("s/x/y/","x123456789",n);
\r
188 test("s/x/y/","-----x",n);
\r
189 test("s/x.*?x/y/",".xx..x..x...x...x....x....x",n);
\r
190 test("s/x.*x/[$&]/","--x........x--xx",n);
\r
191 test("s/x.*x/[$&]/","--x........x------",n);
\r
192 test("s/.$/a/m","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb",n);
\r
193 test("s/.$/a/","123",n);
\r
194 test("s/.$/a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);
\r
195 test("s/^./a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);
\r
196 test("s/$/a/","bbb",n);
\r
197 test("s/^/a/","bbb",n);
\r
198 test("s/^/a/","",n);
\r
199 test("s{.*}{N}","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",n);
\r
200 test("s/.{0,7}/y/","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",n);
\r
201 test("s/x/$&/","xxx",n);
\r
203 System.out.println("Success!!!");
\r