//
// This software is now distributed according to
// the Lesser Gnu Public License. Please see
// http://www.gnu.org/copyleft/lesser.txt for
// the details.
// -- Happy Computing!
//
package com.stevesoft.ewe_pat;
import ewe.util.Hashtable;
/** A special case of Multi, implemented when minChars().equals(maxChars()),
* and some other conditions spelled out in RegOpt.safe4fm "Safe for
* FastMulti." It avoids stack growth problems as well as being slightly
* faster.
*/
class FastMulti extends PatternSub {
patInt fewestMatches,mostMatches;
public patInt minChars() {
return sub.countMinChars().mul(fewestMatches);
}
public patInt maxChars() {
return sub.countMaxChars().mul(mostMatches);
}
public boolean matchFewest = false;
FastMulti(patInt a,patInt b,Pattern p) throws RegSyntax {
if(p == null) RegSyntaxError.endItAll("Null length pattern "+
"followed by *, +, or other Multi.");
fewestMatches = a;
mostMatches = b;
sub = p;
step = p.countMinChars().intValue();
sub.setParent(null);
}
public String toString() {
return sub.toString()+"{"
+fewestMatches+","+mostMatches+"}"+
(matchFewest ? "?" : "")+"(?# <= fast multi)"+
nextString();
}
int step = -1;
public int matchInternal(int pos,Pthings pt) {
int m=-1;
int i=pos;
int endstr = pt.src.length()-step;
patInt matches = new patInt(0);
if(matchFewest) {
if(fewestMatches.lessEq(matches)) {
int ii = nextMatch(i,pt);
if(ii >= 0) return ii;
}
while(i >= 0 && i <= endstr) {
i=sub.matchInternal(i,pt);
if(i >= 0) {
matches.inc();
if(fewestMatches.lessEq(matches)) {
int ii = nextMatch(i,pt);
if(ii >= 0) return ii;
}
if(matches.equals(mostMatches))
return -1;
}
}
return -1;
}
int nMatches = 0;
while(fewestMatches.intValue() > nMatches) {
i=sub.matchInternal(i,pt);
if(i >= 0)
nMatches++;
else
return -1;
}
m=i;
if(mostMatches.finite()) {
while(nMatches < mostMatches.intValue()) {
i = sub.matchInternal(i,pt);
if(i>=0) {
m=i;
nMatches++;
} else break;
}
} else {
while(true) {
i = sub.matchInternal(i,pt);
if(i>=0) {
m=i;
nMatches++;
} else break;
}
}
while(m >= pos) {
int r=nextMatch(m,pt);
if(r >= 0) return r;
m -= step;
nMatches--;
if(nMatches < fewestMatches.intValue())
return -1;
}
return -1;
}
public Pattern clone1(Hashtable h) {
try {
FastMulti fm = new FastMulti(fewestMatches,mostMatches,sub.clone(h));
fm.matchFewest = matchFewest;
return fm;
} catch(RegSyntax rs) {
return null;
}
}
}