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>bb10
parent
a08bafc920
commit
ee612626f9
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 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 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, 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;
|
||||
|
|
|
|||
|
|
@ -6731,6 +6731,20 @@ Qt::strong_ordering QByteArrayView::compareThreeWay(const QByteArrayView &lhs,
|
|||
return Qt::compareThreeWay(res, 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue