Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qstringview.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 #ifndef QSTRINGVIEW_H
0005 #define QSTRINGVIEW_H
0006 
0007 #include <QtCore/qchar.h>
0008 #include <QtCore/qcompare.h>
0009 #include <QtCore/qcontainerfwd.h>
0010 #include <QtCore/qbytearray.h>
0011 #include <QtCore/qstringfwd.h>
0012 #include <QtCore/qstringliteral.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     constexpr Q_ALWAYS_INLINE 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     { return QtPrivate::compareStrings(*this, other, cs); }
0255     [[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0256     [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0257     [[nodiscard]] constexpr int compare(QChar c) const noexcept
0258     { return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
0259     [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
0260     { return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
0261 
0262     [[nodiscard]] inline int localeAwareCompare(QStringView other) const;
0263 
0264     [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0265     { return QtPrivate::startsWith(*this, s, cs); }
0266     [[nodiscard]] inline bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0267     [[nodiscard]] bool startsWith(QChar c) const noexcept
0268     { return !empty() && front() == c; }
0269     [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
0270     { return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
0271 
0272     [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0273     { return QtPrivate::endsWith(*this, s, cs); }
0274     [[nodiscard]] inline bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0275     [[nodiscard]] bool endsWith(QChar c) const noexcept
0276     { return !empty() && back() == c; }
0277     [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
0278     { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
0279 
0280     [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0281     { return QtPrivate::findString(*this, from, c.unicode(), cs); }
0282     [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0283     { return QtPrivate::findString(*this, from, s, cs); }
0284     [[nodiscard]] inline qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0285 
0286     [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0287     { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); }
0288     [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0289     { return indexOf(s, 0, cs) != qsizetype(-1); }
0290     [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0291 
0292     [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0293     { return QtPrivate::count(*this, c, cs); }
0294     [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0295     { return QtPrivate::count(*this, s, cs); }
0296     [[nodiscard]] inline qsizetype count(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0297 
0298     [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0299     { return lastIndexOf(c, -1, cs); }
0300     [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0301     { return QtPrivate::lastIndexOf(*this, from, c.unicode(), cs); }
0302     [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0303     { return lastIndexOf(s, size(), cs); }
0304     [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0305     { return QtPrivate::lastIndexOf(*this, from, s, cs); }
0306     [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0307     [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0308 
0309 #if QT_CONFIG(regularexpression)
0310     [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const
0311     {
0312         return QtPrivate::indexOf(*this, re, from, rmatch);
0313     }
0314 #ifdef Q_QDOC
0315     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
0316 #else
0317     // prevent an ambiguity when called like this: lastIndexOf(re, 0)
0318     template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
0319     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
0320     {
0321         return QtPrivate::lastIndexOf(*this, re, size(), rmatch);
0322     }
0323 #endif
0324     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch = nullptr) const
0325     {
0326         return QtPrivate::lastIndexOf(*this, re, from, rmatch);
0327     }
0328     [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
0329     {
0330         return QtPrivate::contains(*this, re, rmatch);
0331     }
0332     [[nodiscard]] qsizetype count(const QRegularExpression &re) const
0333     {
0334         return QtPrivate::count(*this, re);
0335     }
0336 #endif
0337 
0338     [[nodiscard]] bool isRightToLeft() const noexcept
0339     { return QtPrivate::isRightToLeft(*this); }
0340     [[nodiscard]] bool isValidUtf16() const noexcept
0341     { return QtPrivate::isValidUtf16(*this); }
0342 
0343     [[nodiscard]] bool isUpper() const noexcept
0344     { return QtPrivate::isUpper(*this); }
0345     [[nodiscard]] bool isLower() const noexcept
0346     { return QtPrivate::isLower(*this); }
0347 
0348     [[nodiscard]] inline short toShort(bool *ok = nullptr, int base = 10) const;
0349     [[nodiscard]] inline ushort toUShort(bool *ok = nullptr, int base = 10) const;
0350     [[nodiscard]] inline int toInt(bool *ok = nullptr, int base = 10) const;
0351     [[nodiscard]] inline uint toUInt(bool *ok = nullptr, int base = 10) const;
0352     [[nodiscard]] inline long toLong(bool *ok = nullptr, int base = 10) const;
0353     [[nodiscard]] inline ulong toULong(bool *ok = nullptr, int base = 10) const;
0354     [[nodiscard]] inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
0355     [[nodiscard]] inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
0356     [[nodiscard]] Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const;
0357     [[nodiscard]] Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const;
0358 
0359     [[nodiscard]] inline qsizetype toWCharArray(wchar_t *array) const; // defined in qstring.h
0360 
0361 
0362     [[nodiscard]] Q_CORE_EXPORT
0363     QList<QStringView> split(QStringView sep,
0364                              Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
0365                              Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0366     [[nodiscard]] Q_CORE_EXPORT
0367     QList<QStringView> split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
0368                              Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0369 
0370 #if QT_CONFIG(regularexpression)
0371     [[nodiscard]] Q_CORE_EXPORT
0372     QList<QStringView> split(const QRegularExpression &sep,
0373                              Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
0374 #endif
0375 
0376     // QStringView <> QStringView
0377     friend bool comparesEqual(const QStringView &lhs, const QStringView &rhs) noexcept
0378     { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
0379     friend Qt::strong_ordering
0380     compareThreeWay(const QStringView &lhs, const QStringView &rhs) noexcept
0381     {
0382         const int res = QtPrivate::compareStrings(lhs, rhs);
0383         return Qt::compareThreeWay(res, 0);
0384     }
0385     Q_DECLARE_STRONGLY_ORDERED(QStringView)
0386 
0387     // QStringView <> QChar
0388     friend bool comparesEqual(const QStringView &lhs, QChar rhs) noexcept
0389     { return lhs.size() == 1 && lhs[0] == rhs; }
0390     friend Qt::strong_ordering compareThreeWay(const QStringView &lhs, QChar rhs) noexcept
0391     { return compareThreeWay(lhs, QStringView(&rhs, 1)); }
0392     Q_DECLARE_STRONGLY_ORDERED(QStringView, QChar)
0393 
0394     //
0395     // STL compatibility API:
0396     //
0397     [[nodiscard]] const_iterator begin()   const noexcept { return data(); }
0398     [[nodiscard]] const_iterator end()     const noexcept { return data() + size(); }
0399     [[nodiscard]] const_iterator cbegin()  const noexcept { return begin(); }
0400     [[nodiscard]] const_iterator cend()    const noexcept { return end(); }
0401     [[nodiscard]] const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
0402     [[nodiscard]] const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
0403     [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0404     [[nodiscard]] const_reverse_iterator crend()   const noexcept { return rend(); }
0405 
0406     [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0407     [[nodiscard]] constexpr QChar front() const { return Q_PRE(!empty()), QChar(m_data[0]); }
0408     [[nodiscard]] constexpr QChar back()  const { return Q_PRE(!empty()), QChar(m_data[m_size - 1]); }
0409 
0410     [[nodiscard]] Q_IMPLICIT operator std::u16string_view() const noexcept
0411     { return std::u16string_view(m_data, size_t(m_size)); }
0412 
0413     [[nodiscard]] constexpr qsizetype max_size() const noexcept { return maxSize(); }
0414 
0415     //
0416     // Qt compatibility API:
0417     //
0418     [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); }
0419     [[nodiscard]] const_iterator constEnd() const noexcept { return end(); }
0420     [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0421     [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0422     [[nodiscard]] constexpr qsizetype length() const noexcept
0423     { return size(); }
0424     [[nodiscard]] constexpr QChar first() const { return front(); }
0425     [[nodiscard]] constexpr QChar last()  const { return back(); }
0426 
0427     [[nodiscard]] static constexpr qsizetype maxSize() noexcept
0428     {
0429         // -1 to deal with the pointer one-past-the-end;
0430         return QtPrivate::MaxAllocSize / sizeof(storage_type) - 1;
0431     }
0432 private:
0433 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
0434     const storage_type *m_data = nullptr;
0435     qsizetype m_size = 0;
0436 #else
0437     qsizetype m_size = 0;
0438     const storage_type *m_data = nullptr;
0439 #endif
0440 
0441     Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0442                                           [[maybe_unused]] qsizetype n = 1) const
0443     {
0444         Q_PRE(pos >= 0);
0445         Q_PRE(pos <= size());
0446         Q_PRE(n >= 0);
0447         Q_PRE(n <= size() - pos);
0448     }
0449 
0450     constexpr int compare_single_char_helper(int diff) const noexcept
0451     { return diff ? diff : size() > 1 ? 1 : 0; }
0452 
0453     Q_CORE_EXPORT static bool equal_helper(QStringView sv, const char *data, qsizetype len);
0454     Q_CORE_EXPORT static int compare_helper(QStringView sv, const char *data, qsizetype len);
0455 
0456 #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
0457     friend bool comparesEqual(const QStringView &lhs, const QByteArrayView &rhs) noexcept
0458     { return equal_helper(lhs, rhs.data(), rhs.size()); }
0459     friend Qt::strong_ordering
0460     compareThreeWay(const QStringView &lhs, const QByteArrayView &rhs) noexcept
0461     {
0462         const int res = compare_helper(lhs, rhs.data(), rhs.size());
0463         return Qt::compareThreeWay(res, 0);
0464     }
0465     Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArrayView, QT_ASCII_CAST_WARN)
0466     Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArray, QT_ASCII_CAST_WARN)
0467     Q_DECLARE_STRONGLY_ORDERED(QStringView, const char *, QT_ASCII_CAST_WARN)
0468 #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
0469 };
0470 Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE);
0471 
0472 template <typename QStringLike, typename std::enable_if<
0473     std::is_same<QStringLike, QString>::value,
0474     bool>::type = true>
0475 inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
0476 { return QStringView(s.begin(), s.size()); }
0477 
0478 // QChar inline functions:
0479 
0480 [[nodiscard]] constexpr auto QChar::fromUcs4(char32_t c) noexcept
0481 {
0482     struct R {
0483         char16_t chars[2];
0484         [[nodiscard]] constexpr operator QStringView() const noexcept { return {begin(), end()}; }
0485         [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
0486         [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; }
0487         [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); }
0488     };
0489     return requiresSurrogates(c) ? R{{QChar::highSurrogate(c),
0490                                       QChar::lowSurrogate(c)}} :
0491                                    R{{char16_t(c), u'\0'}} ;
0492 }
0493 
0494 qsizetype QtPrivate::findString(QStringView str, qsizetype from, QChar ch, Qt::CaseSensitivity cs) noexcept
0495 {
0496     if (from < -str.size()) // from < 0 && abs(from) > str.size(), avoiding overflow
0497         return -1;
0498     if (from < 0)
0499         from = qMax(from + str.size(), qsizetype(0));
0500     if (from < str.size()) {
0501         const char16_t *s = str.utf16();
0502         char16_t c = ch.unicode();
0503         const char16_t *n = s + from;
0504         const char16_t *e = s + str.size();
0505         if (cs == Qt::CaseSensitive)
0506             n = qustrchr(QStringView(n, e), c);
0507         else
0508             n = qustrcasechr(QStringView(n, e), c);
0509         if (n != e)
0510             return n - s;
0511     }
0512     return -1;
0513 }
0514 
0515 QT_END_NAMESPACE
0516 
0517 #endif /* QSTRINGVIEW_H */