diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2024-02-22 16:49:37 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2024-03-02 00:12:54 +0100 |
commit | 7068418a13c7149f81dade96000b99b1c37c0df8 (patch) | |
tree | b3a52682debbfb5cb8ff3ad481af84b54805c8a3 | |
parent | ee612626f99d5a8da6814c2df90db00f9beb463f (diff) |
QByteArray: use comparison helper macros
Replace the existing friend relational operators with the macros.
Add the previously-missing relational opertors with QChar and char16_t.
This allows to remove the last dummy relational operators and the
macros to generate them in tst_qstringapisymmetry.
Because of a bug in libstdc++[0], we have to explicitly keep the
QBA vs QBA relational operators even in C++20 mode. This problem is
specific to QByteArray, because it is convertible to const void *.
[0]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114153
Task-number: QTBUG-117661
Change-Id: Iac7f81cd3274331b7c7695a51803321b511361c0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/text/qbytearray.cpp | 112 | ||||
-rw-r--r-- | src/corelib/text/qbytearray.h | 87 | ||||
-rw-r--r-- | src/corelib/text/qstring.cpp | 22 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp | 24 |
4 files changed, 118 insertions, 127 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 8ae3ab4b9c..cacf8cbf63 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -809,6 +809,14 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes) \reentrant + \compares strong + \compareswith strong {const char *} QByteArrayView + \endcompareswith + \compareswith strong QChar char16_t QString QStringView QLatin1StringView \ + QUtf8StringView + When comparing with string types, the content is interpreted as utf-8. + \endcompareswith + QByteArray can be used to store both raw bytes (including '\\0's) and traditional 8-bit '\\0'-terminated strings. Using QByteArray is much more convenient than using \c{const char *}. Behind the @@ -3382,164 +3390,164 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba) } #endif // QT_NO_DATASTREAM -/*! \fn bool QByteArray::operator==(const QByteArray &a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator==(const QByteArray &lhs, const QByteArray &rhs) \overload - Returns \c true if byte array \a a1 is equal to byte array \a a2; + Returns \c true if byte array \a lhs is equal to byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator==(const QByteArray &a1, const char *a2) +/*! \fn bool QByteArray::operator==(const QByteArray &lhs, const char * const &rhs) \overload - Returns \c true if byte array \a a1 is equal to the '\\0'-terminated string - \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is equal to the '\\0'-terminated string + \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator==(const char *a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator==(const char * const &lhs, const QByteArray &rhs) \overload - Returns \c true if '\\0'-terminated string \a a1 is equal to byte array \a - a2; otherwise returns \c false. + Returns \c true if '\\0'-terminated string \a lhs is equal to byte array \a + rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator!=(const QByteArray &a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator!=(const QByteArray &lhs, const QByteArray &rhs) \overload - Returns \c true if byte array \a a1 is not equal to byte array \a a2; + Returns \c true if byte array \a lhs is not equal to byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator!=(const QByteArray &a1, const char *a2) +/*! \fn bool QByteArray::operator!=(const QByteArray &lhs, const char * const &rhs) \overload - Returns \c true if byte array \a a1 is not equal to the '\\0'-terminated - string \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is not equal to the '\\0'-terminated + string \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator!=(const char *a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator!=(const char * const &lhs, const QByteArray &rhs) \overload - Returns \c true if '\\0'-terminated string \a a1 is not equal to byte array - \a a2; otherwise returns \c false. + Returns \c true if '\\0'-terminated string \a lhs is not equal to byte array + \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator<(const QByteArray &a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator<(const QByteArray &lhs, const QByteArray &rhs) \overload - Returns \c true if byte array \a a1 is lexically less than byte array - \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically less than byte array + \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator<(const QByteArray &a1, const char *a2) +/*! \fn bool QByteArray::operator<(const QByteArray &lhs, const char * const &rhs) \overload - Returns \c true if byte array \a a1 is lexically less than the - '\\0'-terminated string \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically less than the + '\\0'-terminated string \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator<(const char *a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator<(const char * const &lhs, const QByteArray &rhs) \overload - Returns \c true if '\\0'-terminated string \a a1 is lexically less than byte - array \a a2; otherwise returns \c false. + Returns \c true if '\\0'-terminated string \a lhs is lexically less than byte + array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator<=(const QByteArray &a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator<=(const QByteArray &lhs, const QByteArray &rhs) \overload - Returns \c true if byte array \a a1 is lexically less than or equal - to byte array \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically less than or equal + to byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator<=(const QByteArray &a1, const char *a2) +/*! \fn bool QByteArray::operator<=(const QByteArray &lhs, const char * const &rhs) \overload - Returns \c true if byte array \a a1 is lexically less than or equal to the - '\\0'-terminated string \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically less than or equal to the + '\\0'-terminated string \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator<=(const char *a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator<=(const char * const &lhs, const QByteArray &rhs) \overload - Returns \c true if '\\0'-terminated string \a a1 is lexically less than or - equal to byte array \a a2; otherwise returns \c false. + Returns \c true if '\\0'-terminated string \a lhs is lexically less than or + equal to byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator>(const QByteArray &a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator>(const QByteArray &lhs, const QByteArray &rhs) \overload - Returns \c true if byte array \a a1 is lexically greater than byte - array \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically greater than byte + array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator>(const QByteArray &a1, const char *a2) +/*! \fn bool QByteArray::operator>(const QByteArray &lhs, const char * const &rhs) \overload - Returns \c true if byte array \a a1 is lexically greater than the - '\\0'-terminated string \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically greater than the + '\\0'-terminated string \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator>(const char *a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator>(const char * const &lhs, const QByteArray &rhs) \overload - Returns \c true if '\\0'-terminated string \a a1 is lexically greater than - byte array \a a2; otherwise returns \c false. + Returns \c true if '\\0'-terminated string \a lhs is lexically greater than + byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator>=(const QByteArray &a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator>=(const QByteArray &lhs, const QByteArray &rhs) \overload - Returns \c true if byte array \a a1 is lexically greater than or - equal to byte array \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically greater than or + equal to byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator>=(const QByteArray &a1, const char *a2) +/*! \fn bool QByteArray::operator>=(const QByteArray &lhs, const char * const &rhs) \overload - Returns \c true if byte array \a a1 is lexically greater than or equal to - the '\\0'-terminated string \a a2; otherwise returns \c false. + Returns \c true if byte array \a lhs is lexically greater than or equal to + the '\\0'-terminated string \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ -/*! \fn bool QByteArray::operator>=(const char *a1, const QByteArray &a2) +/*! \fn bool QByteArray::operator>=(const char * const &lhs, const QByteArray &rhs) \overload - Returns \c true if '\\0'-terminated string \a a1 is lexically greater than - or equal to byte array \a a2; otherwise returns \c false. + Returns \c true if '\\0'-terminated string \a lhs is lexically greater than + or equal to byte array \a rhs; otherwise returns \c false. \sa QByteArray::compare() */ diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h index 9d3eeba360..710eb65c66 100644 --- a/src/corelib/text/qbytearray.h +++ b/src/corelib/text/qbytearray.h @@ -368,57 +368,6 @@ public: QT_ASCII_CAST_WARN inline bool operator>=(const QString &s2) const; #endif // QT_CORE_REMOVED_SINCE(6, 8) #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) - friend inline bool operator==(const QByteArray &a1, const QByteArray &a2) noexcept - { return QByteArrayView(a1) == QByteArrayView(a2); } - friend inline bool operator==(const QByteArray &a1, const char *a2) noexcept - { return QByteArrayView(a1) == QByteArrayView(a2); } - friend inline bool operator==(const char *a1, const QByteArray &a2) noexcept - { return QByteArrayView(a1) == QByteArrayView(a2); } - friend inline bool operator!=(const QByteArray &a1, const QByteArray &a2) noexcept - { return !(a1==a2); } - friend inline bool operator!=(const QByteArray &a1, const char *a2) noexcept - { return QByteArrayView(a1) != QByteArrayView(a2); } - friend inline bool operator!=(const char *a1, const QByteArray &a2) noexcept - { return QByteArrayView(a1) != QByteArrayView(a2); } - friend inline bool operator<(const QByteArray &a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) < 0; } - friend inline bool operator<(const QByteArray &a1, const char *a2) noexcept - { return QtPrivate::compareMemory(a1, a2) < 0; } - friend inline bool operator<(const char *a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(a1, a2) < 0; } - friend inline bool operator<=(const QByteArray &a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) <= 0; } - friend inline bool operator<=(const QByteArray &a1, const char *a2) noexcept - { return QtPrivate::compareMemory(a1, a2) <= 0; } - friend inline bool operator<=(const char *a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(a1, a2) <= 0; } - friend inline bool operator>(const QByteArray &a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) > 0; } - friend inline bool operator>(const QByteArray &a1, const char *a2) noexcept - { return QtPrivate::compareMemory(a1, a2) > 0; } - friend inline bool operator>(const char *a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(a1, a2) > 0; } - friend inline bool operator>=(const QByteArray &a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) >= 0; } - friend inline bool operator>=(const QByteArray &a1, const char *a2) noexcept - { return QtPrivate::compareMemory(a1, a2) >= 0; } - friend inline bool operator>=(const char *a1, const QByteArray &a2) noexcept - { return QtPrivate::compareMemory(a1, a2) >= 0; } - - // Check isEmpty() instead of isNull() for backwards compatibility. - friend inline bool operator==(const QByteArray &a1, std::nullptr_t) noexcept { return a1.isEmpty(); } - friend inline bool operator!=(const QByteArray &a1, std::nullptr_t) noexcept { return !a1.isEmpty(); } - friend inline bool operator< (const QByteArray & , std::nullptr_t) noexcept { return false; } - friend inline bool operator> (const QByteArray &a1, std::nullptr_t) noexcept { return !a1.isEmpty(); } - friend inline bool operator<=(const QByteArray &a1, std::nullptr_t) noexcept { return a1.isEmpty(); } - friend inline bool operator>=(const QByteArray & , std::nullptr_t) noexcept { return true; } - - friend inline bool operator==(std::nullptr_t, const QByteArray &a2) noexcept { return a2 == nullptr; } - friend inline bool operator!=(std::nullptr_t, const QByteArray &a2) noexcept { return a2 != nullptr; } - friend inline bool operator< (std::nullptr_t, const QByteArray &a2) noexcept { return a2 > nullptr; } - friend inline bool operator> (std::nullptr_t, const QByteArray &a2) noexcept { return a2 < nullptr; } - friend inline bool operator<=(std::nullptr_t, const QByteArray &a2) noexcept { return a2 >= nullptr; } - friend inline bool operator>=(std::nullptr_t, const QByteArray &a2) noexcept { return a2 <= nullptr; } short toShort(bool *ok = nullptr, int base = 10) const; ushort toUShort(bool *ok = nullptr, int base = 10) const; @@ -566,7 +515,43 @@ private: const int res = QtPrivate::compareMemory(QByteArrayView(lhs), rhs); return Qt::compareThreeWay(res, 0); } + Q_DECLARE_STRONGLY_ORDERED(QByteArray) Q_DECLARE_STRONGLY_ORDERED(QByteArray, QByteArrayView) + Q_DECLARE_STRONGLY_ORDERED(QByteArray, const char *) +#if defined(__GLIBCXX__) && defined(__cpp_lib_three_way_comparison) + // libstdc++ has a bug [0] when `operator const void *()` is preferred over + // `operator<=>()` when calling std::less<> and other similar methods. + // Fix it by explicitly providing relational operators in such case. + // [0]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114153 + friend bool operator<(const QByteArray &lhs, const QByteArray &rhs) noexcept + { return is_lt(compareThreeWay(lhs, rhs)); } + friend bool operator<=(const QByteArray &lhs, const QByteArray &rhs) noexcept + { return is_lteq(compareThreeWay(lhs, rhs)); } + friend bool operator>(const QByteArray &lhs, const QByteArray &rhs) noexcept + { return is_gt(compareThreeWay(lhs, rhs)); } + friend bool operator>=(const QByteArray &lhs, const QByteArray &rhs) noexcept + { return is_gteq(compareThreeWay(lhs, rhs)); } +#endif // defined(__GLIBCXX__) && defined(__cpp_lib_three_way_comparison) + + // Check isEmpty() instead of isNull() for backwards compatibility. + friend bool comparesEqual(const QByteArray &lhs, std::nullptr_t) noexcept + { return lhs.isEmpty(); } + friend Qt::strong_ordering compareThreeWay(const QByteArray &lhs, std::nullptr_t) noexcept + { return lhs.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; } + Q_DECLARE_STRONGLY_ORDERED(QByteArray, std::nullptr_t) + + // defined in qstring.cpp + friend Q_CORE_EXPORT bool comparesEqual(const QByteArray &lhs, const QChar &rhs) noexcept; + friend Q_CORE_EXPORT Qt::strong_ordering + compareThreeWay(const QByteArray &lhs, const QChar &rhs) noexcept; + friend Q_CORE_EXPORT bool comparesEqual(const QByteArray &lhs, char16_t rhs) noexcept; + friend Q_CORE_EXPORT Qt::strong_ordering + compareThreeWay(const QByteArray &lhs, char16_t rhs) noexcept; +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) + Q_DECLARE_STRONGLY_ORDERED(QByteArray, QChar, QT_ASCII_CAST_WARN) + Q_DECLARE_STRONGLY_ORDERED(QByteArray, char16_t, QT_ASCII_CAST_WARN) +#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) + void reallocData(qsizetype alloc, QArrayData::AllocationOption option); void reallocGrowData(qsizetype n); diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 58b9a42813..b3fd7be4f0 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -6731,6 +6731,28 @@ Qt::strong_ordering QByteArrayView::compareThreeWay(const QByteArrayView &lhs, return Qt::compareThreeWay(res, 0); } +bool comparesEqual(const QByteArray &lhs, const QChar &rhs) noexcept +{ + return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1)); +} + +Qt::strong_ordering compareThreeWay(const QByteArray &lhs, const QChar &rhs) noexcept +{ + const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1)); + return Qt::compareThreeWay(res, 0); +} + +bool comparesEqual(const QByteArray &lhs, char16_t rhs) noexcept +{ + return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1)); +} + +Qt::strong_ordering compareThreeWay(const QByteArray &lhs, char16_t rhs) noexcept +{ + const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1)); + return Qt::compareThreeWay(res, 0); +} + /*! \internal \since 6.8 diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp index 33bfdf163a..e1a262b61a 100644 --- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -32,7 +32,6 @@ struct QAnyStringViewUsingU16 : QAnyStringView {}; // QAnyStringView with Utf-1 template <typename T> QString toQString(const T &t) { return QString(t); } QString toQString(QStringView view) { return view.toString(); } -QString toQString(QUtf8StringView view) { return view.toString(); } template <typename Iterable> QStringList toQStringList(const Iterable &i) { @@ -45,29 +44,6 @@ QStringList toQStringList(const Iterable &i) { template <typename LHS, typename RHS> constexpr bool is_fake_comparator_v = false; -// FIXME: these are missing at the time of writing, add them, then remove the dummies here: -#define MAKE_RELOP(op, A1, A2) \ - static bool operator op (A1 lhs, A2 rhs) \ - { return toQString(lhs) op toQString(rhs); } \ - /*end*/ -#define MAKE_ALL(A1, A2) \ - template <> constexpr bool is_fake_comparator_v<A1, A2> = true; \ - MAKE_RELOP(==, A1, A2) \ - MAKE_RELOP(!=, A1, A2) \ - MAKE_RELOP(<, A1, A2) \ - MAKE_RELOP(>, A1, A2) \ - MAKE_RELOP(<=, A1, A2) \ - MAKE_RELOP(>=, A1, A2) \ - /*end*/ - - -MAKE_ALL(char16_t, QByteArray) -MAKE_ALL(QByteArray, char16_t) - -#undef MAKE_ALL -#undef MAKE_RELOP -// END FIXME - } // namespace static constexpr int sign(int i) noexcept |