summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/text/qbytearray.cpp49
-rw-r--r--src/corelib/text/qbytearrayalgorithms.h47
-rw-r--r--src/corelib/text/qbytearrayview.h14
3 files changed, 75 insertions, 35 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 4b2896433c..ce86f8df83 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -3528,7 +3528,7 @@ bool QByteArray::isNull() const noexcept
return d->isNull();
}
-qlonglong QtPrivate::toSignedInteger(QByteArrayView data, bool *ok, int base)
+auto QtPrivate::toSignedInteger(QByteArrayView data, int base) -> ParsedNumber<qlonglong>
{
#if defined(QT_CHECK_RANGE)
if (base != 0 && (base < 2 || base > 36)) {
@@ -3536,16 +3536,17 @@ qlonglong QtPrivate::toSignedInteger(QByteArrayView data, bool *ok, int base)
base = 10;
}
#endif
- if (data.isEmpty()) {
- if (ok)
- *ok = false;
- return 0;
- }
+ if (data.isEmpty())
+ return {};
- return QLocaleData::bytearrayToLongLong(data, base, ok);
+ bool ok = false;
+ const auto i = QLocaleData::bytearrayToLongLong(data, base, &ok);
+ if (ok)
+ return ParsedNumber(i);
+ return {};
}
-qulonglong QtPrivate::toUnsignedInteger(QByteArrayView data, bool *ok, int base)
+auto QtPrivate::toUnsignedInteger(QByteArrayView data, int base) -> ParsedNumber<qulonglong>
{
#if defined(QT_CHECK_RANGE)
if (base != 0 && (base < 2 || base > 36)) {
@@ -3553,13 +3554,14 @@ qulonglong QtPrivate::toUnsignedInteger(QByteArrayView data, bool *ok, int base)
base = 10;
}
#endif
- if (data.isEmpty()) {
- if (ok)
- *ok = false;
- return 0;
- }
+ if (data.isEmpty())
+ return {};
- return QLocaleData::bytearrayToUnsLongLong(data, base, ok);
+ bool ok = false;
+ const auto u = QLocaleData::bytearrayToUnsLongLong(data, base, &ok);
+ if (ok)
+ return ParsedNumber(u);
+ return {};
}
/*!
@@ -3814,14 +3816,15 @@ double QByteArray::toDouble(bool *ok) const
return QByteArrayView(*this).toDouble(ok);
}
-double QtPrivate::toDouble(QByteArrayView a, bool *ok)
+auto QtPrivate::toDouble(QByteArrayView a) noexcept -> ParsedNumber<double>
{
bool nonNullOk = false;
int processed = 0;
double d = qt_asciiToDouble(a.data(), a.size(), nonNullOk, processed, WhitespacesAllowed);
- if (ok)
- *ok = nonNullOk;
- return d;
+ if (nonNullOk)
+ return ParsedNumber{d};
+ else
+ return {};
}
/*!
@@ -3854,9 +3857,15 @@ float QByteArray::toFloat(bool *ok) const
return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
}
-float QtPrivate::toFloat(QByteArrayView a, bool *ok)
+auto QtPrivate::toFloat(QByteArrayView a) noexcept -> ParsedNumber<float>
{
- return QLocaleData::convertDoubleToFloat(a.toDouble(ok), ok);
+ if (const auto r = toDouble(a)) {
+ bool ok = true;
+ const auto f = QLocaleData::convertDoubleToFloat(*r, &ok);
+ if (ok)
+ return ParsedNumber(f);
+ }
+ return {};
}
/*!
diff --git a/src/corelib/text/qbytearrayalgorithms.h b/src/corelib/text/qbytearrayalgorithms.h
index f80b97e04e..164868fa91 100644
--- a/src/corelib/text/qbytearrayalgorithms.h
+++ b/src/corelib/text/qbytearrayalgorithms.h
@@ -76,10 +76,31 @@ qsizetype count(QByteArrayView haystack, QByteArrayView needle) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf8(QByteArrayView s) noexcept;
-[[nodiscard]] Q_CORE_EXPORT double toDouble(QByteArrayView a, bool *ok);
-[[nodiscard]] Q_CORE_EXPORT float toFloat(QByteArrayView a, bool *ok);
-[[nodiscard]] Q_CORE_EXPORT qlonglong toSignedInteger(QByteArrayView data, bool *ok, int base);
-[[nodiscard]] Q_CORE_EXPORT qulonglong toUnsignedInteger(QByteArrayView data, bool *ok, int base);
+template <typename T>
+class ParsedNumber
+{
+ T m_value;
+ quint32 m_error : 1;
+ quint32 m_reserved : 31;
+ void *m_reserved2 = nullptr;
+public:
+ constexpr ParsedNumber() noexcept : m_value(), m_error(true), m_reserved(0) {}
+ constexpr explicit ParsedNumber(T v) : m_value(v), m_error(false), m_reserved(0) {}
+
+ // minimal optional-like API:
+ explicit operator bool() const noexcept { return !m_error; }
+ T &operator*() { Q_ASSERT(*this); return m_value; }
+ const T &operator*() const { Q_ASSERT(*this); return m_value; }
+ T *operator->() noexcept { return *this ? &m_value : nullptr; }
+ const T *operator->() const noexcept { return *this ? &m_value : nullptr; }
+ template <typename U> // not = T, as that'd allow calls that are incompatible with std::optional
+ T value_or(U &&u) const { return *this ? m_value : T(std::forward<U>(u)); }
+};
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<double> toDouble(QByteArrayView a) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<float> toFloat(QByteArrayView a) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<qlonglong> toSignedInteger(QByteArrayView data, int base);
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<qulonglong> toUnsignedInteger(QByteArrayView data, int base);
// QByteArrayView has incomplete type here, and we can't include qbytearrayview.h,
// since it includes qbytearrayalgorithms.h. Use the ByteArrayView template type as
@@ -88,18 +109,18 @@ template <typename T, typename ByteArrayView,
typename = std::enable_if_t<std::is_same_v<ByteArrayView, QByteArrayView>>>
static inline T toIntegral(ByteArrayView data, bool *ok, int base)
{
- auto val = [&] {
+ const auto val = [&] {
if constexpr (std::is_unsigned_v<T>)
- return toUnsignedInteger(data, ok, base);
+ return toUnsignedInteger(data, base);
else
- return toSignedInteger(data, ok, base);
+ return toSignedInteger(data, base);
}();
- if (T(val) != val) {
- if (ok)
- *ok = false;
- val = 0;
- }
- return T(val);
+ const bool failed = !val || T(*val) != *val;
+ if (ok)
+ *ok = !failed;
+ if (failed)
+ return 0;
+ return T(*val);
}
} // namespace QtPrivate
diff --git a/src/corelib/text/qbytearrayview.h b/src/corelib/text/qbytearrayview.h
index 40205cae9c..612dbc3e82 100644
--- a/src/corelib/text/qbytearrayview.h
+++ b/src/corelib/text/qbytearrayview.h
@@ -260,9 +260,19 @@ public:
[[nodiscard]] qulonglong toULongLong(bool *ok = nullptr, int base = 10) const
{ return QtPrivate::toIntegral<qulonglong>(*this, ok, base); }
[[nodiscard]] float toFloat(bool *ok = nullptr) const
- { return QtPrivate::toFloat(*this, ok); }
+ {
+ const auto r = QtPrivate::toFloat(*this);
+ if (ok)
+ *ok = bool(r);
+ return r.value_or(0.0f);
+ }
[[nodiscard]] double toDouble(bool *ok = nullptr) const
- { return QtPrivate::toDouble(*this, ok); }
+ {
+ const auto r = QtPrivate::toDouble(*this);
+ if (ok)
+ *ok = bool(r);
+ return r.value_or(0.0);
+ }
[[nodiscard]] bool startsWith(QByteArrayView other) const noexcept
{ return QtPrivate::startsWith(*this, other); }