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