From 88b54cc22a45f9724c201e7249ac79deb55ff48a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 27 Aug 2021 15:48:12 +0200 Subject: [PATCH] Rework QLocalePrivate::bytearrayToU?LongLong() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change it to take a QByteArrayView instead of a plain char *; all its callers do know the size and propagating it enables the implementation to call strntou?ll() rather than strtou?ll(), thereby escaping the need for '\0'-termination. Fixes: QTBUG-74286 Change-Id: Ie9394786e9fcf25c1d1be2421805f47c018d13bb Reviewed-by: Thiago Macieira Reviewed-by: MÄrten Nordheim --- src/corelib/text/qbytearray.cpp | 24 +++++++------- src/corelib/text/qlocale.cpp | 55 +++++++++++++++++++-------------- src/corelib/text/qlocale_p.h | 6 ++-- src/gui/util/qvalidator.cpp | 6 ++-- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 70526825f3..320f744c4f 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -3507,18 +3507,18 @@ bool QByteArray::isNull() const return d->isNull(); } -static qlonglong toIntegral_helper(const char *data, bool *ok, int base, qlonglong) +static qlonglong toIntegral_helper(QByteArrayView data, bool *ok, int base, qlonglong) { return QLocaleData::bytearrayToLongLong(data, base, ok); } -static qulonglong toIntegral_helper(const char *data, bool *ok, int base, qulonglong) +static qulonglong toIntegral_helper(QByteArrayView data, bool *ok, int base, qulonglong) { return QLocaleData::bytearrayToUnsLongLong(data, base, ok); } template static inline -T toIntegral_helper(const char *data, bool *ok, int base) +T toIntegral_helper(QByteArrayView data, bool *ok, int base) { using Int64 = typename std::conditional::value, qulonglong, qlonglong>::type; @@ -3528,7 +3528,7 @@ T toIntegral_helper(const char *data, bool *ok, int base) base = 10; } #endif - if (!data) { + if (data.isEmpty()) { if (ok) *ok = false; return 0; @@ -3568,7 +3568,7 @@ T toIntegral_helper(const char *data, bool *ok, int base) qlonglong QByteArray::toLongLong(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3595,7 +3595,7 @@ qlonglong QByteArray::toLongLong(bool *ok, int base) const qulonglong QByteArray::toULongLong(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3624,7 +3624,7 @@ qulonglong QByteArray::toULongLong(bool *ok, int base) const int QByteArray::toInt(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3651,7 +3651,7 @@ int QByteArray::toInt(bool *ok, int base) const uint QByteArray::toUInt(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3681,7 +3681,7 @@ uint QByteArray::toUInt(bool *ok, int base) const */ long QByteArray::toLong(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3709,7 +3709,7 @@ long QByteArray::toLong(bool *ok, int base) const */ ulong QByteArray::toULong(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3736,7 +3736,7 @@ ulong QByteArray::toULong(bool *ok, int base) const short QByteArray::toShort(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } /*! @@ -3763,7 +3763,7 @@ short QByteArray::toShort(bool *ok, int base) const ushort QByteArray::toUShort(bool *ok, int base) const { - return toIntegral_helper(nulTerminated().constData(), ok, base); + return toIntegral_helper(*this, ok, base); } diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index db8e1fe563..5abc4d3a09 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -3997,7 +3997,7 @@ qlonglong QLocaleData::stringToLongLong(QStringView str, int base, bool *ok, return 0; } - return bytearrayToLongLong(buff.constData(), base, ok); + return bytearrayToLongLong(QByteArrayView(buff.constData(), buff.size()), base, ok); } qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok, @@ -4010,34 +4010,34 @@ qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok, return 0; } - return bytearrayToUnsLongLong(buff.constData(), base, ok); + return bytearrayToUnsLongLong(QByteArrayView(buff.constData(), buff.size()), base, ok); } -qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok) +qlonglong QLocaleData::bytearrayToLongLong(QByteArrayView num, int base, bool *ok) { + if (num.isEmpty() || num.at(0) == '\0') { + if (ok != nullptr) + *ok = false; + return 0; + } + bool _ok; const char *endptr; + const qlonglong l = qstrntoll(num.data(), num.size(), &endptr, base, &_ok); - if (*num == '\0') { + if (!_ok || endptr == num.data()) { if (ok != nullptr) *ok = false; return 0; } - qlonglong l = qstrtoll(num, &endptr, base, &_ok); - - if (!_ok) { - if (ok != nullptr) - *ok = false; - return 0; - } - - if (*endptr != '\0') { - while (ascii_isspace(*endptr)) + const char *const stop = num.end(); + if (endptr < stop && *endptr != '\0') { + while (endptr < stop && ascii_isspace(*endptr)) ++endptr; } - if (*endptr != '\0') { + if (endptr < stop && *endptr != '\0') { // we stopped at a non-digit character after converting some digits if (ok != nullptr) *ok = false; @@ -4049,24 +4049,31 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok) return l; } -qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool *ok) +qulonglong QLocaleData::bytearrayToUnsLongLong(QByteArrayView num, int base, bool *ok) { - bool _ok; - const char *endptr; - qulonglong l = qstrtoull(num, &endptr, base, &_ok); - - if (!_ok) { + if (num.isEmpty() || num.at(0) == '\0') { if (ok != nullptr) *ok = false; return 0; } - if (*endptr != '\0') { - while (ascii_isspace(*endptr)) + bool _ok; + const char *endptr; + const qulonglong l = qstrntoull(num.data(), num.size(), &endptr, base, &_ok); + + if (!_ok || endptr == num.data()) { + if (ok != nullptr) + *ok = false; + return 0; + } + + const char *const stop = num.end(); + if (endptr < stop && *endptr != '\0') { + while (endptr < stop && ascii_isspace(*endptr)) ++endptr; } - if (*endptr != '\0') { + if (endptr < stop && *endptr != '\0') { if (ok != nullptr) *ok = false; return 0; diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h index a547dad7b7..da39be9ce1 100644 --- a/src/corelib/text/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -276,8 +276,8 @@ public: quint64 stringToUnsLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const; // this function is used in QIntValidator (QtGui) - Q_CORE_EXPORT static qint64 bytearrayToLongLong(const char *num, int base, bool *ok); - static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok); + Q_CORE_EXPORT static qint64 bytearrayToLongLong(QByteArrayView num, int base, bool *ok); + static quint64 bytearrayToUnsLongLong(QByteArrayView num, int base, bool *ok); bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options, CharBuff *result) const; diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index f15057801b..95d8b2a542 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2012 KlarÀlvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo ** Contact: https://www.qt.io/licensing/ ** @@ -421,7 +421,7 @@ QValidator::State QIntValidator::validate(QString & input, int&) const return Intermediate; bool ok; - qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok); + qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok); if (!ok) return Invalid; @@ -456,7 +456,7 @@ void QIntValidator::fixup(QString &input) const return; } bool ok; - qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok); + qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok); if (ok) input = locale().toString(entered); }