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
6 // -- Happy Computing!
\r
8 package com.stevesoft.pat;
\r
12 /** Uses table lookup to match [] type constructs, but
\r
13 only if it can use a lookup table 256 bits in size.
\r
14 It is impractical to make a table if it is too large.
\r
16 public class FastBracket extends Bracket {
\r
19 FastBracket(boolean n) { super(n); }
\r
20 // This routine can optimize a bracket, possibly
\r
21 // it will replace it with a FastBracket.
\r
22 static Bracket process(Bracket b,boolean ignc) {
\r
27 // Expand out the vector to make separate
\r
28 // entries for other cases if ignoreCase is
\r
33 for(int i=0;i<v.size();i++) {
\r
34 Pattern p = (Pattern)v.elementAt(i);
\r
36 if(p instanceof oneChar) {
\r
37 oneChar oc = (oneChar)p;
\r
38 nv.addElement(new oneChar(oc.altc));
\r
39 } else if(p instanceof Range) {
\r
40 Range ra = (Range)p;
\r
41 nv.addElement(new Range(ra.altlo,ra.althi));
\r
47 // Bubble sort, make sure elements
\r
48 // are in order. This will allow us
\r
50 for(int i=0;i<v.size()-1;i++) {
\r
51 for(int j=0;j<v.size()-1;j++) {
\r
52 char c1 = getl(v.elementAt(j));
\r
53 char c2 = getl(v.elementAt(j+1));
\r
55 Object o = v.elementAt(j);
\r
56 v.setElementAt(v.elementAt(j+1),j);
\r
57 v.setElementAt(o,j+1);
\r
63 // merge -- remove overlaps
\r
64 Pattern p = (Pattern)v.elementAt(0);
\r
66 for(int i=1;i<v.size();i++) {
\r
67 if(geth(p)+1 >= getl(v.elementAt(i))) {
\r
68 Pattern p2 = (Pattern)v.elementAt(i);
\r
69 char lo = min(getl(p),getl(p2));
\r
70 char hi = max(geth(p),geth(p2));
\r
71 nv.setElementAt(p=mkelem(lo,hi),nv.size()-1);
\r
73 p = (Pattern)v.elementAt(i);
\r
79 } catch(RegSyntax e) {
\r
80 e.printStackTrace();
\r
83 // We don't want these things to be empty.
\r
84 Vector negv = neg(v);
\r
85 if(v.size()==1) return b;
\r
86 if(negv.size()==1) {
\r
92 // Now consider if we can make a FastBracket.
\r
93 // Uses a BitSet to do a lookup.
\r
94 FastBracket fb = newbrack(v,b.neg);
\r
96 fb = newbrack(negv,!b.neg);
\r
98 fb.parent = b.parent;
\r
103 // return the normal Bracket.
\r
107 // Build a FastBracket and set bits. If this can't
\r
108 // be done, return null.
\r
109 final static FastBracket newbrack(Vector v,boolean neg) {
\r
110 FastBracket fb = new FastBracket(neg);
\r
112 if(v.size()==0) return null;
\r
113 fb.min = getl(v.elementAt(0));
\r
114 fb.max = geth(v.elementAt(v.size()-1));
\r
115 if(fb.max-fb.min <= 256) {
\r
116 fb.bs = new BitSet(fb.max-fb.min+1);
\r
117 for(int i=0;i<v.size();i++) {
\r
118 Object o = v.elementAt(i);
\r
119 int min0 = getl(o)-fb.min;
\r
120 int max0 = geth(o)-fb.min;
\r
121 for(int j=min0;j<=max0;j++)
\r
129 // Negate a sorted Vector. Applying this
\r
130 // operation twice should yield the same Vector
\r
132 final static Vector neg(Vector v) {
\r
134 Vector nv = new Vector();
\r
136 nv.addElement(new Range((char)0,(char)65535));
\r
139 int p0 = getl(v.elementAt(0));
\r
141 nv.addElement(mkelem((char)0,(char)(p0-1) ));
\r
142 for(int i=0;i<v.size()-1;i++) {
\r
143 int hi = getl(v.elementAt(i+1))-1;
\r
144 int lo = geth(v.elementAt(i))+1;
\r
145 nv.addElement(mkelem((char)lo,(char)hi));
\r
147 int pN = geth(v.lastElement());
\r
149 nv.addElement(mkelem((char)(pN+1),(char)65535));
\r
151 } catch(RegSyntax rs) {
\r
155 // Make either a Range or oneChar Object, depending on which
\r
157 final static Pattern mkelem(char lo,char hi) throws RegSyntax {
\r
158 return lo==hi ? (Pattern)(new oneChar(lo)) : (Pattern)(new Range(lo,hi));
\r
160 static final char min(char a,char b) {
\r
161 return a<b ? a : b;
\r
163 static final char max(char a,char b) {
\r
164 return a>b ? a : b;
\r
167 // getl -- get lower value of Range object,
\r
168 // or get value of oneChar object.
\r
169 final static char getl(Object o) {
\r
170 Pattern p = (Pattern)o;
\r
171 if(p instanceof Range)
\r
172 return ((Range)p).lo;
\r
173 return ((oneChar)p).c;
\r
175 // geth -- get higher value of Range object,
\r
176 // or get value of oneChar object.
\r
177 final static char geth(Object o) {
\r
178 Pattern p = (Pattern)o;
\r
179 if(p instanceof Range)
\r
180 return ((Range)p).hi;
\r
181 return ((oneChar)p).c;
\r
184 // This is the easy part!
\r
185 public int matchInternal(int pos,Pthings pt) {
\r
186 if(pos >= pt.src.length() || Masked(pos,pt)) return -1;
\r
187 char c = pt.src.charAt(pos);
\r
188 return (neg ^ (c >= min && c <= max && bs.get(c-min)) ) ?
\r
189 nextMatch(pos+1,pt) : -1;
\r