--- /dev/null
+//\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