Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:39

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/qbytearray.h>
0009 #include <QtCore/qstringliteral.h>
0010 #include <QtCore/qstringalgorithms.h>
0011 
0012 #include <string>
0013 #include <string_view>
0014 #include <QtCore/q20type_traits.h>
0015 
0016 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
0017 Q_FORWARD_DECLARE_CF_TYPE(CFString);
0018 Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
0019 #endif
0020 
0021 QT_BEGIN_NAMESPACE
0022 
0023 class QString;
0024 class QStringView;
0025 class QRegularExpression;
0026 class QRegularExpressionMatch;
0027 #ifdef Q_QDOC
0028 class QUtf8StringView;
0029 #endif
0030 
0031 namespace QtPrivate {
0032 template <typename Char>
0033 struct IsCompatibleCharTypeHelper
0034     : std::integral_constant<bool,
0035                              std::is_same<Char, QChar>::value ||
0036                              std::is_same<Char, ushort>::value ||
0037                              std::is_same<Char, char16_t>::value ||
0038                              (std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {};
0039 template <typename Char>
0040 struct IsCompatibleCharType
0041     : IsCompatibleCharTypeHelper<q20::remove_cvref_t<Char>> {};
0042 
0043 template <typename Pointer>
0044 struct IsCompatiblePointerHelper : std::false_type {};
0045 template <typename Char>
0046 struct IsCompatiblePointerHelper<Char*>
0047     : IsCompatibleCharType<Char> {};
0048 template <typename Pointer>
0049 struct IsCompatiblePointer
0050     : IsCompatiblePointerHelper<q20::remove_cvref_t<Pointer>> {};
0051 
0052 template <typename T, typename Enable = void>
0053 struct IsContainerCompatibleWithQStringView : std::false_type {};
0054 
0055 template <typename T>
0056 struct IsContainerCompatibleWithQStringView<T, std::enable_if_t<std::conjunction_v<
0057             // lacking concepts and ranges, we accept any T whose std::data yields a suitable pointer ...
0058             IsCompatiblePointer<decltype( std::data(std::declval<const T &>()) )>,
0059             // ... and that has a suitable size ...
0060             std::is_convertible<decltype( std::size(std::declval<const T &>()) ), qsizetype>,
0061             // ... and it's a range as it defines an iterator-like API
0062             IsCompatibleCharType<typename std::iterator_traits<decltype( std::begin(std::declval<const T &>()) )>::value_type>,
0063             std::is_convertible<
0064                 decltype( std::begin(std::declval<const T &>()) != std::end(std::declval<const T &>()) ),
0065                 bool>,
0066 
0067             // These need to be treated specially due to the empty vs null distinction
0068             std::negation<std::is_same<std::decay_t<T>, QString>>,
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 std::char_traits<Char>::length(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_ASSERT(len >= 0), Q_ASSERT(str || !len), len))
0134 #else
0135         : m_size((Q_ASSERT(len >= 0), Q_ASSERT(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 
0152     template <typename Pointer, if_compatible_pointer<Pointer> = true>
0153     constexpr QStringView(const Pointer &str) noexcept
0154         : QStringView(str, str ? lengthHelperPointer(str) : 0) {}
0155 #endif
0156 
0157 #ifdef Q_QDOC
0158     QStringView(const QString &str) noexcept;
0159 #else
0160     template <typename String, if_compatible_qstring_like<String> = true>
0161     QStringView(const String &str) noexcept
0162         : QStringView(str.isNull() ? nullptr : str.data(), qsizetype(str.size())) {}
0163 #endif
0164 
0165     template <typename Container, if_compatible_container<Container> = true>
0166     constexpr Q_ALWAYS_INLINE QStringView(const Container &c) noexcept
0167         : QStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {}
0168 
0169     template <typename Char, size_t Size, if_compatible_char<Char> = true>
0170     [[nodiscard]] constexpr static QStringView fromArray(const Char (&string)[Size]) noexcept
0171     { return QStringView(string, Size); }
0172 
0173     [[nodiscard]] inline QString toString() const; // defined in qstring.h
0174 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
0175     // defined in qcore_foundation.mm
0176     [[nodiscard]] Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
0177     [[nodiscard]] Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
0178 #endif
0179 
0180     [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
0181     [[nodiscard]] const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); }
0182     [[nodiscard]] const_pointer constData() const noexcept { return data(); }
0183     [[nodiscard]] constexpr const storage_type *utf16() const noexcept { return m_data; }
0184 
0185     [[nodiscard]] constexpr QChar operator[](qsizetype n) const
0186     { verify(n, 1); return QChar(m_data[n]); }
0187 
0188     //
0189     // QString API
0190     //
0191 
0192     template <typename...Args>
0193     [[nodiscard]] inline QString arg(Args &&...args) const; // defined in qstring.h
0194 
0195     [[nodiscard]] QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); }
0196     [[nodiscard]] QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); }
0197     [[nodiscard]] QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); }
0198     [[nodiscard]] inline QList<uint> toUcs4() const; // defined in qlist.h ### Qt 7 char32_t
0199 
0200     [[nodiscard]] constexpr QChar at(qsizetype n) const noexcept { return (*this)[n]; }
0201 
0202     [[nodiscard]] constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const noexcept
0203     {
0204         using namespace QtPrivate;
0205         auto result = QContainerImplHelper::mid(size(), &pos, &n);
0206         return result == QContainerImplHelper::Null ? QStringView() : QStringView(m_data + pos, n);
0207     }
0208     [[nodiscard]] constexpr QStringView left(qsizetype n) const noexcept
0209     {
0210         if (size_t(n) >= size_t(size()))
0211             n = size();
0212         return QStringView(m_data, n);
0213     }
0214     [[nodiscard]] constexpr QStringView right(qsizetype n) const noexcept
0215     {
0216         if (size_t(n) >= size_t(size()))
0217             n = size();
0218         return QStringView(m_data + m_size - n, n);
0219     }
0220 
0221     [[nodiscard]] constexpr QStringView first(qsizetype n) const noexcept
0222     { verify(0, n); return sliced(0, n); }
0223     [[nodiscard]] constexpr QStringView last(qsizetype n) const noexcept
0224     { verify(0, n); return sliced(size() - n, n); }
0225     [[nodiscard]] constexpr QStringView sliced(qsizetype pos) const noexcept
0226     { verify(pos, 0); return QStringView(m_data + pos, size() - pos); }
0227     [[nodiscard]] constexpr QStringView sliced(qsizetype pos, qsizetype n) const noexcept
0228     { verify(pos, n); return QStringView(m_data + pos, n); }
0229     [[nodiscard]] constexpr QStringView chopped(qsizetype n) const noexcept
0230     { verify(0, n); return sliced(0, m_size - n); }
0231 
0232     constexpr void truncate(qsizetype n) noexcept
0233     { verify(0, n); ; m_size = n; }
0234     constexpr void chop(qsizetype n) noexcept
0235     { verify(0, n); m_size -= n; }
0236 
0237     [[nodiscard]] QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
0238 
0239     template <typename Needle, typename...Flags>
0240     [[nodiscard]] constexpr inline auto tokenize(Needle &&needle, Flags...flags) const
0241         noexcept(noexcept(qTokenize(std::declval<const QStringView&>(), std::forward<Needle>(needle), flags...)))
0242             -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
0243     { return qTokenize(*this, std::forward<Needle>(needle), flags...); }
0244 
0245     [[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0246     { return QtPrivate::compareStrings(*this, other, cs); }
0247     [[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0248     [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0249     [[nodiscard]] constexpr int compare(QChar c) const noexcept
0250     { return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
0251     [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
0252     { return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
0253 
0254     [[nodiscard]] inline int localeAwareCompare(QStringView other) const;
0255 
0256     [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0257     { return QtPrivate::startsWith(*this, s, cs); }
0258     [[nodiscard]] inline bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0259     [[nodiscard]] bool startsWith(QChar c) const noexcept
0260     { return !empty() && front() == c; }
0261     [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
0262     { return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
0263 
0264     [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0265     { return QtPrivate::endsWith(*this, s, cs); }
0266     [[nodiscard]] inline bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0267     [[nodiscard]] bool endsWith(QChar c) const noexcept
0268     { return !empty() && back() == c; }
0269     [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
0270     { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
0271 
0272     [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0273     { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); }
0274     [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0275     { return QtPrivate::findString(*this, from, s, cs); }
0276     [[nodiscard]] inline qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0277 
0278     [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0279     { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); }
0280     [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0281     { return indexOf(s, 0, cs) != qsizetype(-1); }
0282     [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0283 
0284     [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0285     { return QtPrivate::count(*this, c, cs); }
0286     [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0287     { return QtPrivate::count(*this, s, cs); }
0288     [[nodiscard]] inline qsizetype count(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0289 
0290     [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0291     { return lastIndexOf(c, -1, cs); }
0292     [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0293     { return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); }
0294     [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0295     { return lastIndexOf(s, size(), cs); }
0296     [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0297     { return QtPrivate::lastIndexOf(*this, from, s, cs); }
0298     [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0299     [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0300 
0301 #if QT_CONFIG(regularexpression)
0302     [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const
0303     {
0304         return QtPrivate::indexOf(*this, re, from, rmatch);
0305     }
0306 #ifdef Q_QDOC
0307     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
0308 #else
0309     // prevent an ambiguity when called like this: lastIndexOf(re, 0)
0310     template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
0311     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
0312     {
0313         return QtPrivate::lastIndexOf(*this, re, size(), rmatch);
0314     }
0315 #endif
0316     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch = nullptr) const
0317     {
0318         return QtPrivate::lastIndexOf(*this, re, from, rmatch);
0319     }
0320     [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
0321     {
0322         return QtPrivate::contains(*this, re, rmatch);
0323     }
0324     [[nodiscard]] qsizetype count(const QRegularExpression &re) const
0325     {
0326         return QtPrivate::count(*this, re);
0327     }
0328 #endif
0329 
0330     [[nodiscard]] bool isRightToLeft() const noexcept
0331     { return QtPrivate::isRightToLeft(*this); }
0332     [[nodiscard]] bool isValidUtf16() const noexcept
0333     { return QtPrivate::isValidUtf16(*this); }
0334 
0335     [[nodiscard]] bool isUpper() const noexcept
0336     { return QtPrivate::isUpper(*this); }
0337     [[nodiscard]] bool isLower() const noexcept
0338     { return QtPrivate::isLower(*this); }
0339 
0340     [[nodiscard]] inline short toShort(bool *ok = nullptr, int base = 10) const;
0341     [[nodiscard]] inline ushort toUShort(bool *ok = nullptr, int base = 10) const;
0342     [[nodiscard]] inline int toInt(bool *ok = nullptr, int base = 10) const;
0343     [[nodiscard]] inline uint toUInt(bool *ok = nullptr, int base = 10) const;
0344     [[nodiscard]] inline long toLong(bool *ok = nullptr, int base = 10) const;
0345     [[nodiscard]] inline ulong toULong(bool *ok = nullptr, int base = 10) const;
0346     [[nodiscard]] inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
0347     [[nodiscard]] inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
0348     [[nodiscard]] Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const;
0349     [[nodiscard]] Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const;
0350 
0351     [[nodiscard]] inline qsizetype toWCharArray(wchar_t *array) const; // defined in qstring.h
0352 
0353 
0354     [[nodiscard]] Q_CORE_EXPORT
0355     QList<QStringView> split(QStringView sep,
0356                              Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
0357                              Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0358     [[nodiscard]] Q_CORE_EXPORT
0359     QList<QStringView> split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
0360                              Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
0361 
0362 #if QT_CONFIG(regularexpression)
0363     [[nodiscard]] Q_CORE_EXPORT
0364     QList<QStringView> split(const QRegularExpression &sep,
0365                              Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
0366 #endif
0367 
0368     // QStringView <> QStringView
0369     friend bool operator==(QStringView lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
0370     friend bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
0371     friend bool operator< (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <  0; }
0372     friend bool operator<=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
0373     friend bool operator> (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >  0; }
0374     friend bool operator>=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
0375 
0376     // QStringView <> QChar
0377     friend bool operator==(QStringView lhs, QChar rhs) noexcept { return lhs == QStringView(&rhs, 1); }
0378     friend bool operator!=(QStringView lhs, QChar rhs) noexcept { return lhs != QStringView(&rhs, 1); }
0379     friend bool operator< (QStringView lhs, QChar rhs) noexcept { return lhs <  QStringView(&rhs, 1); }
0380     friend bool operator<=(QStringView lhs, QChar rhs) noexcept { return lhs <= QStringView(&rhs, 1); }
0381     friend bool operator> (QStringView lhs, QChar rhs) noexcept { return lhs >  QStringView(&rhs, 1); }
0382     friend bool operator>=(QStringView lhs, QChar rhs) noexcept { return lhs >= QStringView(&rhs, 1); }
0383 
0384     friend bool operator==(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) == rhs; }
0385     friend bool operator!=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) != rhs; }
0386     friend bool operator< (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <  rhs; }
0387     friend bool operator<=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <= rhs; }
0388     friend bool operator> (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >  rhs; }
0389     friend bool operator>=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >= rhs; }
0390 
0391     //
0392     // STL compatibility API:
0393     //
0394     [[nodiscard]] const_iterator begin()   const noexcept { return data(); }
0395     [[nodiscard]] const_iterator end()     const noexcept { return data() + size(); }
0396     [[nodiscard]] const_iterator cbegin()  const noexcept { return begin(); }
0397     [[nodiscard]] const_iterator cend()    const noexcept { return end(); }
0398     [[nodiscard]] const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
0399     [[nodiscard]] const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
0400     [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0401     [[nodiscard]] const_reverse_iterator crend()   const noexcept { return rend(); }
0402 
0403     [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0404     [[nodiscard]] constexpr QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
0405     [[nodiscard]] constexpr QChar back()  const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
0406 
0407     [[nodiscard]] Q_IMPLICIT operator std::u16string_view() const noexcept
0408     { return std::u16string_view(m_data, size_t(m_size)); }
0409 
0410     //
0411     // Qt compatibility API:
0412     //
0413     [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); }
0414     [[nodiscard]] const_iterator constEnd() const noexcept { return end(); }
0415     [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0416     [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0417     [[nodiscard]] constexpr qsizetype length() const noexcept
0418     { return size(); }
0419     [[nodiscard]] constexpr QChar first() const { return front(); }
0420     [[nodiscard]] constexpr QChar last()  const { return back(); }
0421 private:
0422 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
0423     const storage_type *m_data = nullptr;
0424     qsizetype m_size = 0;
0425 #else
0426     qsizetype m_size = 0;
0427     const storage_type *m_data = nullptr;
0428 #endif
0429 
0430     Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0431                                           [[maybe_unused]] qsizetype n = 1) const
0432     {
0433         Q_ASSERT(pos >= 0);
0434         Q_ASSERT(pos <= size());
0435         Q_ASSERT(n >= 0);
0436         Q_ASSERT(n <= size() - pos);
0437     }
0438 
0439     constexpr int compare_single_char_helper(int diff) const noexcept
0440     { return diff ? diff : size() > 1 ? 1 : 0; }
0441 };
0442 Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE);
0443 
0444 template <typename QStringLike, typename std::enable_if<
0445     std::is_same<QStringLike, QString>::value,
0446     bool>::type = true>
0447 inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
0448 { return QStringView(s.data(), s.size()); }
0449 
0450 // QChar inline functions:
0451 
0452 [[nodiscard]] constexpr auto QChar::fromUcs4(char32_t c) noexcept
0453 {
0454     struct R {
0455         char16_t chars[2];
0456         [[nodiscard]] constexpr operator QStringView() const noexcept { return {begin(), end()}; }
0457         [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
0458         [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; }
0459         [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); }
0460     };
0461     return requiresSurrogates(c) ? R{{QChar::highSurrogate(c),
0462                                       QChar::lowSurrogate(c)}} :
0463                                    R{{char16_t(c), u'\0'}} ;
0464 }
0465 
0466 QT_END_NAMESPACE
0467 
0468 #endif /* QSTRINGVIEW_H */