From 91f3687ee51db83d9018bd61c3fbc736c6e9912e Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 8 Jun 2018 17:37:49 +0200 Subject: Make QString's formatting of doubles be consistent with other places QString::sprintf(), like the C printf-family, always includes two digits in any exponent it outputs. Up to 5.6, number() and arg() taking a double did the same; but changes at 5.7 to enable opting out of the leading zero this implies for a single-digit exponent accidentally opted out of it in args() and number(). This commit fixes number() and arg() to include QLocaleData::ZeroPadExponent in the flags they pass down to the C locale's doubleToString(), restoring the prior behavior, including consistency with sprintf(). [ChangeLog][QtCore][QString] Formatting of doubles with single-digit exponent, by number() or args(), now includes a leading zero in that exponent, consistently with sprintf(), as it did up to 5.6. Task-number: QTBUG-63620 Change-Id: I10c491902b8556e9f19e605177ead8d9fd32abd9 Reviewed-by: Thiago Macieira Reviewed-by: Ulf Hermann --- src/corelib/tools/qstring.cpp | 14 ++++++-------- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index a4b34263df..3787c496b2 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -7414,13 +7414,12 @@ QString QString::number(qulonglong n, int base) QString QString::number(double n, char f, int prec) { QLocaleData::DoubleForm form = QLocaleData::DFDecimal; - uint flags = 0; + uint flags = QLocaleData::ZeroPadExponent; if (qIsUpper(f)) - flags = QLocaleData::CapitalEorX; - f = qToLower(f); + flags |= QLocaleData::CapitalEorX; - switch (f) { + switch (qToLower(f)) { case 'f': form = QLocaleData::DFDecimal; break; @@ -8487,14 +8486,13 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha unsigned flags = QLocaleData::NoFlags; if (fillChar == QLatin1Char('0')) - flags = QLocaleData::ZeroPadded; + flags |= QLocaleData::ZeroPadded; if (qIsUpper(fmt)) flags |= QLocaleData::CapitalEorX; - fmt = qToLower(fmt); QLocaleData::DoubleForm form = QLocaleData::DFDecimal; - switch (fmt) { + switch (qToLower(fmt)) { case 'f': form = QLocaleData::DFDecimal; break; @@ -8513,7 +8511,7 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha QString arg; if (d.occurrences > d.locale_occurrences) - arg = QLocaleData::c()->doubleToString(a, prec, form, fieldWidth, flags); + arg = QLocaleData::c()->doubleToString(a, prec, form, fieldWidth, flags | QLocaleData::ZeroPadExponent); QString locale_arg; if (d.locale_occurrences > 0) { diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 28014840a3..2074c9789a 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -516,6 +516,7 @@ private slots: void toUcs4(); void arg(); void number(); + void doubleOut(); void arg_fillChar_data(); void arg_fillChar(); void capacity_data(); @@ -4882,6 +4883,28 @@ void tst_QString::number() #endif } +void tst_QString::doubleOut() +{ + // Regression test for QTBUG-63620; the first two paths lost the exponent's + // leading 0 at 5.7; C's printf() family guarantee a two-digit exponent (in + // contrast with ECMAScript, which forbids leading zeros). + const QString expect(QStringLiteral("1e-06")); + const double micro = 1e-6; + QCOMPARE(QString::number(micro), expect); + QCOMPARE(QString("%1").arg(micro), expect); + { + QString text; + text.sprintf("%g", micro); + QCOMPARE(text, expect); + } + { + QString text; + QTextStream stream(&text); + stream << micro; + QCOMPARE(text, expect); + } +} + void tst_QString::capacity_data() { length_data(); -- cgit v1.2.3