needed for applet search
[jalview.git] / src / com / stevesoft / pat / FastMulti.java
diff --git a/src/com/stevesoft/pat/FastMulti.java b/src/com/stevesoft/pat/FastMulti.java
new file mode 100755 (executable)
index 0000000..2a38281
--- /dev/null
@@ -0,0 +1,111 @@
+//\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
+import java.util.Hashtable;\r
+\r
+/** A special case of Multi, implemented when minChars().equals(maxChars()),\r
+  * and some other conditions spelled out in RegOpt.safe4fm "Safe for\r
+  * FastMulti."  It avoids stack growth problems as well as being slightly\r
+  * faster.\r
+  */\r
+class FastMulti extends PatternSub {\r
+    patInt fewestMatches,mostMatches;\r
+    public patInt minChars() {\r
+        return sub.countMinChars().mul(fewestMatches);\r
+    }\r
+    public patInt maxChars() {\r
+        return sub.countMaxChars().mul(mostMatches);\r
+    }\r
+    public boolean matchFewest = false;\r
+\r
+    FastMulti(patInt a,patInt b,Pattern p) throws RegSyntax {\r
+        if(p == null) RegSyntaxError.endItAll("Null length pattern "+\r
+                "followed by *, +, or other Multi.");\r
+        fewestMatches = a;\r
+        mostMatches = b;\r
+        sub = p;\r
+        step = p.countMinChars().intValue();\r
+        sub.setParent(null);\r
+    }\r
+    public String toString() {\r
+        return sub.toString()+"{"\r
+            +fewestMatches+","+mostMatches+"}"+\r
+            (matchFewest ? "?" : "")+"(?# <= fast multi)"+\r
+            nextString();\r
+    }\r
+    int step = -1;\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        int m=-1;\r
+        int i=pos;\r
+        int endstr = pt.src.length()-step;\r
+        patInt matches = new patInt(0);\r
+        if(matchFewest) {\r
+            if(fewestMatches.lessEq(matches)) {\r
+                int ii = nextMatch(i,pt);\r
+                if(ii >= 0) return ii;\r
+            }\r
+            while(i >= 0 && i <= endstr) {\r
+                i=sub.matchInternal(i,pt);\r
+                if(i >= 0) {\r
+                    matches.inc();\r
+                    if(fewestMatches.lessEq(matches)) {\r
+                        int ii = nextMatch(i,pt);\r
+                        if(ii >= 0) return ii;\r
+                    }\r
+                    if(matches.equals(mostMatches))\r
+                        return -1;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+        int nMatches = 0;\r
+        while(fewestMatches.intValue() > nMatches) {\r
+            i=sub.matchInternal(i,pt);\r
+            if(i >= 0)\r
+                nMatches++;\r
+            else\r
+                return -1;\r
+        }\r
+        m=i;\r
+        if(mostMatches.finite()) {\r
+            while(nMatches < mostMatches.intValue()) {\r
+                i = sub.matchInternal(i,pt);\r
+                if(i>=0) {\r
+                    m=i;\r
+                    nMatches++;\r
+                } else break;\r
+            }\r
+        } else {\r
+            while(true) {\r
+                i = sub.matchInternal(i,pt);\r
+                if(i>=0) {\r
+                    m=i;\r
+                    nMatches++;\r
+                } else break;\r
+            }\r
+        }\r
+        while(m >= pos) {\r
+            int r=nextMatch(m,pt);\r
+            if(r >= 0) return r;\r
+            m -= step;\r
+            nMatches--;\r
+            if(nMatches < fewestMatches.intValue())\r
+                return -1;\r
+        }\r
+        return -1;\r
+    }\r
+    public Pattern clone1(Hashtable h) {\r
+        try {\r
+            FastMulti fm = new FastMulti(fewestMatches,mostMatches,sub.clone(h));\r
+            fm.matchFewest = matchFewest;\r
+            return fm;\r
+        } catch(RegSyntax rs) {\r
+            return null;\r
+        }\r
+    }\r
+}\r