// // This software is now distributed according to // the Lesser Gnu Public License. Please see // http://www.gnu.org/copyleft/lesser.txt for // the details. // -- Happy Computing! // package com.stevesoft.ewe_pat; import ewe.io.*; import com.stevesoft.ewe_pat.wrap.*; /** A basic extension of FilterWriter that uses Transformer to make replacements in data as it is written out. It attempts to transform a string whenever the End-of-Line (EOL) character is written (which is, by default, the carriage return '\n'). Only the transformed portion of the line is written out, allowing the RegexWriter to wait until a complete pattern is present before attempting to write out info. Until a pattern completes, data is stored in a StringBuffer -- which can be accessed through the length() and charAt() methods of this class. <p> Note a subtlety here -- while a Transformer normally matches at higher priority against the pattern added to it first, this will not necessarily be true when a multi-line match is in progress because one of the complete multi-line patterns may not be completely loaded in RegexWriter's buffer. For this reason, the Transformer class is equipped with a way to add a pattern and replacement rule in three pieces -- a beginning (once this matches, nothing else in the Transformer can match until the whole pattern matches), an ending (the whole pattern is a String formed by adding the beginning and ending), and a ReplaceRule. <p> An illustration of this is given in the this <a href="../test/trans.java">example.</a> */ public class RegexWriter extends Writer { Replacer repr; Writer w; WriterWrap ww; StringBuffer sb = new StringBuffer(); PartialBuffer wrap = new PartialBuffer(sb); int pos, epos; int interval = 128; int bufferSize = 2*1024; public RegexWriter(Transformer t,Writer w) { this.w = w; ww = new WriterWrap(w); repr = t.getReplacer(); repr.setBuffer(new StringBufferLike(ww)); repr.setSource(wrap); } public RegexWriter(Regex r,Writer w) { this.w = w; ww = new WriterWrap(w); repr = r.getReplacer(); repr.setBuffer(new StringBufferLike(ww)); repr.setSource(wrap); } char EOLchar = '\n'; /** This method no longer serves any purpose. @deprecated */ public char getEOLchar() { return EOLchar; } /** This method no longer serves any purpose. @deprecated */ public void setEOLchar(char c) { EOLchar = c; } int max_lines=2; /** This method no longer serves any purpose. @deprecated */ public int getMaxLines() { return max_lines; } /** This method no longer serves any purpose. @deprecated */ public void setMaxLines(int ml) { max_lines = ml; } void write() throws IOException { Regex rex = repr.getRegex(); int eposOld = epos; if(rex.matchAt(wrap,epos) && !wrap.overRun) { while(pos < epos) w.write(sb.charAt(pos++)); int to = rex.matchedTo(); repr.setPos(to); repr.apply(rex,rex.getReplaceRule()); epos = pos = to; if(epos == eposOld && epos < sb.length()) epos++; } else if(!wrap.overRun && epos < sb.length()) { epos++; } while(pos < epos) w.write(sb.charAt(pos++)); if(epos == sb.length()) { sb.setLength(1); pos = epos = 1; } else if(pos > bufferSize) { for(int i=bufferSize;i<sb.length();i++) sb.setCharAt(i-bufferSize,sb.charAt(i)); pos -= bufferSize; epos -= bufferSize; sb.setLength(sb.length()-bufferSize); } } public void write(char[] ca,int b,int n) throws IOException { int m = b+n; for(int i=b;i<m;i++) { sb.append(ca[i]); if(sb.length() % interval == interval - 1) { wrap.overRun = false; while(epos+interval < sb.length() && !wrap.overRun) { write(); } } } } public void flush() throws IOException { } public void close() throws IOException { wrap.allowOverRun = false; wrap.overRun = false; while(epos < sb.length()) write(); write(); w.close(); } /** The current size of the StringBuffer in use by RegexWriter. */ public int length() { return sb.length(); } /** The character at location i in the StringBuffer. */ public char charAt(int i) { return sb.charAt(i); } /** Set the interval at which regex patterns are checked. */ public void setInterval(int i) { interval = i; } /** Get the interval at which regex matches are checked. */ public int getInterval() { return interval; } /** Get the buffer size. */ public int getBufferSize() { return bufferSize; } /** Set the buffer size. */ public void setBufferSize(int i) { bufferSize = i; } static void test(String re,String inp,int n) throws Exception { StringWriter sw = new StringWriter(); Regex rex = Regex.perlCode(re); String res1 = rex.replaceAll(inp); RegexWriter rw = new RegexWriter(rex,sw); for(int i=0;i<inp.length();i++) rw.write(inp.charAt(i)); rw.close(); String res2 = sw.toString(); if(!res1.equals(res2)) { ewe.sys.Vm.out().println("nmax="+n); ewe.sys.Vm.out().println("re="+re); ewe.sys.Vm.out().println("inp="+inp); ewe.sys.Vm.out().println("res1="+res1); ewe.sys.Vm.out().println("res2="+res2); System.exit(255); } } public static void main(String[] args) throws Exception { for(int n=1;n<=1;n++) { test("s/x/y/","-----x123456789",n); test("s/x/y/","x123456789",n); test("s/x/y/","-----x",n); test("s/x.*?x/y/",".xx..x..x...x...x....x....x",n); test("s/x.*x/[$&]/","--x........x--xx",n); test("s/x.*x/[$&]/","--x........x------",n); test("s/.$/a/m","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb",n); test("s/.$/a/","123",n); test("s/.$/a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n); test("s/^./a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n); test("s/$/a/","bbb",n); test("s/^/a/","bbb",n); test("s/^/a/","",n); test("s{.*}{N}","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",n); test("s/.{0,7}/y/","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",n); test("s/x/$&/","xxx",n); } ewe.sys.Vm.out().println("Success!!!"); } }