QString: ensure multi-arg arg() parses replacement like single-arg arg()

There was a discrepancy that the multi-arg arg() overload would accept
any number of digits in the placeholder, resolving up to value 999
(e.g., %000001 was interpreted as placeholder #1), but the single-arg
arg() overload only supported exactly one or two digits. The single-arg
behavior was documented, so use it.

[ChangeLog][Important Behavior Changes] The QString::arg() overload
taking multiple QString-like arguments is now fixed to interpret
placeholders like the other arg() overloads: it will find at most two
digits after the '%' character. That is, the sequence "%123" is now
interpreted as placeholder #12 followed by character '3' (verbatim).

Fixes: QTBUG-118581
Change-Id: I455fe22ef4ad4b2f9b01fffd17c767a948d41138
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
(cherry picked from commit f0f2a9ef2600288b16b69c135389dfe1fea89a8d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2024-04-18 07:55:59 -07:00 committed by Qt Cherry-pick Bot
parent a4b8399957
commit 5be8cf4e9a
2 changed files with 18 additions and 13 deletions

View File

@ -8855,7 +8855,7 @@ static inline char16_t to_unicode(const QChar c) { return c.unicode(); }
static inline char16_t to_unicode(const char c) { return QLatin1Char{c}.unicode(); }
template <typename Char>
static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumber = 999)
static int getEscape(const Char *uc, qsizetype *pos, qsizetype len)
{
qsizetype i = *pos;
++i;
@ -8866,17 +8866,16 @@ static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumbe
if (uint(escape) >= 10U)
return -1;
++i;
while (i < len) {
if (i < len) {
// there's a second digit
int digit = to_unicode(uc[i]) - '0';
if (uint(digit) >= 10U)
break;
escape = (escape * 10) + digit;
++i;
}
if (escape <= maxNumber) {
*pos = i;
return escape;
if (uint(digit) < 10U) {
escape = (escape * 10) + digit;
++i;
}
}
*pos = i;
return escape;
}
return -1;
}

View File

@ -6716,9 +6716,15 @@ void tst_QString::arg()
str = str.arg(u"ahoy"_s, u"there"_s);
QCOMPARE(str, "one 2 3 4 5 6 7 8 9 foo ahoy there bar"_L1);
QString str2(u"%123 %234 %345 %456 %567 %999 %1000 %1230"_s);
str2 = str2.arg(u"A"_s, u"B"_s, u"C"_s, u"D"_s, u"E"_s, u"F"_s);
QCOMPARE(str2, QLatin1String("A B C D E F %1000 %1230"));
// Make sure the single- and multi-arg expand the same sequences: at most
// two digits. The sequence below has four replacements: %01, %10 (twice),
// %11, and %12.
QString str2 = u"%100 %101 %110 %12 %0100"_s;
QLatin1StringView str2expected = "B0 B1 C0 D A00"_L1;
QCOMPARE(str2.arg(QChar(u'A')).arg(QChar(u'B')).arg(QChar(u'C')).arg(QChar(u'D')), str2expected);
QCOMPARE(str2.arg(QChar(u'A'), QChar(u'B')).arg(QChar(u'C')).arg(QChar(u'D')), str2expected);
QCOMPARE(str2.arg(QChar(u'A'), QChar(u'B'), QChar(u'C')).arg(QChar(u'D')), str2expected);
QCOMPARE(str2.arg(QChar(u'A'), QChar(u'B'), QChar(u'C'), QChar(u'D')), str2expected);
QCOMPARE(u"%1"_s.arg(-1, 3, 10, QChar(u'0')), "-01"_L1);
QCOMPARE(u"%1"_s.arg(-100, 3, 10, QChar(u'0')), "-100"_L1);