summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qbytearray.cpp3
-rw-r--r--src/corelib/tools/qlocale.cpp18
-rw-r--r--src/corelib/tools/qstring.cpp6
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp56
4 files changed, 62 insertions, 21 deletions
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 424420204a..1b7a4366c7 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -3871,7 +3871,8 @@ ushort QByteArray::toUShort(bool *ok, int base) const
/*!
Returns the byte array converted to a \c double value.
- Returns 0.0 if the conversion fails.
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for other reasons (e.g. underflow).
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 6361280bc7..8f9fb3de2d 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -1373,8 +1373,10 @@ float QLocale::toFloat(const QString &s, bool *ok) const
}
/*!
- Returns the double represented by the localized string \a s, or
- 0.0 if the conversion failed.
+ Returns the double represented by the localized string \a s.
+
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for any other reason (e.g. underflow).
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
@@ -1542,8 +1544,10 @@ float QLocale::toFloat(const QStringRef &s, bool *ok) const
}
/*!
- Returns the double represented by the localized string \a s, or
- 0.0 if the conversion failed.
+ Returns the double represented by the localized string \a s.
+
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for any other reason (e.g. underflow).
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
@@ -1711,8 +1715,10 @@ float QLocale::toFloat(QStringView s, bool *ok) const
}
/*!
- Returns the double represented by the localized string \a s, or
- 0.0 if the conversion failed.
+ Returns the double represented by the localized string \a s.
+
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for any other reason (e.g. underflow).
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 0a8b2b4238..1381e8c11c 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -7169,7 +7169,8 @@ ushort QString::toUShort(bool *ok, int base) const
/*!
Returns the string converted to a \c double value.
- Returns 0.0 if the conversion fails.
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for other reasons (e.g. underflow).
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
@@ -11794,7 +11795,8 @@ ushort QStringRef::toUShort(bool *ok, int base) const
/*!
Returns the string converted to a \c double value.
- Returns 0.0 if the conversion fails.
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for other reasons (e.g. underflow).
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index fa1a64a045..7bf6d1327e 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -83,7 +83,7 @@ private slots:
void matchingLocales();
void stringToDouble_data();
void stringToDouble();
- void stringToFloat_data() { stringToDouble_data(); }
+ void stringToFloat_data();
void stringToFloat();
void doubleToString_data();
void doubleToString();
@@ -155,6 +155,7 @@ private:
QString m_decimal, m_thousand, m_sdate, m_ldate, m_time;
QString m_sysapp;
bool europeanTimeZone;
+ void toReal_data();
class TransientLocale
{
@@ -679,7 +680,7 @@ void tst_QLocale::unixLocaleName()
#undef TEST_NAME
}
-void tst_QLocale::stringToDouble_data()
+void tst_QLocale::toReal_data()
{
QTest::addColumn<QString>("locale_name");
QTest::addColumn<QString>("num_str");
@@ -801,6 +802,32 @@ void tst_QLocale::stringToDouble_data()
QTest::newRow("de_DE 9.876543,0e--2") << QString("de_DE") << QString("9.876543,0e")+QChar(8722)+QString("2") << false << 0.0;
}
+void tst_QLocale::stringToDouble_data()
+{
+ toReal_data();
+ if (std::numeric_limits<double>::has_infinity) {
+ double huge = std::numeric_limits<double>::infinity();
+ QTest::newRow("C inf") << QString("C") << QString("inf") << true << huge;
+ QTest::newRow("C +inf") << QString("C") << QString("+inf") << true << +huge;
+ QTest::newRow("C -inf") << QString("C") << QString("-inf") << true << -huge;
+ // Overflow:
+ QTest::newRow("C huge") << QString("C") << QString("2e308") << false << huge;
+ QTest::newRow("C -huge") << QString("C") << QString("-2e308") << false << -huge;
+ }
+ if (std::numeric_limits<double>::has_quiet_NaN)
+ QTest::newRow("C qnan") << QString("C") << QString("NaN") << true << std::numeric_limits<double>::quiet_NaN();
+
+ // In range (but outside float's range):
+ QTest::newRow("C big") << QString("C") << QString("3.5e38") << true << 3.5e38;
+ QTest::newRow("C -big") << QString("C") << QString("-3.5e38") << true << -3.5e38;
+ QTest::newRow("C small") << QString("C") << QString("1e-45") << true << 1e-45;
+ QTest::newRow("C -small") << QString("C") << QString("-1e-45") << true << -1e-45;
+
+ // Underflow:
+ QTest::newRow("C tiny") << QString("C") << QString("2e-324") << false << 0.;
+ QTest::newRow("C -tiny") << QString("C") << QString("-2e-324") << false << 0.;
+}
+
void tst_QLocale::stringToDouble()
{
#define MY_DOUBLE_EPSILON (2.22045e-16) // 1/2^{52}; double has a 53-bit mantissa
@@ -825,28 +852,33 @@ void tst_QLocale::stringToDouble()
QCOMPARE(ok, good);
}
- if (ok) {
+ if (ok || std::isinf(num)) {
// First use fuzzy-compare, then a more precise check:
QCOMPARE(d, num);
- double diff = d - num;
- if (diff < 0)
- diff = -diff;
- QVERIFY(diff <= MY_DOUBLE_EPSILON);
+ if (std::isfinite(num)) {
+ double diff = d > num ? d - num : num - d;
+ QVERIFY(diff <= MY_DOUBLE_EPSILON);
+ }
}
d = locale.toDouble(num_strRef, &ok);
QCOMPARE(ok, good);
- if (ok) {
+ if (ok || std::isinf(num)) {
QCOMPARE(d, num);
- double diff = d - num;
- if (diff < 0)
- diff = -diff;
- QVERIFY(diff <= MY_DOUBLE_EPSILON);
+ if (std::isfinite(num)) {
+ double diff = d > num ? d - num : num - d;
+ QVERIFY(diff <= MY_DOUBLE_EPSILON);
+ }
}
#undef MY_DOUBLE_EPSILON
}
+void tst_QLocale::stringToFloat_data()
+{
+ toReal_data();
+}
+
void tst_QLocale::stringToFloat()
{
#define MY_FLOAT_EPSILON (2.384e-7) // 1/2^{22}; float has a 23-bit mantissa