needed for applet search
[jalview.git] / src / com / stevesoft / pat / FastMulti.java
1 //\r
2 // This software is now distributed according to\r
3 // the Lesser Gnu Public License.  Please see\r
4 // http://www.gnu.org/copyleft/lesser.txt for\r
5 // the details.\r
6 //    -- Happy Computing!\r
7 //\r
8 package com.stevesoft.pat;\r
9 import java.util.Hashtable;\r
10 \r
11 /** A special case of Multi, implemented when minChars().equals(maxChars()),\r
12   * and some other conditions spelled out in RegOpt.safe4fm "Safe for\r
13   * FastMulti."  It avoids stack growth problems as well as being slightly\r
14   * faster.\r
15   */\r
16 class FastMulti extends PatternSub {\r
17     patInt fewestMatches,mostMatches;\r
18     public patInt minChars() {\r
19         return sub.countMinChars().mul(fewestMatches);\r
20     }\r
21     public patInt maxChars() {\r
22         return sub.countMaxChars().mul(mostMatches);\r
23     }\r
24     public boolean matchFewest = false;\r
25 \r
26     FastMulti(patInt a,patInt b,Pattern p) throws RegSyntax {\r
27         if(p == null) RegSyntaxError.endItAll("Null length pattern "+\r
28                 "followed by *, +, or other Multi.");\r
29         fewestMatches = a;\r
30         mostMatches = b;\r
31         sub = p;\r
32         step = p.countMinChars().intValue();\r
33         sub.setParent(null);\r
34     }\r
35     public String toString() {\r
36         return sub.toString()+"{"\r
37             +fewestMatches+","+mostMatches+"}"+\r
38             (matchFewest ? "?" : "")+"(?# <= fast multi)"+\r
39             nextString();\r
40     }\r
41     int step = -1;\r
42     public int matchInternal(int pos,Pthings pt) {\r
43         int m=-1;\r
44         int i=pos;\r
45         int endstr = pt.src.length()-step;\r
46         patInt matches = new patInt(0);\r
47         if(matchFewest) {\r
48             if(fewestMatches.lessEq(matches)) {\r
49                 int ii = nextMatch(i,pt);\r
50                 if(ii >= 0) return ii;\r
51             }\r
52             while(i >= 0 && i <= endstr) {\r
53                 i=sub.matchInternal(i,pt);\r
54                 if(i >= 0) {\r
55                     matches.inc();\r
56                     if(fewestMatches.lessEq(matches)) {\r
57                         int ii = nextMatch(i,pt);\r
58                         if(ii >= 0) return ii;\r
59                     }\r
60                     if(matches.equals(mostMatches))\r
61                         return -1;\r
62                 }\r
63             }\r
64             return -1;\r
65         }\r
66         int nMatches = 0;\r
67         while(fewestMatches.intValue() > nMatches) {\r
68             i=sub.matchInternal(i,pt);\r
69             if(i >= 0)\r
70                 nMatches++;\r
71             else\r
72                 return -1;\r
73         }\r
74         m=i;\r
75         if(mostMatches.finite()) {\r
76             while(nMatches < mostMatches.intValue()) {\r
77                 i = sub.matchInternal(i,pt);\r
78                 if(i>=0) {\r
79                     m=i;\r
80                     nMatches++;\r
81                 } else break;\r
82             }\r
83         } else {\r
84             while(true) {\r
85                 i = sub.matchInternal(i,pt);\r
86                 if(i>=0) {\r
87                     m=i;\r
88                     nMatches++;\r
89                 } else break;\r
90             }\r
91         }\r
92         while(m >= pos) {\r
93             int r=nextMatch(m,pt);\r
94             if(r >= 0) return r;\r
95             m -= step;\r
96             nMatches--;\r
97             if(nMatches < fewestMatches.intValue())\r
98                 return -1;\r
99         }\r
100         return -1;\r
101     }\r
102     public Pattern clone1(Hashtable h) {\r
103         try {\r
104             FastMulti fm = new FastMulti(fewestMatches,mostMatches,sub.clone(h));\r
105             fm.matchFewest = matchFewest;\r
106             return fm;\r
107         } catch(RegSyntax rs) {\r
108             return null;\r
109         }\r
110     }\r
111 }\r