merge from 2_4_Release branch
[jalview.git] / src / com / stevesoft / pat / Replacer.java
index bdeea39..062a548 100755 (executable)
-//\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 com.stevesoft.pat.wrap.StringWrap;\r
-\r
-/** Internally used class. */\r
-class RegHolder {\r
-    Regex me = null;\r
-    RegHolder prev = null;\r
-}\r
-\r
-/** Internally used class.\r
-  * @see CodeRule\r
-  */\r
-class CodeVal {\r
-    int pos;\r
-    char code;\r
-    CodeVal(int p,char c) {\r
-        pos = p;\r
-        code = c;\r
-    }\r
-    public String toString() {\r
-        return "("+pos+","+code+")";\r
-    }\r
-}\r
-\r
-/**\r
-  To use this class, first use either the getReplacer() method from\r
-  Transformer or Regex.  You can then use replaceAll, replaceFirst,\r
-  etc. methods on the Replacer in the same way that you can from\r
-  either of those two classes.\r
-  <p>\r
-  The only potential difference between using the methods of\r
-  Replacer to do the replacing is that Replacer remembers changes\r
-  to the replacing object between calls to replaceAll, replaceFirst\r
-  etc.  For details, see the example file\r
-  <a href="http://javaregex.com/code/trans3.java.html">trans3.java</a>.\r
-  @see com.stevesoft.pat.Transformer\r
-  @see com.stevesoft.pat.Regex\r
-*/\r
-public class Replacer {\r
-    boolean first;\r
-\r
-    /** Instantiate a new Replacer. */\r
-    public Replacer() {}\r
-\r
-    public StringLike replaceFirstRegion(String s,Regex r,\r
-        int start,int end) {\r
-        return replaceFirstRegion(new StringWrap(s),r,start,end);\r
-    }\r
-    /** This method replaces the first occurence of the Regex in the\r
-        String starting with position pos\r
-        according to the Replacer rule of this object. */\r
-    public StringLike replaceFirstRegion(StringLike s,Regex r,\r
-        int start,int end) {\r
-        first = true;\r
-        rh.me = r;\r
-        rh.prev = null;\r
-        return dorep(s,start,end);\r
-    }\r
-    public StringLike replaceFirst(StringLike s) {\r
-        return replaceFirstRegion(s,0,s.length());\r
-    }\r
-    public StringLike replaceFirstFrom(StringLike s,int start) {\r
-        return replaceFirstRegion(s,start,s.length());\r
-    }\r
-    public StringLike replaceFirstRegion(StringLike s,int start,int end) {\r
-        first = true;\r
-        return dorep(s,start,end);\r
-    }\r
-\r
-    RegHolder rh = new RegHolder();\r
-\r
-    public StringLike replaceAllRegion(String s,Regex r,\r
-        int start, int end) {\r
-        return replaceAllRegion(new StringWrap(s),r,start,end);\r
-    }\r
-    /** This method replaces all occurences of the Regex in the\r
-        String starting with postition pos\r
-        according to the Replacer rule of this object. */\r
-    public StringLike replaceAllRegion(StringLike s,Regex r,\r
-        int start,int end) {\r
-        first = false;\r
-        // reset\r
-        rh.me = r;\r
-        rh.prev = null;\r
-        return dorep(s,start,end);\r
-    }\r
-    public StringLike replaceAll(StringLike s) {\r
-        return replaceAllRegion(s,0,s.length());\r
-    }\r
-    public StringLike replaceAllFrom(StringLike s,int start) {\r
-        return replaceAllRegion(s,start,s.length());\r
-    }\r
-    public StringLike replaceAllRegion(StringLike s,int start,int end) {\r
-        first = false;\r
-        return dorep(s,start,end);\r
-    }\r
-\r
-    public String replaceAll(String s) {\r
-        return replaceAllRegion(new StringWrap(s),0,s.length()).toString();\r
-    }\r
-    public String replaceAllFrom(String s,int start) {\r
-        return replaceAllRegion(new StringWrap(s),start,s.length()).toString();\r
-    }\r
-    public String replaceAllRegion(String s,int start,int end) {\r
-        first = false;\r
-        return dorep(new StringWrap(s),start,end).toString();\r
-    }\r
-\r
-    final public boolean isSpecial(ReplaceRule x) {\r
-        while(x != null) {\r
-            if(x instanceof SpecialRule\r
-                    || (x instanceof RuleHolder && ((RuleHolder)x).held instanceof SpecialRule))\r
-                return true;\r
-            x = x.next;\r
-        }\r
-        return false;\r
-    }\r
-    final public void apply1(RegRes rr) {\r
-        rr.charsMatched_++;\r
-        apply(rr,null);\r
-        rr.charsMatched_--;\r
-    }\r
-\r
-    final StringLike dorep(StringLike s,int start,int end) {\r
-        StringLike ret = s;\r
-        want_more_text = false;\r
-        lastMatchedTo = 0;\r
-        if(rh.me == null)\r
-            throw new NullPointerException("Replacer has null Regex pointer");\r
-        if(rh.me._search(s,start,end)) {\r
-            int rmn = rh.me.matchedTo();\r
-            if(rh.me.charsMatched()==0 && !isSpecial(rh.me.getReplaceRule())) {\r
-                apply1(rh.me);\r
-                rmn++;\r
-            }\r
-            apply(rh.me);\r
-            if(!first)\r
-                for(int i=rmn;\r
-                        !want_more_text && rh.me._search(s,i,end);i=rmn) {\r
-                    rmn = rh.me.matchedTo();\r
-                    if(rh.me.charsMatched()==0) {\r
-                        if(!isSpecial(rh.me.getReplaceRule()))\r
-                            apply1(rh.me);\r
-                        rmn++;\r
-                    }\r
-                    apply(rh.me);\r
-                }\r
-            ret = finish();\r
-            ret = ret == null ? s : ret;\r
-        }\r
-        return ret;\r
-    }\r
-\r
-    StringBufferLike sb = null;\r
-    StringLike src = null;\r
-    int pos = 0;\r
-    /** This method allows you to apply the results of several\r
-        matches in a sequence to modify a String of text.  Each\r
-        call in the sequence must operate on the same piece of\r
-        text and the matchedFrom() of each RegRes given to this\r
-        method must be greater in value than the preceeding\r
-        RegRes's matchedTo() value.\r
-        */\r
-    public void apply(RegRes r,ReplaceRule rp) {\r
-        if(rp==null ||(rp.next == null && rp instanceof AmpersandRule))\r
-            return;\r
-        if(r.didMatch()) {\r
-            if(src == null)\r
-                src = r.getStringLike();\r
-           if(sb == null)\r
-                sb = new StringBufferLike(src.newStringBufferLike());\r
-            int rmf = r.matchedFrom();\r
-            for(int ii=pos;ii<rmf;ii++)\r
-              sb.append(src.charAt(ii));\r
-\r
-            for(ReplaceRule x=rp;x != null;x=x.next) {\r
-                x.apply(sb,r);\r
-                if(x instanceof SpecialRule) {\r
-                    if(x instanceof WantMoreTextReplaceRule\r
-                            && want_more_text_enable)\r
-                        want_more_text = true;\r
-                    else if(x instanceof PushRule) {\r
-                        RegHolder rh2 = new RegHolder();\r
-                        rh2.me = ( (PushRule)x ).NewRule;\r
-                        rh2.prev = rh;\r
-                        rh = rh2;\r
-                    } else if(x instanceof PopRule) {\r
-                        if(rh.prev != null)\r
-                            rh = rh.prev;\r
-                    } else if(x instanceof ChangeRule) {\r
-                        rh.me = ( (ChangeRule) x).NewRule;\r
-                    }\r
-                }\r
-            }\r
-            if(!want_more_text)\r
-                pos = r.matchedTo();\r
-        }\r
-    }\r
-    boolean want_more_text = false, want_more_text_enable = false;\r
-    public boolean WantMoreText() { return want_more_text; }\r
-    /** Another form of apply, it is the same as\r
-        apply(r,r.getReplaceRule()). */\r
-    public void apply(Regex r) { apply(r,r.getReplaceRule()); }\r
-\r
-    /** This finishes the replacement, appending the right() part of\r
-        the last RegRes given to substitute(RegRes).  After this method\r
-        is called, the Replace object is reset to perform another\r
-        substitution. If no RegRes objects with a true didMatch are\r
-        applied, this returns null. */\r
-    public StringLike finish() {\r
-        if(src==null)\r
-            return null;\r
-        //sb.append(src.substring(pos,src.length()));\r
-        int s_end = src.length();\r
-        for(int ii=pos;ii<s_end;ii++)\r
-          sb.append(src.charAt(ii));\r
-        src = null;\r
-        lastMatchedTo = pos;\r
-        pos = 0;\r
-        StringLike retstr = sb.toStringLike();\r
-        sb = null;\r
-        return retstr;\r
-    }\r
-    int lastMatchedTo = 0;\r
-    public Object clone() {\r
-        Replacer r = new Replacer();\r
-        r.first = first;\r
-        r.src = src;\r
-        r.sb = sb;\r
-        r.pos = pos;\r
-        r.lastMatchedTo = lastMatchedTo;\r
-        r.want_more_text = want_more_text;\r
-        r.want_more_text_enable = want_more_text_enable;\r
-        r.rh.me = rh.me;\r
-        r.rh.prev = rh.prev;\r
-        return r;\r
-    }\r
-    public int lastMatchedTo() { return lastMatchedTo; }\r
-    public Regex getRegex() {\r
-      return rh.me;\r
-    }\r
-    public void setSource(StringLike sl) {\r
-      src = sl;\r
-    }\r
-    public void setBuffer(StringBufferLike sbl) {\r
-      sb = sbl;\r
-    }\r
-    public void setPos(int pos) {\r
-      this.pos = pos;\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 com.stevesoft.pat.wrap.*;
+
+/** Internally used class. */
+class RegHolder
+{
+  Regex me = null;
+
+  RegHolder prev = null;
+}
+
+/**
+ * Internally used class.
+ * 
+ * @see CodeRule
+ */
+class CodeVal
+{
+  int pos;
+
+  char code;
+
+  CodeVal(int p, char c)
+  {
+    pos = p;
+    code = c;
+  }
+
+  public String toString()
+  {
+    return "(" + pos + "," + code + ")";
+  }
+}
+
+/**
+ * To use this class, first use either the getReplacer() method from Transformer
+ * or Regex. You can then use replaceAll, replaceFirst, etc. methods on the
+ * Replacer in the same way that you can from either of those two classes.
+ * <p>
+ * The only potential difference between using the methods of Replacer to do the
+ * replacing is that Replacer remembers changes to the replacing object between
+ * calls to replaceAll, replaceFirst etc. For details, see the example file <a
+ * href="http://javaregex.com/code/trans3.java.html">trans3.java</a>.
+ * 
+ * @see com.stevesoft.pat.Transformer
+ * @see com.stevesoft.pat.Regex
+ */
+public class Replacer
+{
+  boolean first;
+
+  /** Instantiate a new Replacer. */
+  public Replacer()
+  {
+  }
+
+  public StringLike replaceFirstRegion(String s, Regex r, int start, int end)
+  {
+    return replaceFirstRegion(new StringWrap(s), r, start, end);
+  }
+
+  /**
+   * This method replaces the first occurence of the Regex in the String
+   * starting with position pos according to the Replacer rule of this object.
+   */
+  public StringLike replaceFirstRegion(StringLike s, Regex r, int start,
+          int end)
+  {
+    first = true;
+    rh.me = r;
+    rh.prev = null;
+    return dorep(s, start, end);
+  }
+
+  public StringLike replaceFirst(StringLike s)
+  {
+    return replaceFirstRegion(s, 0, s.length());
+  }
+
+  public StringLike replaceFirstFrom(StringLike s, int start)
+  {
+    return replaceFirstRegion(s, start, s.length());
+  }
+
+  public StringLike replaceFirstRegion(StringLike s, int start, int end)
+  {
+    first = true;
+    return dorep(s, start, end);
+  }
+
+  RegHolder rh = new RegHolder();
+
+  public StringLike replaceAllRegion(String s, Regex r, int start, int end)
+  {
+    return replaceAllRegion(new StringWrap(s), r, start, end);
+  }
+
+  /**
+   * This method replaces all occurences of the Regex in the String starting
+   * with postition pos according to the Replacer rule of this object.
+   */
+  public StringLike replaceAllRegion(StringLike s, Regex r, int start,
+          int end)
+  {
+    first = false;
+    // reset
+    rh.me = r;
+    rh.prev = null;
+    return dorep(s, start, end);
+  }
+
+  public StringLike replaceAll(StringLike s)
+  {
+    return replaceAllRegion(s, 0, s.length());
+  }
+
+  public StringLike replaceAllFrom(StringLike s, int start)
+  {
+    return replaceAllRegion(s, start, s.length());
+  }
+
+  public StringLike replaceAllRegion(StringLike s, int start, int end)
+  {
+    first = false;
+    return dorep(s, start, end);
+  }
+
+  public String replaceAll(String s)
+  {
+    return replaceAllRegion(new StringWrap(s), 0, s.length()).toString();
+  }
+
+  public String replaceAllFrom(String s, int start)
+  {
+    return replaceAllRegion(new StringWrap(s), start, s.length())
+            .toString();
+  }
+
+  public String replaceAllRegion(String s, int start, int end)
+  {
+    first = false;
+    return dorep(new StringWrap(s), start, end).toString();
+  }
+
+  final public boolean isSpecial(ReplaceRule x)
+  {
+    while (x != null)
+    {
+      if (x instanceof SpecialRule
+              || (x instanceof RuleHolder && ((RuleHolder) x).held instanceof SpecialRule))
+      {
+        return true;
+      }
+      x = x.next;
+    }
+    return false;
+  }
+
+  final public void apply1(RegRes rr)
+  {
+    rr.charsMatched_++;
+    apply(rr, null);
+    rr.charsMatched_--;
+  }
+
+  final StringLike dorep(StringLike s, int start, int end)
+  {
+    StringLike ret = s;
+    want_more_text = false;
+    lastMatchedTo = 0;
+    if (rh.me == null)
+    {
+      throw new NullPointerException("Replacer has null Regex pointer");
+    }
+    if (rh.me._search(s, start, end))
+    {
+      int rmn = rh.me.matchedTo();
+      if (rh.me.charsMatched() == 0 && !isSpecial(rh.me.getReplaceRule()))
+      {
+        apply1(rh.me);
+        rmn++;
+      }
+      apply(rh.me);
+      if (!first)
+      {
+        for (int i = rmn; !want_more_text && rh.me._search(s, i, end); i = rmn)
+        {
+          rmn = rh.me.matchedTo();
+          if (rh.me.charsMatched() == 0)
+          {
+            if (!isSpecial(rh.me.getReplaceRule()))
+            {
+              apply1(rh.me);
+            }
+            rmn++;
+          }
+          apply(rh.me);
+        }
+      }
+      ret = finish();
+      ret = ret == null ? s : ret;
+    }
+    return ret;
+  }
+
+  StringBufferLike sb = null;
+
+  StringLike src = null;
+
+  int pos = 0;
+
+  /**
+   * This method allows you to apply the results of several matches in a
+   * sequence to modify a String of text. Each call in the sequence must operate
+   * on the same piece of text and the matchedFrom() of each RegRes given to
+   * this method must be greater in value than the preceeding RegRes's
+   * matchedTo() value.
+   */
+  public void apply(RegRes r, ReplaceRule rp)
+  {
+    if (rp == null || (rp.next == null && rp instanceof AmpersandRule))
+    {
+      return;
+    }
+    if (r.didMatch())
+    {
+      if (src == null)
+      {
+        src = r.getStringLike();
+      }
+      if (sb == null)
+      {
+        sb = new StringBufferLike(src.newStringBufferLike());
+      }
+      int rmf = r.matchedFrom();
+      for (int ii = pos; ii < rmf; ii++)
+      {
+        sb.append(src.charAt(ii));
+      }
+
+      for (ReplaceRule x = rp; x != null; x = x.next)
+      {
+        x.apply(sb, r);
+        if (x instanceof SpecialRule)
+        {
+          if (x instanceof WantMoreTextReplaceRule && want_more_text_enable)
+          {
+            want_more_text = true;
+          }
+          else if (x instanceof PushRule)
+          {
+            RegHolder rh2 = new RegHolder();
+            rh2.me = ((PushRule) x).NewRule;
+            rh2.prev = rh;
+            rh = rh2;
+          }
+          else if (x instanceof PopRule)
+          {
+            if (rh.prev != null)
+            {
+              rh = rh.prev;
+            }
+          }
+          else if (x instanceof ChangeRule)
+          {
+            rh.me = ((ChangeRule) x).NewRule;
+          }
+        }
+      }
+      if (!want_more_text)
+      {
+        pos = r.matchedTo();
+      }
+    }
+  }
+
+  boolean want_more_text = false, want_more_text_enable = false;
+
+  public boolean WantMoreText()
+  {
+    return want_more_text;
+  }
+
+  /**
+   * Another form of apply, it is the same as apply(r,r.getReplaceRule()).
+   */
+  public void apply(Regex r)
+  {
+    apply(r, r.getReplaceRule());
+  }
+
+  /**
+   * This finishes the replacement, appending the right() part of the last
+   * RegRes given to substitute(RegRes). After this method is called, the
+   * Replace object is reset to perform another substitution. If no RegRes
+   * objects with a true didMatch are applied, this returns null.
+   */
+  public StringLike finish()
+  {
+    if (src == null)
+    {
+      return null;
+    }
+    // sb.append(src.substring(pos,src.length()));
+    int s_end = src.length();
+    for (int ii = pos; ii < s_end; ii++)
+    {
+      sb.append(src.charAt(ii));
+    }
+    src = null;
+    lastMatchedTo = pos;
+    pos = 0;
+    StringLike retstr = sb.toStringLike();
+    sb = null;
+    return retstr;
+  }
+
+  int lastMatchedTo = 0;
+
+  public Object clone()
+  {
+    Replacer r = new Replacer();
+    r.first = first;
+    r.src = src;
+    r.sb = sb;
+    r.pos = pos;
+    r.lastMatchedTo = lastMatchedTo;
+    r.want_more_text = want_more_text;
+    r.want_more_text_enable = want_more_text_enable;
+    r.rh.me = rh.me;
+    r.rh.prev = rh.prev;
+    return r;
+  }
+
+  public int lastMatchedTo()
+  {
+    return lastMatchedTo;
+  }
+
+  public Regex getRegex()
+  {
+    return rh.me;
+  }
+
+  public void setSource(StringLike sl)
+  {
+    src = sl;
+  }
+
+  public void setBuffer(StringBufferLike sbl)
+  {
+    sb = sbl;
+  }
+
+  public void setPos(int pos)
+  {
+    this.pos = pos;
+  }
+}