summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qstringview.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qstringview.h')
-rw-r--r--src/corelib/text/qstringview.h137
1 files changed, 85 insertions, 52 deletions
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h
index 3dc8b5ce0b..ab97d834d3 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -5,11 +5,13 @@
#define QSTRINGVIEW_H
#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)
@@ -105,13 +107,8 @@ private:
template <typename Char>
static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
{
-#if defined(__cpp_lib_is_constant_evaluated)
- if (std::is_constant_evaluated())
+ if (q20::is_constant_evaluated())
return std::char_traits<Char>::length(str);
-#elif defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
- if (__builtin_constant_p(*str))
- return std::char_traits<Char>::length(str);
-#endif
return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
}
static qsizetype lengthHelperPointer(const QChar *str) noexcept
@@ -119,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::end(str);
- 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); }
@@ -181,8 +164,8 @@ 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
@@ -201,7 +184,7 @@ public:
[[nodiscard]] constexpr const storage_type *utf16() const noexcept { return m_data; }
[[nodiscard]] constexpr QChar operator[](qsizetype n) const
- { return Q_ASSERT(n >= 0), Q_ASSERT(n < size()), QChar(m_data[n]); }
+ { verify(n, 1); return QChar(m_data[n]); }
//
// QString API
@@ -237,20 +220,20 @@ public:
}
[[nodiscard]] constexpr QStringView first(qsizetype n) const noexcept
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data, n); }
+ { verify(0, n); return sliced(0, n); }
[[nodiscard]] constexpr QStringView last(qsizetype n) const noexcept
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data + size() - n, n); }
+ { verify(0, n); return sliced(size() - n, n); }
[[nodiscard]] constexpr QStringView sliced(qsizetype pos) const noexcept
- { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QStringView(m_data + pos, size() - pos); }
+ { verify(pos, 0); return QStringView(m_data + pos, size() - pos); }
[[nodiscard]] constexpr QStringView sliced(qsizetype pos, qsizetype n) const noexcept
- { 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); }
+ { verify(pos, n); return QStringView(m_data + pos, n); }
[[nodiscard]] constexpr QStringView chopped(qsizetype n) const noexcept
- { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, m_size - n); }
+ { verify(0, n); return sliced(0, m_size - n); }
constexpr void truncate(qsizetype n) noexcept
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
+ { verify(0, n); ; m_size = n; }
constexpr void chop(qsizetype n) noexcept
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
+ { verify(0, n); m_size -= n; }
[[nodiscard]] QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
@@ -288,7 +271,7 @@ public:
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
[[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); }
+ { 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); }
[[nodiscard]] inline qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
@@ -308,7 +291,7 @@ public:
[[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, QStringView(&c, 1), cs); }
+ { 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
@@ -350,6 +333,11 @@ public:
[[nodiscard]] bool isValidUtf16() const noexcept
{ return QtPrivate::isValidUtf16(*this); }
+ [[nodiscard]] bool isUpper() const noexcept
+ { return QtPrivate::isUpper(*this); }
+ [[nodiscard]] bool isLower() const noexcept
+ { return QtPrivate::isLower(*this); }
+
[[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;
@@ -379,27 +367,22 @@ public:
#endif
// QStringView <> QStringView
- friend bool operator==(QStringView lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
- friend bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
- friend bool operator< (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
- friend bool operator<=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
- friend bool operator> (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
- friend bool operator>=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
+ 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 operator==(QStringView lhs, QChar rhs) noexcept { return lhs == QStringView(&rhs, 1); }
- friend bool operator!=(QStringView lhs, QChar rhs) noexcept { return lhs != QStringView(&rhs, 1); }
- friend bool operator< (QStringView lhs, QChar rhs) noexcept { return lhs < QStringView(&rhs, 1); }
- friend bool operator<=(QStringView lhs, QChar rhs) noexcept { return lhs <= QStringView(&rhs, 1); }
- friend bool operator> (QStringView lhs, QChar rhs) noexcept { return lhs > QStringView(&rhs, 1); }
- friend bool operator>=(QStringView lhs, QChar rhs) noexcept { return lhs >= QStringView(&rhs, 1); }
-
- friend bool operator==(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) == rhs; }
- friend bool operator!=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) != rhs; }
- friend bool operator< (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) < rhs; }
- friend bool operator<=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <= rhs; }
- friend bool operator> (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) > rhs; }
- friend bool operator>=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >= rhs; }
+ 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:
@@ -417,6 +400,9 @@ public:
[[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:
//
@@ -437,8 +423,34 @@ private:
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);
@@ -446,7 +458,7 @@ 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:
@@ -464,6 +476,27 @@ inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
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 */