summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2019-12-06 12:03:25 +0100
committerLars Knoll <lars.knoll@qt.io>2020-05-29 19:01:58 +0200
commitbeaef85b8d5cb4b0153f87736c56ef25eeec13d4 (patch)
treee3a540958cac590965210896884a469309fcc533
parentbf03396ad8e69369db0e9ee87aa7bb95e1a431a8 (diff)
Add toInt() and friends to QStringView
Make the API more symmetric with regards to both QString and QStringRef. Having this available helps making QStringView more of a drop-in replacement for QStringRef. QStringRef is planned to get removed in Qt 6. Change-Id: Ife036c0b55970078f42e1335442ff9ee5f4a2f0d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--src/corelib/text/qstring.cpp10
-rw-r--r--src/corelib/text/qstring.h18
-rw-r--r--src/corelib/text/qstringview.cpp219
-rw-r--r--src/corelib/text/qstringview.h11
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp113
5 files changed, 371 insertions, 0 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index b1313f0d39..12759c4a5b 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -12127,4 +12127,14 @@ void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out) n
qt_from_latin1(reinterpret_cast<char16_t *>(out), a, uint(len));
}
+double QStringView::toDouble(bool *ok) const
+{
+ return QLocaleData::c()->stringToDouble(*this, ok, QLocale::RejectGroupSeparator);
+}
+
+float QStringView::toFloat(bool *ok) const
+{
+ return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 54c286b945..45eb5f2474 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -1016,6 +1016,23 @@ public:
QString QStringView::toString() const
{ return Q_ASSERT(size() == length()), QString(data(), length()); }
+qint64 QStringView::toLongLong(bool *ok, int base) const
+{ return QString::toIntegral_helper<qint64>(*this, ok, base); }
+quint64 QStringView::toULongLong(bool *ok, int base) const
+{ return QString::toIntegral_helper<quint64>(*this, ok, base); }
+long QStringView::toLong(bool *ok, int base) const
+{ return QString::toIntegral_helper<long>(*this, ok, base); }
+ulong QStringView::toULong(bool *ok, int base) const
+{ return QString::toIntegral_helper<ulong>(*this, ok, base); }
+int QStringView::toInt(bool *ok, int base) const
+{ return QString::toIntegral_helper<int>(*this, ok, base); }
+uint QStringView::toUInt(bool *ok, int base) const
+{ return QString::toIntegral_helper<uint>(*this, ok, base); }
+short QStringView::toShort(bool *ok, int base) const
+{ return QString::toIntegral_helper<short>(*this, ok, base); }
+ushort QStringView::toUShort(bool *ok, int base) const
+{ return QString::toIntegral_helper<ushort>(*this, ok, base); }
+
//
// QString inline members
//
@@ -1073,6 +1090,7 @@ inline QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) c
{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
inline QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
+
#if QT_STRINGVIEW_LEVEL < 2
inline QString QString::arg(const QString &a1, const QString &a2) const
{ return qToStringViewIgnoringNull(*this).arg(a1, a2); }
diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp
index 16ccfa8352..8f87943204 100644
--- a/src/corelib/text/qstringview.cpp
+++ b/src/corelib/text/qstringview.cpp
@@ -39,6 +39,7 @@
#include "qstringview.h"
#include "qstring.h"
+#include "qlocale_p.h"
QT_BEGIN_NAMESPACE
@@ -912,4 +913,222 @@ QT_BEGIN_NAMESPACE
\sa QString::toWCharArray()
*/
+/*!
+ \fn qint64 QStringView::toLongLong(bool *ok, int base) const
+
+ Returns the string converted to a \c{long long} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toLongLong()
+
+ \sa QString::toLongLong()
+
+ \since 6.0
+*/
+
+/*!
+ \fn quint64 QStringView::toULongLong(bool *ok, int base) const
+
+ Returns the string converted to an \c{unsigned long long} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toULongLong()
+
+ \sa QString::toULongLong()
+
+ \since 6.0
+*/
+
+/*!
+ \fn long QStringView::toLong(bool *ok, int base) const
+
+ Returns the string converted to a \c long using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toLong()
+
+ \sa QString::toLong()
+
+ \since 6.0
+*/
+
+/*!
+ \fn ulong QStringView::toULong(bool *ok, int base) const
+
+ Returns the string converted to an \c{unsigned long} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toULongLong()
+
+ \sa QString::toULong()
+
+ \since 6.0
+*/
+
+/*!
+ \fn int QStringView::toInt(bool *ok, int base) const
+
+ Returns the string converted to an \c int using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toInt()
+
+ \sa QString::toInt()
+
+ \since 6.0
+*/
+
+/*!
+ \fn uint QStringView::toUInt(bool *ok, int base) const
+
+ Returns the string converted to an \c{unsigned int} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toUInt()
+
+ \sa QString::toUInt()
+
+ \since 6.0
+*/
+
+/*!
+ \fn short QStringView::toShort(bool *ok, int base) const
+
+ Returns the string converted to a \c short using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toShort()
+
+ \sa QString::toShort()
+
+ \since 6.0
+*/
+
+/*!
+ \fn ushort QStringView::toUShort(bool *ok, int base) const
+
+ Returns the string converted to an \c{unsigned short} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ If \a base is 0, the C language convention is used: If the string
+ begins with "0x", base 16 is used; if the string begins with "0",
+ base 8 is used; otherwise, base 10 is used.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toUShort()
+
+ \sa QString::toUShort()
+
+ \since 6.0
+*/
+
+/*!
+ \fn double QStringView::toDouble(bool *ok) const
+
+ Returns the string converted to a \c double value.
+
+ 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 \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toDouble()
+
+ For historic reasons, this function does not handle
+ thousands group separators. If you need to convert such numbers,
+ use QLocale::toDouble().
+
+ \sa QString::toDouble()
+
+ \since 6.0
+*/
+
+/*!
+ \fn float QStringView::toFloat(bool *ok) const
+
+ Returns the string converted to a \c float value.
+
+ 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 \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ The string conversion will always happen in the 'C' locale. For locale
+ dependent conversion use QLocale::toFloat()
+
+ \sa QString::toFloat()
+
+ \since 6.0
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h
index 0ae1772530..2b7863e156 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -320,6 +320,17 @@ public:
Q_REQUIRED_RESULT bool isValidUtf16() const noexcept
{ return QtPrivate::isValidUtf16(*this); }
+ Q_REQUIRED_RESULT inline short toShort(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline ushort toUShort(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline int toInt(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline uint toUInt(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline long toLong(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline ulong toULong(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
+ Q_REQUIRED_RESULT Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const;
+ Q_REQUIRED_RESULT Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const;
+
Q_REQUIRED_RESULT inline int toWCharArray(wchar_t *array) const; // defined in qstring.h
//
diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
index ed01d46dcd..0fdad63b24 100644
--- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -589,6 +589,20 @@ private Q_SLOTS:
void trim_trimmed_QByteArray_data() { trimmed_data(); }
void trim_trimmed_QByteArray() { trimmed_impl<QByteArray>(); }
+private:
+ void toNumber_data();
+ template <typename String> void toNumber_impl();
+
+private Q_SLOTS:
+ void toNumber_QString_data() { toNumber_data(); }
+ void toNumber_QString() { toNumber_impl<QString>(); }
+ void toNumber_QStringRef_data() { toNumber_data(); }
+ void toNumber_QStringRef() { toNumber_impl<QStringRef>(); }
+ void toNumber_QStringView_data() { toNumber_data(); }
+ void toNumber_QStringView() { toNumber_impl<QStringView>(); }
+ void toNumber_QByteArray_data() { toNumber_data(); }
+ void toNumber_QByteArray() { toNumber_impl<QByteArray>(); }
+
//
// UTF-16-only checks:
//
@@ -1600,6 +1614,105 @@ void tst_QStringApiSymmetry::trimmed_impl()
}
}
+void tst_QStringApiSymmetry::toNumber_data()
+{
+ QTest::addColumn<QString>("data");
+ QTest::addColumn<qint64>("result");
+ QTest::addColumn<bool>("ok");
+
+ QTest::addRow("0") << QString::fromUtf8("0") << qint64(0) << true;
+ QTest::addRow("a0") << QString::fromUtf8("a0") << qint64(0) << false;
+ QTest::addRow("10") << QString::fromUtf8("10") << qint64(10) << true;
+ QTest::addRow("-10") << QString::fromUtf8("-10") << qint64(-10) << true;
+ QTest::addRow("32767") << QString::fromUtf8("32767") << qint64(32767) << true;
+ QTest::addRow("32768") << QString::fromUtf8("32768") << qint64(32768) << true;
+ QTest::addRow("-32767") << QString::fromUtf8("-32767") << qint64(-32767) << true;
+ QTest::addRow("-32768") << QString::fromUtf8("-32768") << qint64(-32768) << true;
+ QTest::addRow("100x") << QString::fromUtf8("100x") << qint64(0) << false;
+ QTest::addRow("-100x") << QString::fromUtf8("-100x") << qint64(0) << false;
+}
+
+template<typename T>
+bool inRange(qint64 n)
+{
+ bool checkMax = quint64(std::numeric_limits<T>::max()) <= quint64(std::numeric_limits<qint64>::max());
+ if (checkMax && n > qint64(std::numeric_limits<T>::max()))
+ return false;
+ return qint64(std::numeric_limits<T>::min()) <= n;
+}
+
+template<typename String>
+void tst_QStringApiSymmetry::toNumber_impl()
+{
+ QFETCH(const QString, data);
+ QFETCH(qint64, result);
+ QFETCH(bool, ok);
+
+ const auto utf8 = data.toUtf8();
+ const auto l1s = data.toLatin1();
+ const auto l1 = l1s.isNull() ? QLatin1String() : QLatin1String(l1s);
+
+ const auto ref = data.isNull() ? QStringRef() : QStringRef(&data);
+ const auto s = make<String>(ref, l1, utf8);
+
+ bool is_ok = false;
+ qint64 n = 0;
+
+ n = s.toShort(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<short>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toUShort(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<ushort>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toInt(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<int>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toUInt(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<uint>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toLong(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<long>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toULong(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<ulong>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toLongLong(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<qlonglong>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ n = s.toULongLong(&is_ok);
+ QCOMPARE(is_ok, ok && inRange<qulonglong>(result));
+ if (is_ok)
+ QCOMPARE(n, result);
+
+ if (qint64(float(n)) == n) {
+ float f = s.toFloat(&is_ok);
+ QCOMPARE(is_ok, ok);
+ if (is_ok)
+ QCOMPARE(qint64(f), result);
+ }
+
+ if (qint64(double(n)) == n) {
+ double d = s.toDouble(&is_ok);
+ QCOMPARE(is_ok, ok);
+ if (is_ok)
+ QCOMPARE(qint64(d), result);
+ }
+}
+
//
//
// UTF-16-only checks: