2 // This software is now distributed according to
3 // the Lesser Gnu Public License. Please see
4 // http://www.gnu.org/copyleft/lesser.txt for
8 package com.stevesoft.pat;
10 import java.util.BitSet;
11 import java.util.Vector;
14 * Uses table lookup to match [] type constructs, but only if it can use a
15 * lookup table 256 bits in size. It is impractical to make a table if it is too
18 public class FastBracket extends Bracket
24 FastBracket(boolean n)
29 // This routine can optimize a bracket, possibly
30 // it will replace it with a FastBracket.
31 static Bracket process(Bracket b, boolean ignc)
38 // Expand out the vector to make separate
39 // entries for other cases if ignoreCase is
45 for (int i = 0; i < v.size(); i++)
47 Pattern p = (Pattern) v.elementAt(i);
49 if (p instanceof oneChar)
51 oneChar oc = (oneChar) p;
52 nv.addElement(new oneChar(oc.altc));
54 else if (p instanceof Range)
57 nv.addElement(new Range(ra.altlo, ra.althi));
63 // Bubble sort, make sure elements
64 // are in order. This will allow us
66 for (int i = 0; i < v.size() - 1; i++)
68 for (int j = 0; j < v.size() - 1; j++)
70 char c1 = getl(v.elementAt(j));
71 char c2 = getl(v.elementAt(j + 1));
74 Object o = v.elementAt(j);
75 v.setElementAt(v.elementAt(j + 1), j);
76 v.setElementAt(o, j + 1);
82 // merge -- remove overlaps
83 Pattern p = (Pattern) v.elementAt(0);
85 for (int i = 1; i < v.size(); i++)
87 if (geth(p) + 1 >= getl(v.elementAt(i)))
89 Pattern p2 = (Pattern) v.elementAt(i);
90 char lo = min(getl(p), getl(p2));
91 char hi = max(geth(p), geth(p2));
92 nv.setElementAt(p = mkelem(lo, hi), nv.size() - 1);
96 p = (Pattern) v.elementAt(i);
102 } catch (RegSyntax e)
107 // We don't want these things to be empty.
108 Vector negv = neg(v);
113 if (negv.size() == 1)
120 // Now consider if we can make a FastBracket.
121 // Uses a BitSet to do a lookup.
122 FastBracket fb = newbrack(v, b.neg);
125 fb = newbrack(negv, !b.neg);
129 fb.parent = b.parent;
134 // return the normal Bracket.
138 // Build a FastBracket and set bits. If this can't
139 // be done, return null.
140 final static FastBracket newbrack(Vector v, boolean neg)
142 FastBracket fb = new FastBracket(neg);
148 fb.min = getl(v.elementAt(0));
149 fb.max = geth(v.elementAt(v.size() - 1));
150 if (fb.max - fb.min <= 256)
152 fb.bs = new BitSet(fb.max - fb.min + 1);
153 for (int i = 0; i < v.size(); i++)
155 Object o = v.elementAt(i);
156 int min0 = getl(o) - fb.min;
157 int max0 = geth(o) - fb.min;
158 for (int j = min0; j <= max0; j++)
168 // Negate a sorted Vector. Applying this
169 // operation twice should yield the same Vector
171 final static Vector neg(Vector v)
175 Vector nv = new Vector();
178 nv.addElement(new Range((char) 0, (char) 65535));
181 int p0 = getl(v.elementAt(0));
184 nv.addElement(mkelem((char) 0, (char) (p0 - 1)));
186 for (int i = 0; i < v.size() - 1; i++)
188 int hi = getl(v.elementAt(i + 1)) - 1;
189 int lo = geth(v.elementAt(i)) + 1;
190 nv.addElement(mkelem((char) lo, (char) hi));
192 int pN = geth(v.lastElement());
195 nv.addElement(mkelem((char) (pN + 1), (char) 65535));
198 } catch (RegSyntax rs)
204 // Make either a Range or oneChar Object, depending on which
206 final static Pattern mkelem(char lo, char hi) throws RegSyntax
208 return lo == hi ? (Pattern) (new oneChar(lo)) : (Pattern) (new Range(
212 static final char min(char a, char b)
214 return a < b ? a : b;
217 static final char max(char a, char b)
219 return a > b ? a : b;
222 // getl -- get lower value of Range object,
223 // or get value of oneChar object.
224 final static char getl(Object o)
226 Pattern p = (Pattern) o;
227 if (p instanceof Range)
229 return ((Range) p).lo;
231 return ((oneChar) p).c;
234 // geth -- get higher value of Range object,
235 // or get value of oneChar object.
236 final static char geth(Object o)
238 Pattern p = (Pattern) o;
239 if (p instanceof Range)
241 return ((Range) p).hi;
243 return ((oneChar) p).c;
246 // This is the easy part!
247 public int matchInternal(int pos, Pthings pt)
249 if (pos >= pt.src.length() || Masked(pos, pt))
253 char c = pt.src.charAt(pos);
254 return (neg ^ (c >= min && c <= max && bs.get(c - min))) ? nextMatch(