diff options
Diffstat (limited to 'src/corelib/text/qstringview.h')
-rw-r--r-- | src/corelib/text/qstringview.h | 434 |
1 files changed, 247 insertions, 187 deletions
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h index a4d0a78e5b..ab97d834d3 100644 --- a/src/corelib/text/qstringview.h +++ b/src/corelib/text/qstringview.h @@ -1,65 +1,18 @@ -/**************************************************************************** -** -** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> -** Copyright (C) 2019 Mail.ru Group. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +// Copyright (C) 2019 Mail.ru Group. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSTRINGVIEW_H #define QSTRINGVIEW_H -/* - This macro enables three "levels" of QStringView support: - - 1. offer QStringView, overload some functions taking QString with - QStringView - - 2. Obsolete: QStringRef and its overloads have been removed. - - 3. like 2, but replace functions taking QString, too. -*/ -#ifndef QT_STRINGVIEW_LEVEL -# define QT_STRINGVIEW_LEVEL 1 -#endif - #include <QtCore/qchar.h> +#include <QtCore/qcompare.h> #include <QtCore/qbytearray.h> #include <QtCore/qstringliteral.h> #include <QtCore/qstringalgorithms.h> #include <string> +#include <string_view> +#include <QtCore/q20type_traits.h> #if defined(Q_OS_DARWIN) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFString); @@ -71,6 +24,10 @@ QT_BEGIN_NAMESPACE class QString; class QStringView; class QRegularExpression; +class QRegularExpressionMatch; +#ifdef Q_QDOC +class QUtf8StringView; +#endif namespace QtPrivate { template <typename Char> @@ -82,7 +39,7 @@ struct IsCompatibleCharTypeHelper (std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {}; template <typename Char> struct IsCompatibleCharType - : IsCompatibleCharTypeHelper<typename std::remove_cv<typename std::remove_reference<Char>::type>::type> {}; + : IsCompatibleCharTypeHelper<q20::remove_cvref_t<Char>> {}; template <typename Pointer> struct IsCompatiblePointerHelper : std::false_type {}; @@ -91,7 +48,7 @@ struct IsCompatiblePointerHelper<Char*> : IsCompatibleCharType<Char> {}; template <typename Pointer> struct IsCompatiblePointer - : IsCompatiblePointerHelper<typename std::remove_cv<typename std::remove_reference<Pointer>::type>::type> {}; + : IsCompatiblePointerHelper<q20::remove_cvref_t<Pointer>> {}; template <typename T, typename Enable = void> struct IsContainerCompatibleWithQStringView : std::false_type {}; @@ -148,16 +105,10 @@ private: using if_compatible_container = typename std::enable_if<QtPrivate::IsContainerCompatibleWithQStringView<T>::value, bool>::type; template <typename Char> - static qsizetype lengthHelperPointer(const Char *str) noexcept + static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept { -#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) - if (__builtin_constant_p(*str)) { - qsizetype result = 0; - while (*str++) - ++result; - return result; - } -#endif + if (q20::is_constant_evaluated()) + return std::char_traits<Char>::length(str); return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str)); } static qsizetype lengthHelperPointer(const QChar *str) noexcept @@ -165,20 +116,6 @@ private: return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str)); } - template <typename Container> - static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept - { - return qsizetype(std::size(c)); - } - - template <typename Char, size_t N> - static constexpr qsizetype lengthHelperContainer(const Char (&str)[N]) noexcept - { - const auto it = std::char_traits<Char>::find(str, N, Char(0)); - const auto end = it ? it : std::next(str, N); - return qsizetype(std::distance(str, end)); - } - template <typename Char> static const storage_type *castHelper(const Char *str) noexcept { return reinterpret_cast<const storage_type*>(str); } @@ -186,21 +123,26 @@ private: { return str; } public: - constexpr QStringView() noexcept - : m_size(0), m_data(nullptr) {} + constexpr QStringView() noexcept {} constexpr QStringView(std::nullptr_t) noexcept : QStringView() {} template <typename Char, if_compatible_char<Char> = true> constexpr QStringView(const Char *str, qsizetype len) +#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) + : m_data(castHelper(str)), + m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)) +#else : m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)), - m_data(castHelper(str)) {} + m_data(castHelper(str)) +#endif + {} template <typename Char, if_compatible_char<Char> = true> constexpr QStringView(const Char *f, const Char *l) : QStringView(f, l - f) {} -#ifdef Q_CLANG_QDOC +#ifdef Q_QDOC template <typename Char, size_t N> constexpr QStringView(const Char (&array)[N]) noexcept; @@ -213,7 +155,7 @@ public: : QStringView(str, str ? lengthHelperPointer(str) : 0) {} #endif -#ifdef Q_CLANG_QDOC +#ifdef Q_QDOC QStringView(const QString &str) noexcept; #else template <typename String, if_compatible_qstring_like<String> = true> @@ -222,196 +164,293 @@ public: #endif template <typename Container, if_compatible_container<Container> = true> - constexpr QStringView(const Container &c) noexcept - : QStringView(std::data(c), lengthHelperContainer(c)) {} + constexpr Q_ALWAYS_INLINE QStringView(const Container &c) noexcept + : QStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {} template <typename Char, size_t Size, if_compatible_char<Char> = true> [[nodiscard]] constexpr static QStringView fromArray(const Char (&string)[Size]) noexcept { return QStringView(string, Size); } - Q_REQUIRED_RESULT inline QString toString() const; // defined in qstring.h + [[nodiscard]] inline QString toString() const; // defined in qstring.h #if defined(Q_OS_DARWIN) || defined(Q_QDOC) // defined in qcore_foundation.mm - Q_REQUIRED_RESULT Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED; - Q_REQUIRED_RESULT Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED; + [[nodiscard]] Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED; + [[nodiscard]] Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED; #endif - Q_REQUIRED_RESULT constexpr qsizetype size() const noexcept { return m_size; } - Q_REQUIRED_RESULT const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); } - Q_REQUIRED_RESULT const_pointer constData() const noexcept { return data(); } - Q_REQUIRED_RESULT constexpr const storage_type *utf16() const noexcept { return m_data; } + [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; } + [[nodiscard]] const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); } + [[nodiscard]] const_pointer constData() const noexcept { return data(); } + [[nodiscard]] constexpr const storage_type *utf16() const noexcept { return m_data; } - Q_REQUIRED_RESULT constexpr QChar operator[](qsizetype n) const - { return Q_ASSERT(n >= 0), Q_ASSERT(n < size()), QChar(m_data[n]); } + [[nodiscard]] constexpr QChar operator[](qsizetype n) const + { verify(n, 1); return QChar(m_data[n]); } // // QString API // template <typename...Args> - Q_REQUIRED_RESULT inline QString arg(Args &&...args) const; // defined in qstring.h + [[nodiscard]] inline QString arg(Args &&...args) const; // defined in qstring.h - Q_REQUIRED_RESULT QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); } - Q_REQUIRED_RESULT QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); } - Q_REQUIRED_RESULT QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); } - Q_REQUIRED_RESULT inline QList<uint> toUcs4() const; // defined in qlist.h + [[nodiscard]] QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); } + [[nodiscard]] QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); } + [[nodiscard]] QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); } + [[nodiscard]] inline QList<uint> toUcs4() const; // defined in qlist.h ### Qt 7 char32_t - Q_REQUIRED_RESULT constexpr QChar at(qsizetype n) const { return (*this)[n]; } + [[nodiscard]] constexpr QChar at(qsizetype n) const noexcept { return (*this)[n]; } - Q_REQUIRED_RESULT constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const + [[nodiscard]] constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const noexcept { using namespace QtPrivate; auto result = QContainerImplHelper::mid(size(), &pos, &n); return result == QContainerImplHelper::Null ? QStringView() : QStringView(m_data + pos, n); } - Q_REQUIRED_RESULT constexpr QStringView left(qsizetype n) const + [[nodiscard]] constexpr QStringView left(qsizetype n) const noexcept { if (size_t(n) >= size_t(size())) n = size(); return QStringView(m_data, n); } - Q_REQUIRED_RESULT constexpr QStringView right(qsizetype n) const + [[nodiscard]] constexpr QStringView right(qsizetype n) const noexcept { if (size_t(n) >= size_t(size())) n = size(); return QStringView(m_data + m_size - n, n); } - Q_REQUIRED_RESULT constexpr QStringView first(qsizetype n) const - { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data, n); } - Q_REQUIRED_RESULT constexpr QStringView last(qsizetype n) const - { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data + size() - n, n); } - Q_REQUIRED_RESULT constexpr QStringView sliced(qsizetype pos) const - { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QStringView(m_data + pos, size() - pos); } - Q_REQUIRED_RESULT constexpr QStringView sliced(qsizetype pos, qsizetype n) const - { Q_ASSERT(pos >= 0); Q_ASSERT(n >= 0); Q_ASSERT(size_t(pos) + size_t(n) <= size_t(size())); return QStringView(m_data + pos, n); } - Q_REQUIRED_RESULT constexpr QStringView chopped(qsizetype n) const - { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, m_size - n); } + [[nodiscard]] constexpr QStringView first(qsizetype n) const noexcept + { verify(0, n); return sliced(0, n); } + [[nodiscard]] constexpr QStringView last(qsizetype n) const noexcept + { verify(0, n); return sliced(size() - n, n); } + [[nodiscard]] constexpr QStringView sliced(qsizetype pos) const noexcept + { verify(pos, 0); return QStringView(m_data + pos, size() - pos); } + [[nodiscard]] constexpr QStringView sliced(qsizetype pos, qsizetype n) const noexcept + { verify(pos, n); return QStringView(m_data + pos, n); } + [[nodiscard]] constexpr QStringView chopped(qsizetype n) const noexcept + { verify(0, n); return sliced(0, m_size - n); } - constexpr void truncate(qsizetype n) - { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; } - constexpr void chop(qsizetype n) - { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; } + constexpr void truncate(qsizetype n) noexcept + { verify(0, n); ; m_size = n; } + constexpr void chop(qsizetype n) noexcept + { verify(0, n); m_size -= n; } - Q_REQUIRED_RESULT QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); } + [[nodiscard]] QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); } template <typename Needle, typename...Flags> - Q_REQUIRED_RESULT constexpr inline auto tokenize(Needle &&needle, Flags...flags) const + [[nodiscard]] constexpr inline auto tokenize(Needle &&needle, Flags...flags) const noexcept(noexcept(qTokenize(std::declval<const QStringView&>(), std::forward<Needle>(needle), flags...))) -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...)) { return qTokenize(*this, std::forward<Needle>(needle), flags...); } - Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::compareStrings(*this, other, cs); } - Q_REQUIRED_RESULT inline int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; - Q_REQUIRED_RESULT constexpr int compare(QChar c) const noexcept + [[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] constexpr int compare(QChar c) const noexcept { return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; } - Q_REQUIRED_RESULT int compare(QChar c, Qt::CaseSensitivity cs) const noexcept + [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); } - Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] inline int localeAwareCompare(QStringView other) const; + + [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::startsWith(*this, s, cs); } - Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; - Q_REQUIRED_RESULT bool startsWith(QChar c) const noexcept + [[nodiscard]] inline bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] bool startsWith(QChar c) const noexcept { return !empty() && front() == c; } - Q_REQUIRED_RESULT bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept + [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); } - Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::endsWith(*this, s, cs); } - Q_REQUIRED_RESULT inline bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; - Q_REQUIRED_RESULT bool endsWith(QChar c) const noexcept + [[nodiscard]] inline bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] bool endsWith(QChar c) const noexcept { return !empty() && back() == c; } - Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept + [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); } - Q_REQUIRED_RESULT qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept - { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); } - Q_REQUIRED_RESULT qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return QtPrivate::findString(*this, from, c.unicode(), cs); } + [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::findString(*this, from, s, cs); } - Q_REQUIRED_RESULT inline qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] inline qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; - Q_REQUIRED_RESULT bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); } - Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return indexOf(s, 0, cs) != qsizetype(-1); } - Q_REQUIRED_RESULT inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; - Q_REQUIRED_RESULT qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::count(*this, c, cs); } - Q_REQUIRED_RESULT qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::count(*this, s, cs); } - - Q_REQUIRED_RESULT qsizetype lastIndexOf(QChar c, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept - { return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); } - Q_REQUIRED_RESULT qsizetype lastIndexOf(QStringView s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + [[nodiscard]] inline qsizetype count(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return lastIndexOf(c, -1, cs); } + [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return QtPrivate::lastIndexOf(*this, from, c.unicode(), cs); } + [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return lastIndexOf(s, size(), cs); } + [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::lastIndexOf(*this, from, s, cs); } - Q_REQUIRED_RESULT inline qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; - Q_REQUIRED_RESULT bool isRightToLeft() const noexcept +#if QT_CONFIG(regularexpression) + [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const + { + return QtPrivate::indexOf(*this, re, from, rmatch); + } +#ifdef Q_QDOC + [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const; +#else + // prevent an ambiguity when called like this: lastIndexOf(re, 0) + template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false> + [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const + { + return QtPrivate::lastIndexOf(*this, re, size(), rmatch); + } +#endif + [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch = nullptr) const + { + return QtPrivate::lastIndexOf(*this, re, from, rmatch); + } + [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const + { + return QtPrivate::contains(*this, re, rmatch); + } + [[nodiscard]] qsizetype count(const QRegularExpression &re) const + { + return QtPrivate::count(*this, re); + } +#endif + + [[nodiscard]] bool isRightToLeft() const noexcept { return QtPrivate::isRightToLeft(*this); } - Q_REQUIRED_RESULT bool isValidUtf16() const noexcept + [[nodiscard]] 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; + [[nodiscard]] bool isUpper() const noexcept + { return QtPrivate::isUpper(*this); } + [[nodiscard]] bool isLower() const noexcept + { return QtPrivate::isLower(*this); } - Q_REQUIRED_RESULT inline qsizetype toWCharArray(wchar_t *array) const; // defined in qstring.h + [[nodiscard]] inline short toShort(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline ushort toUShort(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline int toInt(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline uint toUInt(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline long toLong(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline ulong toULong(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const; + [[nodiscard]] Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const; + [[nodiscard]] Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const; + [[nodiscard]] inline qsizetype toWCharArray(wchar_t *array) const; // defined in qstring.h - Q_REQUIRED_RESULT Q_CORE_EXPORT + + [[nodiscard]] Q_CORE_EXPORT QList<QStringView> split(QStringView sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; - Q_REQUIRED_RESULT Q_CORE_EXPORT + [[nodiscard]] Q_CORE_EXPORT QList<QStringView> split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; #if QT_CONFIG(regularexpression) - Q_REQUIRED_RESULT Q_CORE_EXPORT + [[nodiscard]] Q_CORE_EXPORT QList<QStringView> split(const QRegularExpression &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const; #endif + // QStringView <> QStringView + friend bool comparesEqual(const QStringView &lhs, const QStringView &rhs) noexcept + { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); } + friend Qt::strong_ordering + compareThreeWay(const QStringView &lhs, const QStringView &rhs) noexcept + { + const int res = QtPrivate::compareStrings(lhs, rhs); + return Qt::compareThreeWay(res, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QStringView) + + // QStringView <> QChar + friend bool comparesEqual(const QStringView &lhs, QChar rhs) noexcept + { return lhs.size() == 1 && lhs[0] == rhs; } + friend Qt::strong_ordering compareThreeWay(const QStringView &lhs, QChar rhs) noexcept + { return compareThreeWay(lhs, QStringView(&rhs, 1)); } + Q_DECLARE_STRONGLY_ORDERED(QStringView, QChar) + // // STL compatibility API: // - Q_REQUIRED_RESULT const_iterator begin() const noexcept { return data(); } - Q_REQUIRED_RESULT const_iterator end() const noexcept { return data() + size(); } - Q_REQUIRED_RESULT const_iterator cbegin() const noexcept { return begin(); } - Q_REQUIRED_RESULT const_iterator cend() const noexcept { return end(); } - Q_REQUIRED_RESULT const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - Q_REQUIRED_RESULT const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - Q_REQUIRED_RESULT const_reverse_iterator crbegin() const noexcept { return rbegin(); } - Q_REQUIRED_RESULT const_reverse_iterator crend() const noexcept { return rend(); } - - Q_REQUIRED_RESULT constexpr bool empty() const noexcept { return size() == 0; } - Q_REQUIRED_RESULT constexpr QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); } - Q_REQUIRED_RESULT constexpr QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); } + [[nodiscard]] const_iterator begin() const noexcept { return data(); } + [[nodiscard]] const_iterator end() const noexcept { return data() + size(); } + [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); } + [[nodiscard]] const_iterator cend() const noexcept { return end(); } + [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } + [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); } + [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); } + + [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } + [[nodiscard]] constexpr QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); } + [[nodiscard]] constexpr QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); } + + [[nodiscard]] Q_IMPLICIT operator std::u16string_view() const noexcept + { return std::u16string_view(m_data, size_t(m_size)); } // // Qt compatibility API: // - Q_REQUIRED_RESULT constexpr bool isNull() const noexcept { return !m_data; } - Q_REQUIRED_RESULT constexpr bool isEmpty() const noexcept { return empty(); } - Q_REQUIRED_RESULT constexpr int length() const /* not nothrow! */ - { return Q_ASSERT(int(size()) == size()), int(size()); } - Q_REQUIRED_RESULT constexpr QChar first() const { return front(); } - Q_REQUIRED_RESULT constexpr QChar last() const { return back(); } + [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); } + [[nodiscard]] const_iterator constEnd() const noexcept { return end(); } + [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; } + [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); } + [[nodiscard]] constexpr qsizetype length() const noexcept + { return size(); } + [[nodiscard]] constexpr QChar first() const { return front(); } + [[nodiscard]] constexpr QChar last() const { return back(); } private: - qsizetype m_size; - const storage_type *m_data; +#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) + const storage_type *m_data = nullptr; + qsizetype m_size = 0; +#else + qsizetype m_size = 0; + const storage_type *m_data = nullptr; +#endif + + Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0, + [[maybe_unused]] qsizetype n = 1) const + { + Q_ASSERT(pos >= 0); + Q_ASSERT(pos <= size()); + Q_ASSERT(n >= 0); + Q_ASSERT(n <= size() - pos); + } constexpr int compare_single_char_helper(int diff) const noexcept { return diff ? diff : size() > 1 ? 1 : 0; } + + Q_CORE_EXPORT static bool equal_helper(QStringView sv, const char *data, qsizetype len); + Q_CORE_EXPORT static int compare_helper(QStringView sv, const char *data, qsizetype len); + +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) + friend bool comparesEqual(const QStringView &lhs, const QByteArrayView &rhs) noexcept + { return equal_helper(lhs, rhs.data(), rhs.size()); } + friend Qt::strong_ordering + compareThreeWay(const QStringView &lhs, const QByteArrayView &rhs) noexcept + { + const int res = compare_helper(lhs, rhs.data(), rhs.size()); + return Qt::compareThreeWay(res, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArrayView, QT_ASCII_CAST_WARN) + Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArray, QT_ASCII_CAST_WARN) + Q_DECLARE_STRONGLY_ORDERED(QStringView, const char *, QT_ASCII_CAST_WARN) +#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) }; Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE); @@ -419,24 +458,45 @@ template <typename QStringLike, typename std::enable_if< std::is_same<QStringLike, QString>::value, bool>::type = true> inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept -{ return QStringView(s.data(), s.size()); } +{ return QStringView(s.begin(), s.size()); } // QChar inline functions: -Q_REQUIRED_RESULT constexpr auto QChar::fromUcs4(char32_t c) noexcept +[[nodiscard]] constexpr auto QChar::fromUcs4(char32_t c) noexcept { struct R { char16_t chars[2]; - Q_REQUIRED_RESULT constexpr operator QStringView() const noexcept { return {begin(), end()}; } - Q_REQUIRED_RESULT constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; } - Q_REQUIRED_RESULT constexpr const char16_t *begin() const noexcept { return chars; } - Q_REQUIRED_RESULT constexpr const char16_t *end() const noexcept { return begin() + size(); } + [[nodiscard]] constexpr operator QStringView() const noexcept { return {begin(), end()}; } + [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; } + [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; } + [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); } }; return requiresSurrogates(c) ? R{{QChar::highSurrogate(c), QChar::lowSurrogate(c)}} : R{{char16_t(c), u'\0'}} ; } +qsizetype QtPrivate::findString(QStringView str, qsizetype from, QChar ch, Qt::CaseSensitivity cs) noexcept +{ + if (from < -str.size()) // from < 0 && abs(from) > str.size(), avoiding overflow + return -1; + if (from < 0) + from = qMax(from + str.size(), qsizetype(0)); + if (from < str.size()) { + const char16_t *s = str.utf16(); + char16_t c = ch.unicode(); + const char16_t *n = s + from; + const char16_t *e = s + str.size(); + if (cs == Qt::CaseSensitive) + n = qustrchr(QStringView(n, e), c); + else + n = qustrcasechr(QStringView(n, e), c); + if (n != e) + return n - s; + } + return -1; +} + QT_END_NAMESPACE #endif /* QSTRINGVIEW_H */ |