// // 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.pat; import java.util.*; /** 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; } } }