summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2024-02-22 11:43:35 +0100
committerIvan Solovev <ivan.solovev@qt.io>2024-03-02 00:12:54 +0100
commitee612626f99d5a8da6814c2df90db00f9beb463f (patch)
tree5a92a286c27418b2b4e76e0faf01a24246f5fa82
parenta08bafc9205d0b67f71a1896ad84272eeb294374 (diff)
Q(Latin1)Char: use comparison helper macros
Replace the existing friend relational operators with the macros. Add the previously-missing QChar vs `const char *` relational operators. These require out-of-line helper methods, because we need to interpret the `const char *` array as utf-8. The `const char *` relational operators cause ambiguities when comparing QChar with 0 (previously it was only handled by the nullptr_t overloads). As we have it in several places in our tests, I'd assume that the users can also do it. To resolve the ambiguities, mark the new relational operators as Q_WEAK_OVERLOADs. This allows to remove the dummy QChar vs `const char *` relational operators from tst_qstringapisymmetry, but at the same time requires that we introduce new dummy operators for QByteArray vs char16_t comparison. These will be fixed in a follow-up patch. For QLatin1Char - convert to uchar before doing the comparison, to match the behavior of QLatin1StringView and QChar. Extend QChar's unit tests. Task-number: QTBUG-117661 Change-Id: I9213fe05a5efdb96d48688f07bec9519f9887a77 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/text/qchar.cpp19
-rw-r--r--src/corelib/text/qchar.h87
-rw-r--r--src/corelib/text/qstring.cpp14
-rw-r--r--tests/auto/corelib/text/qchar/tst_qchar.cpp32
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp5
5 files changed, 107 insertions, 50 deletions
diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp
index 7b62b1e04a..63296a92de 100644
--- a/src/corelib/text/qchar.cpp
+++ b/src/corelib/text/qchar.cpp
@@ -55,6 +55,13 @@ QT_BEGIN_NAMESPACE
\ingroup string-processing
\reentrant
+ \compares strong
+ \compareswith strong char16_t QString QStringView QLatin1StringView QUtf8StringView
+ \endcompareswith
+ \compareswith strong {const char *} QByteArray QByteArrayView
+ The contents of the byte array is interpreted as utf-8.
+ \endcompareswith
+
In Qt, Unicode characters are 16-bit entities without any markup
or structure. This class represents such an entity. It is
lightweight, so it can be used everywhere. Most compilers treat
@@ -1740,42 +1747,42 @@ QDataStream &operator>>(QDataStream &in, QChar &chr)
*****************************************************************************/
/*!
- \fn bool QChar::operator==(QChar c1, QChar c2)
+ \fn bool QChar::operator==(const QChar &c1, const QChar &c2)
Returns \c true if \a c1 and \a c2 are the same Unicode character;
otherwise returns \c false.
*/
/*!
- \fn int QChar::operator!=(QChar c1, QChar c2)
+ \fn bool QChar::operator!=(const QChar &c1, const QChar &c2)
Returns \c true if \a c1 and \a c2 are not the same Unicode
character; otherwise returns \c false.
*/
/*!
- \fn int QChar::operator<=(QChar c1, QChar c2)
+ \fn bool QChar::operator<=(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is less than
or equal to that of \a c2; otherwise returns \c false.
*/
/*!
- \fn int QChar::operator>=(QChar c1, QChar c2)
+ \fn bool QChar::operator>=(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is greater than
or equal to that of \a c2; otherwise returns \c false.
*/
/*!
- \fn int QChar::operator<(QChar c1, QChar c2)
+ \fn bool QChar::operator<(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is less than
that of \a c2; otherwise returns \c false.
*/
/*!
- \fn int QChar::operator>(QChar c1, QChar c2)
+ \fn bool QChar::operator>(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is greater than
that of \a c2; otherwise returns \c false.
diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h
index fa3483db75..c0c53664c2 100644
--- a/src/corelib/text/qchar.h
+++ b/src/corelib/text/qchar.h
@@ -5,6 +5,7 @@
#define QCHAR_H
#include <QtCore/qglobal.h>
+#include <QtCore/qcompare.h>
#include <functional> // for std::hash
@@ -20,26 +21,20 @@ public:
constexpr inline char toLatin1() const noexcept { return ch; }
constexpr inline char16_t unicode() const noexcept { return char16_t(uchar(ch)); }
- friend constexpr inline bool operator==(QLatin1Char lhs, QLatin1Char rhs) noexcept { return lhs.ch == rhs.ch; }
- friend constexpr inline bool operator!=(QLatin1Char lhs, QLatin1Char rhs) noexcept { return lhs.ch != rhs.ch; }
- friend constexpr inline bool operator<=(QLatin1Char lhs, QLatin1Char rhs) noexcept { return lhs.ch <= rhs.ch; }
- friend constexpr inline bool operator>=(QLatin1Char lhs, QLatin1Char rhs) noexcept { return lhs.ch >= rhs.ch; }
- friend constexpr inline bool operator< (QLatin1Char lhs, QLatin1Char rhs) noexcept { return lhs.ch < rhs.ch; }
- friend constexpr inline bool operator> (QLatin1Char lhs, QLatin1Char rhs) noexcept { return lhs.ch > rhs.ch; }
-
- friend constexpr inline bool operator==(char lhs, QLatin1Char rhs) noexcept { return lhs == rhs.toLatin1(); }
- friend constexpr inline bool operator!=(char lhs, QLatin1Char rhs) noexcept { return lhs != rhs.toLatin1(); }
- friend constexpr inline bool operator<=(char lhs, QLatin1Char rhs) noexcept { return lhs <= rhs.toLatin1(); }
- friend constexpr inline bool operator>=(char lhs, QLatin1Char rhs) noexcept { return lhs >= rhs.toLatin1(); }
- friend constexpr inline bool operator< (char lhs, QLatin1Char rhs) noexcept { return lhs < rhs.toLatin1(); }
- friend constexpr inline bool operator> (char lhs, QLatin1Char rhs) noexcept { return lhs > rhs.toLatin1(); }
-
- friend constexpr inline bool operator==(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() == rhs; }
- friend constexpr inline bool operator!=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() != rhs; }
- friend constexpr inline bool operator<=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() <= rhs; }
- friend constexpr inline bool operator>=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() >= rhs; }
- friend constexpr inline bool operator< (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() < rhs; }
- friend constexpr inline bool operator> (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() > rhs; }
+ friend constexpr bool
+ comparesEqual(const QLatin1Char &lhs, const QLatin1Char &rhs) noexcept
+ { return lhs.ch == rhs.ch; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QLatin1Char &lhs, const QLatin1Char &rhs) noexcept
+ { return Qt::compareThreeWay(uchar(lhs.ch), uchar(rhs.ch)); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QLatin1Char)
+
+ friend constexpr bool comparesEqual(const QLatin1Char &lhs, char rhs) noexcept
+ { return lhs.toLatin1() == rhs; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QLatin1Char &lhs, char rhs) noexcept
+ { return Qt::compareThreeWay(uchar(lhs.toLatin1()), uchar(rhs)); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QLatin1Char, char)
private:
char ch;
@@ -581,28 +576,19 @@ public:
static constexpr inline bool isTitleCase(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return ucs4 > 127 && QChar::category(ucs4) == Letter_Titlecase; }
- friend constexpr inline bool operator==(QChar c1, QChar c2) noexcept { return c1.ucs == c2.ucs; }
- friend constexpr inline bool operator< (QChar c1, QChar c2) noexcept { return c1.ucs < c2.ucs; }
+ friend constexpr bool comparesEqual(const QChar &lhs, const QChar &rhs) noexcept
+ { return lhs.ucs == rhs.ucs; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QChar &lhs, const QChar &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.ucs, rhs.ucs); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QChar)
- friend constexpr inline bool operator!=(QChar c1, QChar c2) noexcept { return !operator==(c1, c2); }
- friend constexpr inline bool operator>=(QChar c1, QChar c2) noexcept { return !operator< (c1, c2); }
- friend constexpr inline bool operator> (QChar c1, QChar c2) noexcept { return operator< (c2, c1); }
- friend constexpr inline bool operator<=(QChar c1, QChar c2) noexcept { return !operator< (c2, c1); }
-
- friend constexpr inline bool operator==(QChar lhs, std::nullptr_t) noexcept { return lhs.isNull(); }
- friend constexpr inline bool operator< (QChar, std::nullptr_t) noexcept { return false; }
- friend constexpr inline bool operator==(std::nullptr_t, QChar rhs) noexcept { return rhs.isNull(); }
- friend constexpr inline bool operator< (std::nullptr_t, QChar rhs) noexcept { return !rhs.isNull(); }
-
- friend constexpr inline bool operator!=(QChar lhs, std::nullptr_t) noexcept { return !operator==(lhs, nullptr); }
- friend constexpr inline bool operator>=(QChar lhs, std::nullptr_t) noexcept { return !operator< (lhs, nullptr); }
- friend constexpr inline bool operator> (QChar lhs, std::nullptr_t) noexcept { return operator< (nullptr, lhs); }
- friend constexpr inline bool operator<=(QChar lhs, std::nullptr_t) noexcept { return !operator< (nullptr, lhs); }
-
- friend constexpr inline bool operator!=(std::nullptr_t, QChar rhs) noexcept { return !operator==(nullptr, rhs); }
- friend constexpr inline bool operator>=(std::nullptr_t, QChar rhs) noexcept { return !operator< (nullptr, rhs); }
- friend constexpr inline bool operator> (std::nullptr_t, QChar rhs) noexcept { return operator< (rhs, nullptr); }
- friend constexpr inline bool operator<=(std::nullptr_t, QChar rhs) noexcept { return !operator< (rhs, nullptr); }
+ friend constexpr bool comparesEqual(const QChar &lhs, std::nullptr_t) noexcept
+ { return lhs.isNull(); }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QChar &lhs, std::nullptr_t) noexcept
+ { return lhs.isNull() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QChar, std::nullptr_t)
private:
static bool QT_CHAR_FASTCALL isSpace_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
@@ -610,6 +596,25 @@ private:
static bool QT_CHAR_FASTCALL isNumber_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
static bool QT_CHAR_FASTCALL isLetterOrNumber_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ // defined in qstring.cpp, because we need to go via QUtf8StringView
+ static bool QT_CHAR_FASTCALL
+ equal_helper(QChar lhs, const char *rhs) noexcept Q_DECL_CONST_FUNCTION;
+ static int QT_CHAR_FASTCALL
+ compare_helper(QChar lhs, const char *rhs) noexcept Q_DECL_CONST_FUNCTION;
+
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ Q_WEAK_OVERLOAD
+ friend bool comparesEqual(const QChar &lhs, const char *rhs) noexcept
+ { return equal_helper(lhs, rhs); }
+ Q_WEAK_OVERLOAD
+ friend Qt::strong_ordering compareThreeWay(const QChar &lhs, const char *rhs) noexcept
+ {
+ const int res = compare_helper(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QChar, const char *, Q_WEAK_OVERLOAD QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+
#ifdef QT_NO_CAST_FROM_ASCII
QChar(char c) = delete;
QChar(uchar c) = delete;
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 28417a304e..58b9a42813 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -6735,6 +6735,20 @@ Qt::strong_ordering QByteArrayView::compareThreeWay(const QByteArrayView &lhs,
\internal
\since 6.8
*/
+bool QT_FASTCALL QChar::equal_helper(QChar lhs, const char *rhs) noexcept
+{
+ return QtPrivate::equalStrings(QStringView(&lhs, 1), QUtf8StringView(rhs));
+}
+
+int QT_FASTCALL QChar::compare_helper(QChar lhs, const char *rhs) noexcept
+{
+ return QtPrivate::compareStrings(QStringView(&lhs, 1), QUtf8StringView(rhs));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
bool QStringView::equal_helper(QStringView sv, const char *data, qsizetype len)
{
Q_ASSERT(len >= 0);
diff --git a/tests/auto/corelib/text/qchar/tst_qchar.cpp b/tests/auto/corelib/text/qchar/tst_qchar.cpp
index e0578bacb2..b112538a8c 100644
--- a/tests/auto/corelib/text/qchar/tst_qchar.cpp
+++ b/tests/auto/corelib/text/qchar/tst_qchar.cpp
@@ -17,6 +17,8 @@ private slots:
void operator_eqeq_null();
void operators_data();
void operators();
+ void qchar_qlatin1char_operators_symmetry_data();
+ void qchar_qlatin1char_operators_symmetry();
void toUpper();
void toLower();
void toTitle();
@@ -174,6 +176,36 @@ void tst_QChar::operators()
#undef CHECK
}
+void tst_QChar::qchar_qlatin1char_operators_symmetry_data()
+{
+ QTest::addColumn<char>("lhs");
+ QTest::addColumn<char>("rhs");
+
+ const uchar values[] = {0x00, 0x3a, 0x7f, 0x80, 0xab, 0xff};
+
+ for (uchar i : values) {
+ for (uchar j : values)
+ QTest::addRow("'\\x%02x'_op_'\\x%02x'", i, j) << char(i) << char(j);
+ }
+}
+
+void tst_QChar::qchar_qlatin1char_operators_symmetry()
+{
+ QFETCH(char, lhs);
+ QFETCH(char, rhs);
+
+ const QLatin1Char l1lhs(lhs);
+ const QLatin1Char l1rhs(rhs);
+#define CHECK(op) QCOMPARE((l1lhs op l1rhs), (QChar(l1lhs) op QChar(l1rhs)))
+ CHECK(==);
+ CHECK(!=);
+ CHECK(< );
+ CHECK(> );
+ CHECK(<=);
+ CHECK(>=);
+#undef CHECK
+}
+
void tst_QChar::toUpper()
{
QVERIFY(QChar('a').toUpper() == 'A');
diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
index 854d0ac991..33bfdf163a 100644
--- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -61,9 +61,8 @@ constexpr bool is_fake_comparator_v = false;
/*end*/
-MAKE_ALL(const char*, QChar)
-
-MAKE_ALL(QChar, const char*)
+MAKE_ALL(char16_t, QByteArray)
+MAKE_ALL(QByteArray, char16_t)
#undef MAKE_ALL
#undef MAKE_RELOP