Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-15 08:28:35

0001 // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
0002 // Copyright (C) 2019 Mail.ru Group.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 // Qt-Security score:critical reason:data-parser
0005 #ifndef QSTRINGVIEW_H
0006 #define QSTRINGVIEW_H
0007 
0008 #include <QtCore/qchar.h>
0009 #include <QtCore/qcompare.h>
0010 #include <QtCore/qcontainerfwd.h>
0011 #include <QtCore/qbytearray.h>
0012 #include <QtCore/qstringfwd.h>
0013 #include <QtCore/qstringalgorithms.h>
0014 
0015 #include <string>
0016 #include <string_view>
0017 #include <QtCore/q20type_traits.h>
0018 
0019 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
0020 Q_FORWARD_DECLARE_CF_TYPE(CFString);
0021 Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
0022 #endif
0023 
0024 QT_BEGIN_NAMESPACE
0025 
0026 class QRegularExpression;
0027 class QRegularExpressionMatch;
0028 
0029 namespace QtPrivate {
0030 template <typename Char>
0031 struct IsCompatibleCharTypeHelper
0032     : std::integral_constant<bool,
0033                              std::is_same<Char, QChar>::value ||
0034                              std::is_same<Char, ushort>::value ||
0035                              std::is_same<Char, char16_t>::value ||
0036                              (std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {};
0037 template <typename Char>
0038 struct IsCompatibleCharType
0039     : IsCompatibleCharTypeHelper<q20::remove_cvref_t<Char>> {};
0040 
0041 template <typename Pointer>
0042 struct IsCompatiblePointerHelper : std::false_type {};
0043 template <typename Char>
0044 struct IsCompatiblePointerHelper<Char*>
0045     : IsCompatibleCharType<Char> {};
0046 template <typename Pointer>
0047 struct IsCompatiblePointer
0048     : IsCompatiblePointerHelper<q20::remove_cvref_t<Pointer>> {};
0049 
0050 template <typename T, typename Enable = void>
0051 struct IsContainerCompatibleWithQStringView : std::false_type {};
0052 
0053 template <typename T>
0054 struct IsContainerCompatibleWithQStringView<T, std::enable_if_t<std::conjunction_v<
0055             // lacking concepts and ranges, we accept any T whose std::data yields a suitable pointer ...
0056             IsCompatiblePointer<decltype( std::data(std::declval<const T &>()) )>,
0057             // ... and that has a suitable size ...
0058             std::is_convertible<decltype( std::size(std::declval<const T &>()) ), qsizetype>,
0059             // ... and it's a range as it defines an iterator-like API
0060             IsCompatibleCharType<typename std::iterator_traits<decltype( std::begin(std::declval<const T &>()) )>::value_type>,
0061             std::is_convertible<
0062                 decltype( std::begin(std::declval<const T &>()) != std::end(std::declval<const T &>()) ),
0063                 bool>,
0064 
0065             // These need to be treated specially due to the empty vs null distinction
0066             std::negation<std::is_same<std::decay_t<T>, QString>>,
0067 #define QSTRINGVIEW_REFUSES_QSTRINGREF 1
0068             std::negation<std::is_same<q20::remove_cvref_t<T>, QStringRef>>, // QStringRef::op QStringView()
0069 
0070             // Don't make an accidental copy constructor
0071             std::negation<std::is_same<std::decay_t<T>, QStringView>>
0072         >>> : std::true_type {};
0073 
0074 } // namespace QtPrivate
0075 
0076 class QStringView
0077 {
0078 public:
0079     typedef char16_t storage_type;
0080     typedef const QChar value_type;
0081     typedef std::ptrdiff_t difference_type;
0082     typedef qsizetype size_type;
0083     typedef value_type &reference;
0084     typedef value_type &const_reference;
0085     typedef value_type *pointer;
0086     typedef value_type *const_pointer;
0087 
0088     typedef pointer iterator;
0089     typedef const_pointer const_iterator;
0090     typedef std::reverse_iterator<iterator> reverse_iterator;
0091     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0092 
0093 private:
0094     template <typename Char>
0095     using if_compatible_char = typename std::enable_if<QtPrivate::IsCompatibleCharType<Char>::value, bool>::type;
0096 
0097     template <typename Pointer>
0098     using if_compatible_pointer = typename std::enable_if<QtPrivate::IsCompatiblePointer<Pointer>::value, bool>::type;
0099 
0100     template <typename T>
0101     using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value, bool>::type;
0102 
0103     template <typename T>
0104     using if_compatible_container = typename std::enable_if<QtPrivate::IsContainerCompatibleWithQStringView<T>::value, bool>::type;
0105 
0106     template <typename Char>
0107     static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
0108     {
0109         if (q20::is_constant_evaluated())
0110             return QtPrivate::lengthHelperPointer(str);
0111         return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
0112     }
0113     static qsizetype lengthHelperPointer(const QChar *str) noexcept
0114     {
0115         return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
0116     }
0117 
0118     template <typename Char>
0119     static const storage_type *castHelper(const Char *str) noexcept
0120     { return reinterpret_cast<const storage_type*>(str); }
0121     static constexpr const storage_type *castHelper(const storage_type *str) noexcept
0122     { return str; }
0123 
0124 public:
0125     constexpr QStringView() noexcept {}
0126     constexpr QStringView(std::nullptr_t) noexcept
0127         : QStringView() {}
0128 
0129     template <typename Char, if_compatible_char<Char> = true>
0130     constexpr QStringView(const Char *str, qsizetype len)
0131 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
0132         : m_data(castHelper(str)),
0133           m_size((Q_PRE(len >= 0), Q_PRE(str || !len), len))
0134 #else
0135         : m_size((Q_PRE(len >= 0), Q_PRE(str || !len), len)),
0136           m_data(castHelper(str))
0137 #endif
0138     {}
0139 
0140     template <typename Char, if_compatible_char<Char> = true>
0141     constexpr QStringView(const Char *f, const Char *l)
0142         : QStringView(f, l - f) {}
0143 
0144 #ifdef Q_QDOC
0145     template <typename Char, size_t N>
0146     constexpr QStringView(const Char (&array)[N]) noexcept;
0147 
0148     template <typename Char>
0149     constexpr QStringView(const Char *str) noexcept;
0150 #else
0151     template <typename Pointer, if_compatible_pointer<Pointer> = true>
0152     constexpr QStringView(const Pointer &str) noexcept
0153         : QStringView(str, str ? lengthHelperPointer(str) : 0) {}
0154 
0155     template <typename Char, if_compatible_char<Char> = true>
0156     constexpr QStringView(const Char (&str)[]) noexcept // array of unknown bounds
0157         : QStringView{&*str} {} // decay to pointer
0158 #endif
0159 
0160 #ifdef Q_QDOC
0161     QStringView(const QString &str) noexcept;
0162 #else
0163     template <typename String, if_compatible_qstring_like<String> = true>
0164     QStringView(const String &str) noexcept
0165         : QStringView{str.begin(), str.size()} {}
0166 #endif
0167 
0168     template <typename Container, if_compatible_container<Container> = true>
0169     Q_ALWAYS_INLINE constexpr QStringView(const Container &c) noexcept
0170         : QStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {}
0171 
0172     template <typename Char, size_t Size, if_compatible_char<Char> = true>
0173     [[nodiscard]] constexpr static QStringView fromArray(const Char (&string)[Size]) noexcept
0174     { return QStringView(string, Size); }
0175 
0176     [[nodiscard]] inline QString toString() const; // defined in qstring.h
0177 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
0178     // defined in qcore_foundation.mm
0179     [[nodiscard]] Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
0180     [[nodiscard]] Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
0181 #endif
0182 
0183     [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
0184     [[nodiscard]] const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); }
0185     [[nodiscard]] const_pointer constData() const noexcept { return data(); }
0186     [[nodiscard]] constexpr const storage_type *utf16() const noexcept { return m_data; }
0187 
0188     [[nodiscard]] constexpr QChar operator[](qsizetype n) const
0189     { verify(n, 1); return QChar(m_data[n]); }
0190 
0191     //
0192     // QString API
0193     //
0194 
0195     template <typename...Args>
0196     [[nodiscard]] inline QString arg(Args &&...args) const; // defined in qstring.h
0197 
0198     [[nodiscard]] QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); }
0199     [[nodiscard]] QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); }
0200     [[nodiscard]] QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); }
0201     [[nodiscard]] inline QList<uint> toUcs4() const; // defined in qlist.h ### Qt 7 char32_t
0202 
0203     [[nodiscard]] constexpr QChar at(qsizetype n) const noexcept { return (*this)[n]; }
0204 
0205     [[nodiscard]] constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const noexcept
0206     {
0207         using namespace QtPrivate;
0208         auto result = QContainerImplHelper::mid(size(), &pos, &n);
0209         return result == QContainerImplHelper::Null ? QStringView() : QStringView(m_data + pos, n);
0210     }
0211     [[nodiscard]] constexpr QStringView left(qsizetype n) const noexcept
0212     {
0213         if (size_t(n) >= size_t(size()))
0214             n = size();
0215         return QStringView(m_data, n);
0216     }
0217     [[nodiscard]] constexpr QStringView right(qsizetype n) const noexcept
0218     {
0219         if (size_t(n) >= size_t(size()))
0220             n = size();
0221         return QStringView(m_data + m_size - n, n);
0222     }
0223 
0224     [[nodiscard]] constexpr QStringView first(qsizetype n) const noexcept
0225     { verify(0, n); return sliced(0, n); }
0226     [[nodiscard]] constexpr QStringView last(qsizetype n) const noexcept
0227     { verify(0, n); return sliced(size() - n, n); }
0228     [[nodiscard]] constexpr QStringView sliced(qsizetype pos) const noexcept
0229     { verify(pos, 0); return QStringView(m_data + pos, size() - pos); }
0230     [[nodiscard]] constexpr QStringView sliced(qsizetype pos, qsizetype n) const noexcept
0231     { verify(pos, n); return QStringView(m_data + pos, n); }
0232     [[nodiscard]] constexpr QStringView chopped(qsizetype n) const noexcept
0233     { verify(0, n); return sliced(0, m_size - n); }
0234 
0235     constexpr void truncate(qsizetype n) noexcept
0236     { verify(0, n); ; m_size = n; }
0237     constexpr void chop(qsizetype n) noexcept
0238     { verify(0, n); m_size -= n; }
0239 
0240     [[nodiscard]] QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
0241 
0242     constexpr QStringView &slice(qsizetype pos)
0243     { *this = sliced(pos); return *this; }
0244     constexpr QStringView &slice(qsizetype pos, qsizetype n)
0245     { *this = sliced(pos, n); return *this; }
0246 
0247     template <typename Needle, typename...Flags>
0248     [[nodiscard]] constexpr inline auto tokenize(Needle &&needle, Flags...flags) const
0249         noexcept(noexcept(qTokenize(std::declval<const QStringView&>(), std::forward<Needle>(needle), flags...)))
0250             -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
0251     { return qTokenize(*this, std::forward<Needle>(needle), flags...); }
0252 
0253     [[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0254     {
0255 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0256         if (__builtin_constant_p(other.m_size) && other.size() == 1)
0257             return compare(other.front(), cs);
0258 #endif
0259         return QtPrivate::compareStrings(*this, other, cs);
0260     }
0261     [[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0262     [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0263     [[nodiscard]] constexpr int compare(QChar c) const noexcept
0264     { return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
0265     [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
0266     {
0267 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0268         if (__builtin_constant_p(cs) && cs == Qt::CaseSensitive)
0269             return compare(c);
0270 #endif
0271         return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs);
0272     }
0273 
0274     [[nodiscard]] inline int localeAwareCompare(QStringView other) const;
0275 
0276     [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0277     {
0278 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0279         if (__builtin_constant_p(s.m_size) && s.size() == 1)
0280             return startsWith(s.front(), cs);
0281 #endif
0282         return QtPrivate::startsWith(*this, s, cs);
0283     }
0284     [[nodiscard]] inline bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0285     [[nodiscard]] bool startsWith(QChar c) const noexcept
0286     { return !empty() && front() == c; }
0287     [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
0288     {
0289 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0290         if (__builtin_constant_p(cs) && cs == Qt::CaseSensitive)
0291             return startsWith(c);
0292 #endif
0293         return QtPrivate::startsWith(*this, QStringView(&c, 1), cs);
0294     }
0295 
0296     [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0297     {
0298 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0299         if (__builtin_constant_p(s.m_size) && s.size() == 1)
0300             return endsWith(s.front(), cs);
0301 #endif
0302         return QtPrivate::endsWith(*this, s, cs);
0303     }
0304     [[nodiscard]] inline bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0305     [[nodiscard]] bool endsWith(QChar c) const noexcept
0306     { return !empty() && back() == c; }
0307     [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
0308     {
0309 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0310         if (__builtin_constant_p(cs) && cs == Qt::CaseSensitive)
0311             return endsWith(c);
0312 #endif
0313         return QtPrivate::endsWith(*this, QStringView(&c, 1), cs);
0314     }
0315 
0316     [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0317     { return QtPrivate::findString(*this, from, c.unicode(), cs); }
0318     [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0319     {
0320 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0321         if (__builtin_constant_p(s.m_size) && s.size() == 1)
0322             return indexOf(s.front(), from, cs);
0323 #endif
0324         return QtPrivate::findString(*this, from, s, cs);
0325     }
0326     [[nodiscard]] inline qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0327 
0328     [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0329     { return indexOf(c, 0, cs) != qsizetype(-1); }
0330     [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0331     { return indexOf(s, 0, cs) != qsizetype(-1); }
0332     [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0333 
0334     [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0335     { return QtPrivate::count(*this, c, cs); }
0336     [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0337     {
0338 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0339         if (__builtin_constant_p(s.m_size) && s.size() == 1)
0340             return count(s.front(), cs);
0341 #endif
0342         return QtPrivate::count(*this, s, cs);
0343     }
0344     [[nodiscard]] inline qsizetype count(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0345 
0346     [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0347     { return lastIndexOf(c, -1, cs); }
0348     [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0349     { return QtPrivate::lastIndexOf(*this, from, c.unicode(), cs); }
0350     [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0351     { return lastIndexOf(s, size(), cs); }
0352     [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0353     {
0354 #if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
0355         if (__builtin_constant_p(s.m_size) && s.size() == 1)
0356             return lastIndexOf(s.front(), from, cs);
0357 #endif
0358         return QtPrivate::lastIndexOf(*this, from, s, cs);
0359     }
0360     [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0361     [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0362 
0363 #if QT_CONFIG(regularexpression)
0364     [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const
0365     {
0366         return QtPrivate::indexOf(*this, re, from, rmatch);
0367     }
0368 #ifdef Q_QDOC
0369     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
0370 #else
0371     // prevent an ambiguity when called like this: lastIndexOf(re, 0)
0372     template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
0373     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
0374     {
0375         return QtPrivate::lastIndexOf(*this, re, size(), rmatch);
0376     }
0377 #endif
0378     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch = nullptr) const
0379     {
0380         return QtPrivate::lastIndexOf(*this, re, from, rmatch);
0381     }
0382     [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
0383     {
0384         return QtPrivate::contains(*this, re, rmatch);
0385     }
0386     [[nodiscard]] qsizetype count(const QRegularExpression &re) const; // defined in qregularexpression.h
0387 #endif
0388 
0389     [[nodiscard]] bool isRightToLeft() const noexcept
0390     { return QtPrivate::isRightToLeft(*this); }
0391     [[nodiscard]] bool isValidUtf16() const noexcept
0392     { return QtPrivate::isValidUtf16(*this); }
0393 
0394     [[nodiscard]] bool isUpper() const noexcept
0395     { return QtPrivate::isUpper(*this); }
0396     [[nodiscard]] bool isLower() const noexcept
0397     { return QtPrivate::isLower(*this); }
0398 
0399     [[nodiscard]] inline short toShort(bool *ok = nullptr, int base = 10) const;
0400     [[nodiscard]] inline ushort toUShort(bool *ok = nullptr, int base = 10) const;
0401     [[nodiscard]] inline int toInt(bool *ok = nullptr, int base = 10) const;
0402     [[nodiscard]] inline uint toUInt(bool *ok = nullptr, int base = 10) const;
0403     [[nodiscard]] inline long toLong(bool *ok = nullptr, int base = 10) const;
0404     [[nodiscard]] inline ulong toULong(bool *ok = nullptr, int base = 10) const;
0405     [[nodiscard]] inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
0406     [[nodiscard]] inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
0407     [[nodiscard]] Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const;
0408     [[nodiscard]] Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const;
0409 
0410     [[nodiscard]] inline qsizetype toWCharArray(wchar_t *array) const; // defined in qstring.h
0411 
0412 
0413     [[nodiscard]] Q_CORE_EXPORT
0414     QList<QStringView> split(QStringView sep,
0415                              Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
0416                              Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0417     [[nodiscard]] Q_CORE_EXPORT
0418     QList<QStringView> split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
0419                              Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0420 
0421 #if QT_CONFIG(regularexpression)
0422     [[nodiscard]] Q_CORE_EXPORT
0423     QList<QStringView> split(const QRegularExpression &sep,
0424                              Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
0425 #endif
0426 
0427     // QStringView <> QStringView
0428     friend bool comparesEqual(const QStringView &lhs, const QStringView &rhs) noexcept
0429     { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
0430     friend Qt::strong_ordering
0431     compareThreeWay(const QStringView &lhs, const QStringView &rhs) noexcept
0432     {
0433         const int res = QtPrivate::compareStrings(lhs, rhs);
0434         return Qt::compareThreeWay(res, 0);
0435     }
0436     Q_DECLARE_STRONGLY_ORDERED(QStringView)
0437 
0438     // QStringView <> QChar
0439     friend bool comparesEqual(const QStringView &lhs, QChar rhs) noexcept
0440     { return lhs.size() == 1 && lhs[0] == rhs; }
0441     friend Qt::strong_ordering compareThreeWay(const QStringView &lhs, QChar rhs) noexcept
0442     { return compareThreeWay(lhs, QStringView(&rhs, 1)); }
0443     Q_DECLARE_STRONGLY_ORDERED(QStringView, QChar)
0444 
0445     //
0446     // STL compatibility API:
0447     //
0448     [[nodiscard]] const_iterator begin()   const noexcept { return data(); }
0449     [[nodiscard]] const_iterator end()     const noexcept { return data() + size(); }
0450     [[nodiscard]] const_iterator cbegin()  const noexcept { return begin(); }
0451     [[nodiscard]] const_iterator cend()    const noexcept { return end(); }
0452     [[nodiscard]] const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
0453     [[nodiscard]] const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
0454     [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0455     [[nodiscard]] const_reverse_iterator crend()   const noexcept { return rend(); }
0456 
0457     [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0458     [[nodiscard]] constexpr QChar front() const { return Q_PRE(!empty()), QChar(m_data[0]); }
0459     [[nodiscard]] constexpr QChar back()  const { return Q_PRE(!empty()), QChar(m_data[m_size - 1]); }
0460 
0461     [[nodiscard]] constexpr Q_IMPLICIT operator std::u16string_view() const noexcept
0462     { return std::u16string_view(m_data, size_t(m_size)); }
0463 
0464     [[nodiscard]] constexpr qsizetype max_size() const noexcept { return maxSize(); }
0465 
0466     //
0467     // Qt compatibility API:
0468     //
0469     [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); }
0470     [[nodiscard]] const_iterator constEnd() const noexcept { return end(); }
0471     [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0472     [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0473     [[nodiscard]] constexpr qsizetype length() const noexcept
0474     { return size(); }
0475     [[nodiscard]] constexpr QChar first() const { return front(); }
0476     [[nodiscard]] constexpr QChar last()  const { return back(); }
0477 
0478     [[nodiscard]] static constexpr qsizetype maxSize() noexcept
0479     {
0480         // -1 to deal with the pointer one-past-the-end;
0481         return QtPrivate::MaxAllocSize / sizeof(storage_type) - 1;
0482     }
0483 private:
0484 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
0485     const storage_type *m_data = nullptr;
0486     qsizetype m_size = 0;
0487 #else
0488     qsizetype m_size = 0;
0489     const storage_type *m_data = nullptr;
0490 #endif
0491 
0492     Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0493                                           [[maybe_unused]] qsizetype n = 1) const
0494     {
0495         Q_PRE(pos >= 0);
0496         Q_PRE(pos <= size());
0497         Q_PRE(n >= 0);
0498         Q_PRE(n <= size() - pos);
0499     }
0500 
0501     constexpr int compare_single_char_helper(int diff) const noexcept
0502     { return diff ? diff : size() > 1 ? 1 : 0; }
0503 
0504     Q_CORE_EXPORT static bool equal_helper(QStringView sv, const char *data, qsizetype len);
0505     Q_CORE_EXPORT static int compare_helper(QStringView sv, const char *data, qsizetype len);
0506 
0507 #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
0508     friend bool comparesEqual(const QStringView &lhs, const QByteArrayView &rhs) noexcept
0509     { return equal_helper(lhs, rhs.data(), rhs.size()); }
0510     friend Qt::strong_ordering
0511     compareThreeWay(const QStringView &lhs, const QByteArrayView &rhs) noexcept
0512     {
0513         const int res = compare_helper(lhs, rhs.data(), rhs.size());
0514         return Qt::compareThreeWay(res, 0);
0515     }
0516     Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArrayView, QT_ASCII_CAST_WARN)
0517     Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArray, QT_ASCII_CAST_WARN)
0518     Q_DECLARE_STRONGLY_ORDERED(QStringView, const char *, QT_ASCII_CAST_WARN)
0519 #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
0520 };
0521 Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE);
0522 
0523 template <typename QStringLike, typename std::enable_if<
0524     std::is_same<QStringLike, QString>::value,
0525     bool>::type = true>
0526 inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
0527 { return QStringView(s.begin(), s.size()); }
0528 
0529 // QChar inline functions:
0530 
0531 [[nodiscard]] constexpr auto QChar::fromUcs4(char32_t c) noexcept
0532 {
0533     struct R {
0534         char16_t chars[2];
0535         [[nodiscard]] constexpr operator QStringView() const noexcept { return {begin(), end()}; }
0536         [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
0537         [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; }
0538         [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); }
0539     };
0540     return requiresSurrogates(c) ? R{{QChar::highSurrogate(c),
0541                                       QChar::lowSurrogate(c)}} :
0542                                    R{{char16_t(c), u'\0'}} ;
0543 }
0544 
0545 qsizetype QtPrivate::findString(QStringView str, qsizetype from, QChar ch, Qt::CaseSensitivity cs) noexcept
0546 {
0547     if (from < -str.size()) // from < 0 && abs(from) > str.size(), avoiding overflow
0548         return -1;
0549     if (from < 0)
0550         from = qMax(from + str.size(), qsizetype(0));
0551     if (from < str.size()) {
0552         const char16_t *s = str.utf16();
0553         char16_t c = ch.unicode();
0554         const char16_t *n = s + from;
0555         const char16_t *e = s + str.size();
0556         if (cs == Qt::CaseSensitive)
0557             n = qustrchr(QStringView(n, e), c);
0558         else
0559             n = qustrcasechr(QStringView(n, e), c);
0560         if (n != e)
0561             return n - s;
0562     }
0563     return -1;
0564 }
0565 
0566 namespace Qt {
0567 inline namespace Literals {
0568 inline namespace StringLiterals {
0569 constexpr QStringView operator""_sv(const char16_t *str, size_t size) noexcept
0570 {
0571     return QStringView(str, qsizetype(size));
0572 }
0573 } // StringLiterals
0574 } // Literals
0575 } // Qt
0576 
0577 QT_END_NAMESPACE
0578 
0579 #endif /* QSTRINGVIEW_H */