regsub converter: empty match advances by 1 byte to avoid loops

This commit is contained in:
2019-02-18 11:08:21 +01:00
parent acf7efcff2
commit 04906a5835
2 changed files with 55 additions and 39 deletions

View File

@ -666,6 +666,13 @@ Otherwise <em>precision</em> is the index (counting from 1) of the match to repl
Without <em>precision</em> (or 0), all matches are replaced.
</p>
<p>
When replacing multiple matches, the next match is searched directly after the currently
replaced string, so that the <em>subst</em> string itself will never be modified recursively.
<span class="new">
However if an empty string is matched, searching advances by 1 character in order to
avoid matching the same empty string again.</span>
</p>
<p>
In input this converter pre-processes data received from the device before
following converters read it.
Converters preceding this one will read unmodified input.

View File

@ -197,14 +197,15 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
debug("pcre_exec: no match\n");
break;
}
if (!(fmt.flags & sign_flag) && n < fmt.prec) // without + flag
{
// do not yet replace this match
c += ovector[1];
continue;
}
// replace subexpressions
l = ovector[1] - ovector[0];
// no prec: replace all matches
// prec with + flag: replace first prec matches
// prec without + flag: replace only match number prec
if ((fmt.flags & sign_flag) || n >= fmt.prec)
{
// replace subexpressions
debug("before [%d]= \"%s\"\n", ovector[0], buffer.expand(start+c,ovector[0])());
debug("match [%d]= \"%s\"\n", l, buffer.expand(start+c+ovector[0],l)());
for (r = 1; r < rc; r++)
@ -243,8 +244,16 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
debug("subs = \"%s\"\n", s.expand()());
}
buffer.replace(start+c+ovector[0], l, s);
length += s.length() - l;
c += ovector[0] + s.length();
length -= l;
length += s.length();
c += s.length();
}
c += ovector[0];
if (l == 0)
{
debug("pcre_exec: empty match\n");
c++; // Empty strings may lead to an endless loop. Match them only once.
}
if (n == fmt.prec) // max match reached
{
debug("pcre_exec: max match %d reached\n", n);