diff options
Diffstat (limited to 'src/corelib/text/qanystringview.h')
-rw-r--r-- | src/corelib/text/qanystringview.h | 116 |
1 files changed, 46 insertions, 70 deletions
diff --git a/src/corelib/text/qanystringview.h b/src/corelib/text/qanystringview.h index 6bf301cfd2..075d64679c 100644 --- a/src/corelib/text/qanystringview.h +++ b/src/corelib/text/qanystringview.h @@ -4,6 +4,7 @@ #ifndef QANYSTRINGVIEW_H #define QANYSTRINGVIEW_H +#include <QtCore/qcompare.h> #include <QtCore/qlatin1stringview.h> #include <QtCore/qstringview.h> #include <QtCore/qutf8stringview.h> @@ -61,10 +62,13 @@ private: }; template <typename Char> - using if_compatible_char = std::enable_if_t<std::disjunction_v< + using is_compatible_char = std::disjunction< QtPrivate::IsCompatibleCharType<Char>, QtPrivate::IsCompatibleChar8Type<Char> - >, bool>; + >; + + template <typename Char> + using if_compatible_char = std::enable_if_t<is_compatible_char<Char>::value, bool>; template <typename Pointer> using if_compatible_pointer = std::enable_if_t<std::disjunction_v< @@ -86,6 +90,7 @@ private: std::is_same<q20::remove_cvref_t<T>, QAnyStringView::Tag>, std::is_same<q20::remove_cvref_t<T>, QAnyStringView>, // don't make a copy/move ctor std::is_pointer<std::decay_t<T>>, // const char*, etc + is_compatible_char<T>, // don't create a QString/QByteArray, we have a ctor std::is_same<q20::remove_cvref_t<T>, QByteArray>, std::is_same<q20::remove_cvref_t<T>, QString> >>, @@ -101,18 +106,8 @@ private: static constexpr bool isAsciiOnlyCharsAtCompileTime(Char *str, qsizetype sz) noexcept { // do not perform check if not at compile time -#if !(defined(__cpp_lib_is_constant_evaluated) || defined(Q_CC_GNU)) - Q_UNUSED(str); - Q_UNUSED(sz); - return false; -#else -# if defined(__cpp_lib_is_constant_evaluated) - if (!std::is_constant_evaluated()) - return false; -# elif defined(Q_CC_GNU) && !defined(Q_CC_CLANG) - if (!str || !__builtin_constant_p(*str)) + if (!q20::is_constant_evaluated()) return false; -# endif if constexpr (sizeof(Char) != sizeof(char)) { Q_UNUSED(str); Q_UNUSED(sz); @@ -122,9 +117,8 @@ private: if (uchar(str[i]) > 0x7f) return false; } + return true; } - return true; -#endif } template<typename Char> @@ -140,40 +134,25 @@ private: } template <typename Char> - static qsizetype lengthHelperPointer(const Char *str) noexcept + static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept { -#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) - if (__builtin_constant_p(*str)) { - qsizetype result = 0; - while (*str++ != u'\0') - ++result; - return result; - } -#endif + if (q20::is_constant_evaluated()) + return QtPrivate::lengthHelperPointer(str); if constexpr (sizeof(Char) == sizeof(char16_t)) return QtPrivate::qustrlen(reinterpret_cast<const char16_t*>(str)); else return qsizetype(strlen(reinterpret_cast<const char*>(str))); } - template <typename Container> - static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept - { - return qsizetype(std::size(c)); - } - - template <typename Char, size_t N> - static constexpr qsizetype lengthHelperContainer(const Char (&str)[N]) noexcept - { - const auto it = std::char_traits<Char>::find(str, N, Char(0)); - const auto end = it ? it : std::next(str, N); - return qsizetype(std::distance(str, end)); - } - static QChar toQChar(char ch) noexcept { return toQChar(QLatin1Char{ch}); } // we don't handle UTF-8 multibytes static QChar toQChar(QChar ch) noexcept { return ch; } static QChar toQChar(QLatin1Char ch) noexcept { return ch; } + struct QCharContainer { // private, so users can't pass their own + explicit QCharContainer() = default; + QChar ch; + }; + explicit constexpr QAnyStringView(const void *d, qsizetype n, std::size_t sizeAndType) noexcept : m_data{d}, m_size{std::size_t(n) | (sizeAndType & TypeMask)} {} public: @@ -211,8 +190,8 @@ public: inline constexpr QAnyStringView(QLatin1StringView str) noexcept; template <typename Container, if_compatible_container<Container> = true> - constexpr QAnyStringView(const Container &c) noexcept - : QAnyStringView(std::data(c), lengthHelperContainer(c)) {} + constexpr Q_ALWAYS_INLINE QAnyStringView(const Container &c) noexcept + : QAnyStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {} template <typename Container, if_convertible_to<QString, Container> = true> constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QString> &&capacity = {}) @@ -223,24 +202,24 @@ public: constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QByteArray> &&capacity = {}) //noexcept(std::is_nothrow_constructible_v<QByteArray, Container>) : QAnyStringView(capacity = std::forward<Container>(c)) {} - template <typename Char, if_compatible_char<Char> = true> constexpr QAnyStringView(const Char &c) noexcept : QAnyStringView{&c, 1} {} - constexpr QAnyStringView(const QChar &c) noexcept - : QAnyStringView{&c, 1} {} + template <typename Char, if_convertible_to<QChar, Char> = true> + constexpr QAnyStringView(Char ch, QCharContainer &&capacity = QCharContainer()) noexcept + : QAnyStringView{&(capacity.ch = ch), 1} {} template <typename Char, typename Container = decltype(QChar::fromUcs4(U'x')), std::enable_if_t<std::is_same_v<Char, char32_t>, bool> = true> - constexpr QAnyStringView(Char c, Container &&capacity = {}) + constexpr QAnyStringView(Char c, Container &&capacity = {}) noexcept : QAnyStringView(capacity = QChar::fromUcs4(c)) {} constexpr QAnyStringView(QStringView v) noexcept - : QAnyStringView(std::data(v), lengthHelperContainer(v)) {} + : QAnyStringView(std::data(v), QtPrivate::lengthHelperContainer(v)) {} template <bool UseChar8T> constexpr QAnyStringView(QBasicUtf8StringView<UseChar8T> v) noexcept - : QAnyStringView(std::data(v), lengthHelperContainer(v)) {} + : QAnyStringView(std::data(v), QtPrivate::lengthHelperContainer(v)) {} template <typename Char, size_t Size, if_compatible_char<Char> = true> [[nodiscard]] constexpr static QAnyStringView fromArray(const Char (&string)[Size]) noexcept @@ -273,20 +252,20 @@ public: } [[nodiscard]] constexpr QAnyStringView sliced(qsizetype pos) const - { verify(pos); auto r = *this; r.advanceData(pos); r.setSize(size() - pos); return r; } + { verify(pos, 0); auto r = *this; r.advanceData(pos); r.setSize(size() - pos); return r; } [[nodiscard]] constexpr QAnyStringView sliced(qsizetype pos, qsizetype n) const { verify(pos, n); auto r = *this; r.advanceData(pos); r.setSize(n); return r; } [[nodiscard]] constexpr QAnyStringView first(qsizetype n) const - { verify(n); return sliced(0, n); } + { verify(0, n); return sliced(0, n); } [[nodiscard]] constexpr QAnyStringView last(qsizetype n) const - { verify(n); return sliced(size() - n, n); } + { verify(0, n); return sliced(size() - n, n); } [[nodiscard]] constexpr QAnyStringView chopped(qsizetype n) const - { verify(n); return sliced(0, size() - n); } + { verify(0, n); return sliced(0, size() - n); } constexpr void truncate(qsizetype n) - { verify(n); setSize(n); } + { verify(0, n); setSize(n); } constexpr void chop(qsizetype n) - { verify(n); setSize(size() - n); } + { verify(0, n); setSize(size() - n); } [[nodiscard]] inline QString toString() const; // defined in qstring.h @@ -299,12 +278,13 @@ public: [[nodiscard]] Q_CORE_EXPORT static bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept; static constexpr inline bool detects_US_ASCII_at_compile_time = -#ifdef __cpp_lib_is_constant_evaluated +#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED true #else false #endif ; + // // STL compatibility API: // @@ -323,23 +303,18 @@ public: { return size(); } private: - [[nodiscard]] friend inline bool operator==(QAnyStringView lhs, QAnyStringView rhs) noexcept + friend bool comparesEqual(const QAnyStringView &lhs, const QAnyStringView &rhs) noexcept { return QAnyStringView::equal(lhs, rhs); } - [[nodiscard]] friend inline bool operator!=(QAnyStringView lhs, QAnyStringView rhs) noexcept - { return !QAnyStringView::equal(lhs, rhs); } + friend Qt::strong_ordering + compareThreeWay(const QAnyStringView &lhs, const QAnyStringView &rhs) noexcept + { + const int res = QAnyStringView::compare(lhs, rhs); + return Qt::compareThreeWay(res, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QAnyStringView) -#if defined(__cpp_impl_three_way_comparison) && !defined(Q_QDOC) - [[nodiscard]] friend inline auto operator<=>(QAnyStringView lhs, QAnyStringView rhs) noexcept - { return QAnyStringView::compare(lhs, rhs) <=> 0; } -#else - [[nodiscard]] friend inline bool operator<=(QAnyStringView lhs, QAnyStringView rhs) noexcept - { return QAnyStringView::compare(lhs, rhs) <= 0; } - [[nodiscard]] friend inline bool operator>=(QAnyStringView lhs, QAnyStringView rhs) noexcept - { return QAnyStringView::compare(lhs, rhs) >= 0; } - [[nodiscard]] friend inline bool operator<(QAnyStringView lhs, QAnyStringView rhs) noexcept - { return QAnyStringView::compare(lhs, rhs) < 0; } - [[nodiscard]] friend inline bool operator>(QAnyStringView lhs, QAnyStringView rhs) noexcept - { return QAnyStringView::compare(lhs, rhs) > 0; } +#ifndef QT_NO_DEBUG_STREAM + Q_CORE_EXPORT friend QDebug operator<<(QDebug d, QAnyStringView s); #endif [[nodiscard]] constexpr Tag tag() const noexcept { return Tag{m_size & TypeMask}; } @@ -355,7 +330,8 @@ private: constexpr void setSize(qsizetype sz) noexcept { m_size = size_t(sz) | tag(); } constexpr void advanceData(qsizetype delta) noexcept { m_data_utf8 += delta * charSize(); } - Q_ALWAYS_INLINE constexpr void verify(qsizetype pos, qsizetype n = 0) const + 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()); @@ -377,7 +353,7 @@ template <typename QStringLike, std::enable_if_t<std::disjunction_v< std::is_same<QStringLike, QByteArray> >, bool> = true> [[nodiscard]] inline QAnyStringView qToAnyStringViewIgnoringNull(const QStringLike &s) noexcept -{ return QAnyStringView(s.data(), s.size()); } +{ return QAnyStringView(s.begin(), s.size()); } QT_END_NAMESPACE |