QAnyStringView: use new comparison helper macros

Also extend unit-test to use new test helper functions.
Remove the now-redundant test for three-way comparison, because it is
covered by the test helper functions.

Task-number: QTBUG-117661
Change-Id: I242b560c281245e04e34353c80000a20998fc677
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2024-02-29 16:18:23 +01:00
parent 868a5342bb
commit 2bc9ad0e5d
4 changed files with 111 additions and 59 deletions

View File

@ -17,6 +17,12 @@ QT_BEGIN_NAMESPACE
\ingroup tools
\ingroup string-processing
\compares strong
\compareswith strong char16_t QChar {const char16_t *} {const char *} \
QByteArray QByteArrayView QString QStringView QUtf8StringView \
QLatin1StringView
\endcompareswith
A QAnyStringView references a contiguous portion of a string it does
not own. It acts as an interface type to all kinds of strings,
without the need to construct a QString first.
@ -582,12 +588,12 @@ QT_BEGIN_NAMESPACE
*/
/*!
\fn bool QAnyStringView::operator==(QAnyStringView lhs, QAnyStringView rhs)
\fn bool QAnyStringView::operator!=(QAnyStringView lhs, QAnyStringView rhs)
\fn bool QAnyStringView::operator<=(QAnyStringView lhs, QAnyStringView rhs)
\fn bool QAnyStringView::operator>=(QAnyStringView lhs, QAnyStringView rhs)
\fn bool QAnyStringView::operator<(QAnyStringView lhs, QAnyStringView rhs)
\fn bool QAnyStringView::operator>(QAnyStringView lhs, QAnyStringView rhs)
\fn bool QAnyStringView::operator==(const QAnyStringView &lhs, const QAnyStringView & rhs)
\fn bool QAnyStringView::operator!=(const QAnyStringView & lhs, const QAnyStringView & rhs)
\fn bool QAnyStringView::operator<=(const QAnyStringView & lhs, const QAnyStringView & rhs)
\fn bool QAnyStringView::operator>=(const QAnyStringView & lhs, const QAnyStringView & rhs)
\fn bool QAnyStringView::operator<(const QAnyStringView & lhs, const QAnyStringView & rhs)
\fn bool QAnyStringView::operator>(const QAnyStringView & lhs, const QAnyStringView & rhs)
Operators that compare \a lhs to \a rhs.

View File

@ -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>
@ -301,24 +302,15 @@ 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); }
#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; }
#endif
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)
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT friend QDebug operator<<(QDebug d, QAnyStringView s);

View File

@ -16,6 +16,7 @@ qt_internal_add_test(tst_qanystringview
tst_qanystringview.cpp
LIBRARIES
Qt::CorePrivate
Qt::TestPrivate
)
## Scopes:

View File

@ -12,6 +12,7 @@
# include <private/qt_winrtbase_p.h>
#endif
#include <private/qxmlstream_p.h>
#include <private/qcomparisontesthelper_p.h>
#include <QTest>
@ -378,8 +379,9 @@ private Q_SLOTS:
void fromQStringBuilder_QString_QString() const { fromQStringBuilder(u"1"_s % u"2"_s, u"12"); }
void comparisonCompiles();
void comparison_data();
void comparison();
void compare3way();
private:
template <typename StringBuilder>
@ -819,46 +821,97 @@ void tst_QAnyStringView::conversion_tests(String string) const
}
}
void tst_QAnyStringView::comparison()
void tst_QAnyStringView::comparisonCompiles()
{
const QAnyStringView aa = u"aa";
const QAnyStringView upperAa = u"AA";
const QAnyStringView bb = u"bb";
QVERIFY(aa == aa);
QVERIFY(aa != bb);
QVERIFY(aa < bb);
QVERIFY(bb > aa);
QCOMPARE(QAnyStringView::compare(aa, aa), 0);
QVERIFY(QAnyStringView::compare(aa, upperAa) != 0);
QCOMPARE(QAnyStringView::compare(aa, upperAa, Qt::CaseInsensitive), 0);
QVERIFY(QAnyStringView::compare(aa, bb) < 0);
QVERIFY(QAnyStringView::compare(bb, aa) > 0);
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, char16_t>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QChar>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, const char16_t *>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, const char *>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QByteArray>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QByteArrayView>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QString>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QStringView>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QUtf8StringView>();
QTestPrivate::testAllComparisonOperatorsCompile<QAnyStringView, QLatin1StringView>();
}
void tst_QAnyStringView::compare3way()
void tst_QAnyStringView::comparison_data()
{
#define COMPARE_3WAY(lhs, rhs, res) \
do { \
const auto qt_3way_cmp_res = (lhs) <=> (rhs); \
static_assert(std::is_same_v<decltype(qt_3way_cmp_res), decltype(res)>); \
QCOMPARE(std::is_eq(qt_3way_cmp_res), std::is_eq(res)); \
QCOMPARE(std::is_lt(qt_3way_cmp_res), std::is_lt(res)); \
QCOMPARE(std::is_gt(qt_3way_cmp_res), std::is_gt(res)); \
} while (false)
QTest::addColumn<QAnyStringView>("lhs");
QTest::addColumn<QAnyStringView>("rhs");
QTest::addColumn<int>("csr"); // case sensitive result
QTest::addColumn<int>("cir"); // case insensitive result
ONLY_3WAY(
const QAnyStringView aa = u"aa";
const QAnyStringView upperAa = u"AA";
const QAnyStringView bb = u"bb";
COMPARE_3WAY(aa, aa, std::strong_ordering::equal);
COMPARE_3WAY(aa, bb, std::strong_ordering::less);
COMPARE_3WAY(bb, aa, std::strong_ordering::greater);
COMPARE_3WAY(upperAa, aa, std::strong_ordering::less);
COMPARE_3WAY(aa, upperAa, std::strong_ordering::greater);
);
#undef COMPARE_3WAY
auto row = [&](QAnyStringView l, QAnyStringView r, int csr, int cir) {
QTest::addRow("%s_vs_%s", qPrintable(l.toString()), qPrintable(r.toString()))
<< l << r << csr << cir;
};
row(u"aa", u"aa", 0, 0);
row(u"aa", u"AA", 1, 0);
row(u"ab", u"b", -1, -1);
row(u"ab", u"aBb", 1, -1);
row(u"ab", u"B", 1, -1);
}
static int sign(int x)
{
return x == 0 ? 0 : (x < 0 ? -1 : 1);
}
void tst_QAnyStringView::comparison()
{
QFETCH(const QAnyStringView, lhs);
QFETCH(const QAnyStringView, rhs);
QFETCH(const int, csr);
QFETCH(const int, cir);
QCOMPARE(sign(QAnyStringView::compare(lhs, rhs)), csr);
QCOMPARE(sign(QAnyStringView::compare(lhs, rhs, Qt::CaseInsensitive)), cir);
const Qt::strong_ordering ordering = [&csr] {
if (csr == 0)
return Qt::strong_ordering::equal;
else if (csr < 0)
return Qt::strong_ordering::less;
else
return Qt::strong_ordering::greater;
}();
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs, ordering);
const QString rhs_str = rhs.toString();
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_str, ordering);
const QStringView rhs_sv(rhs_str);
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_sv, ordering);
if (!rhs_str.contains(QChar(u'\0'))) {
const char16_t *utfData = reinterpret_cast<const char16_t*>(rhs_str.constData());
QT_TEST_ALL_COMPARISON_OPS(lhs, utfData, ordering);
}
if (rhs_str.size() == 1) {
const QChar ch = rhs_str.front();
QT_TEST_ALL_COMPARISON_OPS(lhs, ch, ordering);
}
if (rhs.isLatin1()) {
const QLatin1StringView rhs_l1 = rhs.asLatin1StringView();
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_l1, ordering);
}
const QByteArray rhs_u8 = rhs_str.toUtf8();
const QUtf8StringView rhs_u8sv(rhs_u8.data(), rhs_u8.size());
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_u8sv, ordering);
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_u8, ordering);
const QByteArrayView rhs_u8view{rhs_u8.begin(), rhs_u8.size()};
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_u8view, ordering);
if (!rhs_str.contains(QChar(u'\0'))) {
const char *rhs_u8data = rhs_u8.constData();
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs_u8data, ordering);
}
}
QTEST_APPLESS_MAIN(tst_QAnyStringView)