Formatting
[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 \r
10 import java.util.*;\r
11 \r
12 /** A special case of Multi, implemented when minChars().equals(maxChars()),\r
13  * and some other conditions spelled out in RegOpt.safe4fm "Safe for\r
14  * FastMulti."  It avoids stack growth problems as well as being slightly\r
15  * faster.\r
16  */\r
17 class FastMulti\r
18     extends PatternSub\r
19 {\r
20   patInt fewestMatches, mostMatches;\r
21   public patInt minChars()\r
22   {\r
23     return sub.countMinChars().mul(fewestMatches);\r
24   }\r
25 \r
26   public patInt maxChars()\r
27   {\r
28     return sub.countMaxChars().mul(mostMatches);\r
29   }\r
30 \r
31   public boolean matchFewest = false;\r
32 \r
33   FastMulti(patInt a, patInt b, Pattern p)\r
34       throws RegSyntax\r
35   {\r
36     if (p == null)\r
37     {\r
38       RegSyntaxError.endItAll("Null length pattern " +\r
39                               "followed by *, +, or other Multi.");\r
40     }\r
41     fewestMatches = a;\r
42     mostMatches = b;\r
43     sub = p;\r
44     step = p.countMinChars().intValue();\r
45     sub.setParent(null);\r
46   }\r
47 \r
48   public String toString()\r
49   {\r
50     return sub.toString() + "{"\r
51         + fewestMatches + "," + mostMatches + "}" +\r
52         (matchFewest ? "?" : "") + "(?# <= fast multi)" +\r
53         nextString();\r
54   }\r
55 \r
56   int step = -1;\r
57   public int matchInternal(int pos, Pthings pt)\r
58   {\r
59     int m = -1;\r
60     int i = pos;\r
61     int endstr = pt.src.length() - step;\r
62     patInt matches = new patInt(0);\r
63     if (matchFewest)\r
64     {\r
65       if (fewestMatches.lessEq(matches))\r
66       {\r
67         int ii = nextMatch(i, pt);\r
68         if (ii >= 0)\r
69         {\r
70           return ii;\r
71         }\r
72       }\r
73       while (i >= 0 && i <= endstr)\r
74       {\r
75         i = sub.matchInternal(i, pt);\r
76         if (i >= 0)\r
77         {\r
78           matches.inc();\r
79           if (fewestMatches.lessEq(matches))\r
80           {\r
81             int ii = nextMatch(i, pt);\r
82             if (ii >= 0)\r
83             {\r
84               return ii;\r
85             }\r
86           }\r
87           if (matches.equals(mostMatches))\r
88           {\r
89             return -1;\r
90           }\r
91         }\r
92       }\r
93       return -1;\r
94     }\r
95     int nMatches = 0;\r
96     while (fewestMatches.intValue() > nMatches)\r
97     {\r
98       i = sub.matchInternal(i, pt);\r
99       if (i >= 0)\r
100       {\r
101         nMatches++;\r
102       }\r
103       else\r
104       {\r
105         return -1;\r
106       }\r
107     }\r
108     m = i;\r
109     if (mostMatches.finite())\r
110     {\r
111       while (nMatches < mostMatches.intValue())\r
112       {\r
113         i = sub.matchInternal(i, pt);\r
114         if (i >= 0)\r
115         {\r
116           m = i;\r
117           nMatches++;\r
118         }\r
119         else\r
120         {\r
121           break;\r
122         }\r
123       }\r
124     }\r
125     else\r
126     {\r
127       while (true)\r
128       {\r
129         i = sub.matchInternal(i, pt);\r
130         if (i >= 0)\r
131         {\r
132           m = i;\r
133           nMatches++;\r
134         }\r
135         else\r
136         {\r
137           break;\r
138         }\r
139       }\r
140     }\r
141     while (m >= pos)\r
142     {\r
143       int r = nextMatch(m, pt);\r
144       if (r >= 0)\r
145       {\r
146         return r;\r
147       }\r
148       m -= step;\r
149       nMatches--;\r
150       if (nMatches < fewestMatches.intValue())\r
151       {\r
152         return -1;\r
153       }\r
154     }\r
155     return -1;\r
156   }\r
157 \r
158   public Pattern clone1(Hashtable h)\r
159   {\r
160     try\r
161     {\r
162       FastMulti fm = new FastMulti(fewestMatches, mostMatches, sub.clone(h));\r
163       fm.matchFewest = matchFewest;\r
164       return fm;\r
165     }\r
166     catch (RegSyntax rs)\r
167     {\r
168       return null;\r
169     }\r
170   }\r
171 }\r