merge from 2_4_Release branch
[jalview.git] / src / com / stevesoft / pat / Skip.java
index 16aada1..d3f3822 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
-/** This class is used internally to search ahead for some\r
-    optimized Regex objects.  It searches within a String\r
-    for occrences of a given String -- like a more flexible\r
-    version of String.indexOf.\r
-    @see com.stevesoft.pat.Skip2\r
-    @see com.stevesoft.pat.SkipBMH\r
- */\r
-public class Skip\r
-{\r
-  static int mkmask(int c)\r
-  {\r
-    char x = (char) c;\r
-    return~ (CaseMgr.toUpperCase(x) |\r
-             CaseMgr.toLowerCase(x) |\r
-             CaseMgr.toTitleCase(x));\r
-  }\r
-\r
-  String src;\r
-  int c, mask;\r
-  int offset;\r
-  boolean ign, m1;\r
-  /** Examine a Regex to determine what String it will\r
-      attempt to skip to when searching for patterns.\r
-      Return -1 if we aren't doing this. */\r
-  public static String string(Regex r)\r
-  {\r
-    return r.skipper == null ? null : r.skipper.src;\r
-  }\r
-\r
-  /** Determine the offset of the String within the pattern\r
-      that we are skipping to. Return -1 if we aren't doing\r
-      this.  */\r
-  public static int offset(Regex r)\r
-  {\r
-    return r.skipper == null ? -1 : r.skipper.offset;\r
-  }\r
-\r
-  /** Initialize, give it a String to search for, tell it\r
-      whether or not to ignoreCase, and what the offset is\r
-      of the String within the String to be searched. */\r
-  public Skip(String s, boolean ign, int o)\r
-  {\r
-    src = s;\r
-    c = s.charAt(0);\r
-    if (ign)\r
-    {\r
-      mask = mkmask(c);\r
-    }\r
-    else\r
-    {\r
-      mask = 0;\r
-    }\r
-    offset = o;\r
-    this.ign = ign;\r
-    m1 = (s.length() == 1);\r
-  }\r
-\r
-  /** The same as find(s,0,s.length()) */\r
-  public final int find(StringLike s)\r
-  {\r
-    return find(s, 0, s.length());\r
-  }\r
-\r
-  static final int min(int a, int b)\r
-  {\r
-    return a < b ? a : b;\r
-  }\r
-\r
-  /** Searches a given region of text beginning at position start\r
-      and ending at position end for the skip object. */\r
-  public int find(StringLike s, int start, int end)\r
-  {\r
-    if (start > end)\r
-    {\r
-      return -1;\r
-    }\r
-    start += offset;\r
-    int vend = min(s.length() - 1, end + offset);\r
-    if (mask != c)\r
-    {\r
-      for (int i = start; i <= vend; i++)\r
-      {\r
-        if (0 == (s.charAt(i) & mask))\r
-        {\r
-          //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
-          if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length()))\r
-          {\r
-            return i - offset;\r
-          }\r
-        }\r
-      }\r
-    }\r
-    else\r
-    {\r
-      for (int i = start; i <= vend; i++)\r
-      {\r
-        if (c == s.charAt(i))\r
-        {\r
-          //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
-          if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length()))\r
-          {\r
-            return i - offset;\r
-          }\r
-        }\r
-      }\r
-    }\r
-    return -1;\r
-  }\r
-\r
-  static Skip findSkip(Regex r)\r
-  {\r
-    return findSkip(r.thePattern, r.ignoreCase, !r.dontMatchInQuotes);\r
-  }\r
-\r
-  // look for things that can be skipped\r
-  static Skip findSkip(Pattern p, boolean ignoreCase, boolean trnc)\r
-  {\r
-    StringBuffer sb = new StringBuffer();\r
-    Skip subsk = null;\r
-    int offset = 0;\r
-    int skipc = -1, skipoff = 0;\r
-    for (; p != null; p = p.next)\r
-    {\r
-      if (p instanceof oneChar)\r
-      {\r
-        skipc = ( (oneChar) p).c;\r
-        skipoff = offset;\r
-      }\r
-      if (p instanceof oneChar && p.next instanceof oneChar)\r
-      {\r
-        Pattern psav = p;\r
-        sb.append( ( (oneChar) p).c);\r
-        while (p.next instanceof oneChar)\r
-        {\r
-          sb.append( ( (oneChar) p.next).c);\r
-          p = p.next;\r
-        }\r
-        String st = sb.toString();\r
-        Skip sk = null;\r
-        if (st.length() > 2)\r
-        {\r
-          sk = new SkipBMH(st, ignoreCase, offset);\r
-        }\r
-        else\r
-        {\r
-          sk = new Skip2(st, ignoreCase, offset);\r
-        }\r
-        if (trnc && st.length() > 2)\r
-        { // chop out a whole string...\r
-          psav.next = new Skipped(st.substring(1));\r
-          psav.next.next = p.next;\r
-          psav.next.parent = p.parent;\r
-        }\r
-        return sk;\r
-      }\r
-      else if (p instanceof Or && ( (Or) p).v.size() == 1\r
-               && ! ( (Or) p).leftForm().equals("(?!")\r
-               && null != (subsk =\r
-                           findSkip( (Pattern) ( (Or) p).v.elementAt(0),\r
-                                    ignoreCase, trnc)))\r
-      {\r
-        subsk.offset += offset;\r
-        return subsk;\r
-      }\r
-      else if (p.minChars().equals(p.maxChars()))\r
-      {\r
-        offset += p.minChars().intValue();\r
-      }\r
-      else\r
-      {\r
-        return skipc < 0 ? null :\r
-            new Skip("" + (char) skipc, ignoreCase, skipoff);\r
-      }\r
-    }\r
-    return null;\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;
+
+/**
+ * This class is used internally to search ahead for some optimized Regex
+ * objects. It searches within a String for occrences of a given String -- like
+ * a more flexible version of String.indexOf.
+ * 
+ * @see com.stevesoft.pat.Skip2
+ * @see com.stevesoft.pat.SkipBMH
+ */
+public class Skip
+{
+  static int mkmask(int c)
+  {
+    char x = (char) c;
+    return ~(CaseMgr.toUpperCase(x) | CaseMgr.toLowerCase(x) | CaseMgr
+            .toTitleCase(x));
+  }
+
+  String src;
+
+  int c, mask;
+
+  int offset;
+
+  boolean ign, m1;
+
+  /**
+   * Examine a Regex to determine what String it will attempt to skip to when
+   * searching for patterns. Return -1 if we aren't doing this.
+   */
+  public static String string(Regex r)
+  {
+    return r.skipper == null ? null : r.skipper.src;
+  }
+
+  /**
+   * Determine the offset of the String within the pattern that we are skipping
+   * to. Return -1 if we aren't doing this.
+   */
+  public static int offset(Regex r)
+  {
+    return r.skipper == null ? -1 : r.skipper.offset;
+  }
+
+  /**
+   * Initialize, give it a String to search for, tell it whether or not to
+   * ignoreCase, and what the offset is of the String within the String to be
+   * searched.
+   */
+  public Skip(String s, boolean ign, int o)
+  {
+    src = s;
+    c = s.charAt(0);
+    if (ign)
+    {
+      mask = mkmask(c);
+    }
+    else
+    {
+      mask = 0;
+    }
+    offset = o;
+    this.ign = ign;
+    m1 = (s.length() == 1);
+  }
+
+  /** The same as find(s,0,s.length()) */
+  public final int find(StringLike s)
+  {
+    return find(s, 0, s.length());
+  }
+
+  static final int min(int a, int b)
+  {
+    return a < b ? a : b;
+  }
+
+  /**
+   * Searches a given region of text beginning at position start and ending at
+   * position end for the skip object.
+   */
+  public int find(StringLike s, int start, int end)
+  {
+    if (start > end)
+    {
+      return -1;
+    }
+    start += offset;
+    int vend = min(s.length() - 1, end + offset);
+    if (mask != c)
+    {
+      for (int i = start; i <= vend; i++)
+      {
+        if (0 == (s.charAt(i) & mask))
+        {
+          // if(m1||s.regionMatches(ign,i,src,0,src.length()) )
+          if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length()))
+          {
+            return i - offset;
+          }
+        }
+      }
+    }
+    else
+    {
+      for (int i = start; i <= vend; i++)
+      {
+        if (c == s.charAt(i))
+        {
+          // if(m1||s.regionMatches(ign,i,src,0,src.length()) )
+          if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length()))
+          {
+            return i - offset;
+          }
+        }
+      }
+    }
+    return -1;
+  }
+
+  static Skip findSkip(Regex r)
+  {
+    return findSkip(r.thePattern, r.ignoreCase, !r.dontMatchInQuotes);
+  }
+
+  // look for things that can be skipped
+  static Skip findSkip(Pattern p, boolean ignoreCase, boolean trnc)
+  {
+    StringBuffer sb = new StringBuffer();
+    Skip subsk = null;
+    int offset = 0;
+    int skipc = -1, skipoff = 0;
+    for (; p != null; p = p.next)
+    {
+      if (p instanceof oneChar)
+      {
+        skipc = ((oneChar) p).c;
+        skipoff = offset;
+      }
+      if (p instanceof oneChar && p.next instanceof oneChar)
+      {
+        Pattern psav = p;
+        sb.append(((oneChar) p).c);
+        while (p.next instanceof oneChar)
+        {
+          sb.append(((oneChar) p.next).c);
+          p = p.next;
+        }
+        String st = sb.toString();
+        Skip sk = null;
+        if (st.length() > 2)
+        {
+          sk = new SkipBMH(st, ignoreCase, offset);
+        }
+        else
+        {
+          sk = new Skip2(st, ignoreCase, offset);
+        }
+        if (trnc && st.length() > 2)
+        { // chop out a whole string...
+          psav.next = new Skipped(st.substring(1));
+          psav.next.next = p.next;
+          psav.next.parent = p.parent;
+        }
+        return sk;
+      }
+      else if (p instanceof Or
+              && ((Or) p).v.size() == 1
+              && !((Or) p).leftForm().equals("(?!")
+              && null != (subsk = findSkip((Pattern) ((Or) p).v
+                      .elementAt(0), ignoreCase, trnc)))
+      {
+        subsk.offset += offset;
+        return subsk;
+      }
+      else if (p.minChars().equals(p.maxChars()))
+      {
+        offset += p.minChars().intValue();
+      }
+      else
+      {
+        return skipc < 0 ? null : new Skip("" + (char) skipc, ignoreCase,
+                skipoff);
+      }
+    }
+    return null;
+  }
+}