RegExp: fix match count computation
* There actually is a way to count the matches, so use it instead of attempting to guess * In some cases (when using optional groups (xxx)?, for example), there may be a non-matching group (with offsets set to -1) and matching groups after it, so the binary search wasn't quite working * Instead, we always return the number of capturing groups in the in the given expression, which is the maximal number of matches. Some (or all) of these may not have any content. We do return 0 matches on any error, including when the regular expression didn't match anything.
This commit is contained in:
@@ -154,40 +154,17 @@ struct RegExp::MatchResultData : public BReferenceable {
|
|||||||
fMatchCount(0),
|
fMatchCount(0),
|
||||||
fMatches(NULL)
|
fMatches(NULL)
|
||||||
{
|
{
|
||||||
// Do the matching: Since we need to provide a buffer for the matches
|
// fMatchCount is always set to the number of matching groups in the
|
||||||
// for regexec() to fill in, but don't know the number of matches
|
// expression (or 0 if an error occured). Some of the "matches" in
|
||||||
// beforehand, we need to guess and retry with a larger buffer, if it
|
// the array may still point to the (-1,-1) range if they don't
|
||||||
// wasn't large enough.
|
// actually match anything.
|
||||||
size_t maxMatchCount = 32;
|
fMatchCount = compiledExpression->re_nsub + 1;
|
||||||
for (;;) {
|
fMatches = new regmatch_t[fMatchCount];
|
||||||
fMatches = new regmatch_t[maxMatchCount];
|
if (regexec(compiledExpression, string, fMatchCount, fMatches, 0)
|
||||||
if (regexec(compiledExpression, string, maxMatchCount, fMatches, 0)
|
!= 0) {
|
||||||
!= 0) {
|
|
||||||
delete[] fMatches;
|
|
||||||
fMatches = NULL;
|
|
||||||
fMatchCount = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fMatches[maxMatchCount - 1].rm_so == -1) {
|
|
||||||
// determine the match count
|
|
||||||
size_t lower = 0;
|
|
||||||
size_t upper = maxMatchCount;
|
|
||||||
while (lower < upper) {
|
|
||||||
size_t mid = (lower + upper) / 2;
|
|
||||||
if (fMatches[mid].rm_so == -1)
|
|
||||||
upper = mid;
|
|
||||||
else
|
|
||||||
lower = mid + 1;
|
|
||||||
}
|
|
||||||
fMatchCount = lower;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// buffer too small -- try again with larger buffer
|
|
||||||
delete[] fMatches;
|
delete[] fMatches;
|
||||||
fMatches = NULL;
|
fMatches = NULL;
|
||||||
maxMatchCount *= 2;
|
fMatchCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user