Add In-place utf-8 case-insensitive comparisons

Also add optimizations for more string comparisons and add tests and
benchmarks.

[ChangeLog][QtCore][QString] Added utf-8 case-insensitive comparisons

Fixes: QTBUG-100235
Change-Id: I7c0809c6d80c00e9a5d0e8ac3ebb045cf7004a30
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Øystein Heskestad 2022-11-22 17:48:45 +01:00
parent 724329b79e
commit b977ae371a
10 changed files with 406 additions and 15 deletions

View File

@ -1482,8 +1482,7 @@ bool QtPrivate::equalStrings(QStringView lhs, QBasicUtf8StringView<false> rhs) n
bool QtPrivate::equalStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs) noexcept
{
QString r = rhs.toString();
return QtPrivate::equalStrings(lhs, r); // ### optimize!
return QUtf8::compareUtf8(QByteArrayView(rhs), lhs) == 0;
}
bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView rhs) noexcept
@ -1612,7 +1611,7 @@ int QtPrivate::compareStrings(QLatin1StringView lhs, QLatin1StringView rhs, Qt::
*/
int QtPrivate::compareStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs) noexcept
{
return compareStrings(lhs, rhs.toString(), cs); // ### optimize!
return -QUtf8::compareUtf8(QByteArrayView(rhs), lhs, cs);
}
/*!
@ -1647,13 +1646,7 @@ int QtPrivate::compareStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView
*/
int QtPrivate::compareStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs) noexcept
{
if (lhs.isEmpty())
return lencmp(0, rhs.size());
if (cs == Qt::CaseInsensitive)
return compareStrings(lhs.toString(), rhs.toString(), cs); // ### optimize!
const auto l = std::min(lhs.size(), rhs.size());
int r = memcmp(lhs.data(), rhs.data(), l);
return r ? r : lencmp(lhs.size(), rhs.size());
return QUtf8::compareUtf8(QByteArrayView(lhs), QByteArrayView(rhs), cs);
}
int QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs) noexcept

View File

@ -119,6 +119,12 @@ public:
{ return isEmpty() ? -1 : front() == c ? int(size() > 1) : uchar(m_data[0]) - c.unicode(); }
[[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
template<bool UseChar8T>
[[nodiscard]] int compare(QBasicUtf8StringView<UseChar8T> other,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{
return QtPrivate::compareStrings(*this, other, cs);
}
[[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
@ -1230,6 +1236,13 @@ QString QBasicUtf8StringView<UseChar8T>::toString() const
return QString::fromUtf8(data(), size());
}
template<bool UseChar8T>
[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(QLatin1StringView other,
Qt::CaseSensitivity cs) const noexcept
{
return QtPrivate::compareStrings(*this, other, cs);
}
//
// QAnyStringView inline members that require QString:
//

View File

@ -820,7 +820,7 @@ QUtf8::ValidUtf8Result QUtf8::isValidUtf8(QByteArrayView in)
return { true, isValidAscii };
}
int QUtf8::compareUtf8(QByteArrayView utf8, QStringView utf16) noexcept
int QUtf8::compareUtf8(QByteArrayView utf8, QStringView utf16, Qt::CaseSensitivity cs) noexcept
{
auto src1 = reinterpret_cast<const qchar8_t *>(utf8.data());
auto end1 = src1 + utf8.size();
@ -847,7 +847,10 @@ int QUtf8::compareUtf8(QByteArrayView utf8, QStringView utf16) noexcept
if (QChar::isHighSurrogate(uc2) && src2 < end2 && QChar::isLowSurrogate(*src2))
uc2 = QChar::surrogateToUcs4(uc2, *src2++);
}
if (cs == Qt::CaseInsensitive) {
uc1 = QChar::toCaseFolded(uc1);
uc2 = QChar::toCaseFolded(uc2);
}
if (uc1 != uc2)
return int(uc1) - int(uc2);
}
@ -857,7 +860,7 @@ int QUtf8::compareUtf8(QByteArrayView utf8, QStringView utf16) noexcept
return (end1 > src1) - int(end2 > src2);
}
int QUtf8::compareUtf8(QByteArrayView utf8, QLatin1StringView s)
int QUtf8::compareUtf8(QByteArrayView utf8, QLatin1StringView s, Qt::CaseSensitivity cs)
{
char32_t uc1 = QChar::Null;
auto src1 = reinterpret_cast<const uchar *>(utf8.data());
@ -875,6 +878,62 @@ int QUtf8::compareUtf8(QByteArrayView utf8, QLatin1StringView s)
}
char32_t uc2 = *src2++;
if (cs == Qt::CaseInsensitive) {
uc1 = QChar::toCaseFolded(uc1);
uc2 = QChar::toCaseFolded(uc2);
}
if (uc1 != uc2)
return int(uc1) - int(uc2);
}
// the shorter string sorts first
return (end1 > src1) - (end2 > src2);
}
static inline int lencmp(qsizetype lhs, qsizetype rhs) noexcept
{
return lhs == rhs ? 0 :
lhs > rhs ? 1 :
/* else */ -1 ;
}
int QUtf8::compareUtf8(QByteArrayView lhs, QByteArrayView rhs, Qt::CaseSensitivity cs) noexcept
{
if (lhs.isEmpty())
return lencmp(0, rhs.size());
if (cs == Qt::CaseSensitive) {
const auto l = std::min(lhs.size(), rhs.size());
int r = memcmp(lhs.data(), rhs.data(), l);
return r ? r : lencmp(lhs.size(), rhs.size());
}
char32_t uc1 = QChar::Null;
auto src1 = reinterpret_cast<const uchar *>(lhs.data());
auto end1 = src1 + lhs.size();
char32_t uc2 = QChar::Null;
auto src2 = reinterpret_cast<const uchar *>(rhs.data());
auto end2 = src2 + rhs.size();
while (src1 < end1 && src2 < end2) {
uchar b = *src1++;
char32_t *output = &uc1;
int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src1, end1);
if (res < 0) {
// decoding error
uc1 = QChar::ReplacementCharacter;
}
b = *src2++;
output = &uc2;
res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src2, end2);
if (res < 0) {
// decoding error
uc2 = QChar::ReplacementCharacter;
}
uc1 = QChar::toCaseFolded(uc1);
uc2 = QChar::toCaseFolded(uc2);
if (uc1 != uc2)
return int(uc1) - int(uc2);
}

View File

@ -276,8 +276,12 @@ struct QUtf8
bool isValidAscii;
};
static ValidUtf8Result isValidUtf8(QByteArrayView in);
static int compareUtf8(QByteArrayView utf8, QStringView utf16) noexcept;
static int compareUtf8(QByteArrayView utf8, QLatin1StringView s);
static int compareUtf8(QByteArrayView utf8, QStringView utf16,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
static int compareUtf8(QByteArrayView utf8, QLatin1StringView s,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
static int compareUtf8(QByteArrayView lhs, QByteArrayView rhs,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
};
struct QUtf16

View File

@ -8,6 +8,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qstringliteral.h>
#include <QtCore/qstringalgorithms.h>
#include <QtCore/qutf8stringview.h>
#include <string>
@ -254,6 +255,12 @@ public:
[[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, other, cs); }
[[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
template<bool UseChar8T>
[[nodiscard]] int compare(QBasicUtf8StringView<UseChar8T> other,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{
return QtPrivate::compareStrings(*this, other, cs);
}
[[nodiscard]] constexpr int compare(QChar c) const noexcept
{ return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
[[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
@ -449,6 +456,15 @@ inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
R{{char16_t(c), u'\0'}} ;
}
// QBasicUtf8StringView functions:
template<bool UseChar8T>
[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(QStringView other,
Qt::CaseSensitivity cs) const noexcept
{
return QtPrivate::compareStrings(*this, other, cs);
}
QT_END_NAMESPACE
#endif /* QSTRINGVIEW_H */

View File

@ -280,6 +280,17 @@ public:
[[nodiscard]] constexpr qsizetype length() const noexcept
{ return size(); }
[[nodiscard]] int compare(QBasicUtf8StringView other,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{
return QtPrivate::compareStrings(*this, other, cs);
}
[[nodiscard]] int compare(QStringView other,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
[[nodiscard]] int compare(QLatin1StringView other,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
private:
[[nodiscard]] static inline int compare(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
{

View File

@ -406,6 +406,8 @@ private Q_SLOTS:
void member_compare_QStringView_QStringView() { member_compare_impl<QStringView, QStringView>(); }
void member_compare_QStringView_QLatin1String_data() { member_compare_data(); }
void member_compare_QStringView_QLatin1String() { member_compare_impl<QStringView, QLatin1String>(); }
void member_compare_QStringView_QUtf8StringView_data() { member_compare_data(); }
void member_compare_QStringView_QUtf8StringView() { member_compare_impl<QStringView, QUtf8StringView>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QStringView_QByteArray_data() { member_compare_data(); }
void member_compare_QStringView_QByteArray() { member_compare_impl<QStringView, QByteArray>(); }
@ -427,6 +429,8 @@ private Q_SLOTS:
void member_compare_QLatin1String_QStringView() { member_compare_impl<QLatin1String, QStringView>(); }
void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); }
void member_compare_QLatin1String_QLatin1String() { member_compare_impl<QLatin1String, QLatin1String>(); }
void member_compare_QLatin1String_QUtf8StringView_data() { member_compare_data(); }
void member_compare_QLatin1String_QUtf8StringView() { member_compare_impl<QLatin1String, QUtf8StringView>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); }
void member_compare_QLatin1String_QByteArray() { member_compare_impl<QLatin1String, QByteArray>(); }
@ -470,6 +474,19 @@ private Q_SLOTS:
void member_compare_QByteArrayView_const_char_star_data() { member_compare_data(); }
void member_compare_QByteArrayView_const_char_star() { member_compare_impl<QByteArrayView, const char *>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QUtf8StringView_QChar_data() { member_compare_data(false); }
void member_compare_QUtf8StringView_QChar() { member_compare_impl<QUtf8StringView, QChar>(); }
void member_compare_QUtf8StringView_char16_t_data() { member_compare_data(false); }
void member_compare_QUtf8StringView_char16_t() { member_compare_impl<QUtf8StringView, char16_t>(); }
#endif
void member_compare_QUtf8StringView_QString_data() { member_compare_data(); }
void member_compare_QUtf8StringView_QString() { member_compare_impl<QUtf8StringView, QString>(); }
void member_compare_QUtf8StringView_QLatin1String_data() { member_compare_data(); }
void member_compare_QUtf8StringView_QLatin1String() { member_compare_impl<QUtf8StringView, QLatin1String>(); }
void member_compare_QUtf8StringView_QUtf8StringView_data() { member_compare_data(); }
void member_compare_QUtf8StringView_QUtf8StringView() { member_compare_impl<QUtf8StringView, QUtf8StringView>(); }
private:
void localeAwareCompare_data();
template<typename LHS, typename RHS>

View File

@ -11,3 +11,4 @@ add_subdirectory(qstringlist)
add_subdirectory(qstringtokenizer)
add_subdirectory(qregularexpression)
add_subdirectory(qstring)
add_subdirectory(qutf8stringview)

View File

@ -0,0 +1,14 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qutf8stringview Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qutf8stringview
SOURCES
tst_bench_qutf8stringview.cpp
LIBRARIES
Qt::Test
Qt::CorePrivate
)

View File

@ -0,0 +1,263 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: BSD-3-Clause
#include <qbytearray.h>
#include <qdebug.h>
#include <qstring.h>
#include <qtest.h>
#include <qutf8stringview.h>
class tst_QUtf8StringView : public QObject
{
Q_OBJECT
private slots:
void equalStringsLatin1_data() { equalStrings_data(); }
void equalStringsLatin1();
void equalStringsUtf16_data() { equalStrings_data(); }
void equalStringsUtf16();
void equalStringsUtf8_data() { equalStrings_data(); }
void equalStringsUtf8();
void compareStringsCaseSensitiveLatin1_data() { compareStringsCaseSensitive_data(); }
void compareStringsCaseSensitiveLatin1() { compareStringsLatin1(true); }
void compareStringsCaseSensitiveUtf16_data() { compareStringsCaseSensitive_data(); }
void compareStringsCaseSensitiveUtf16() { compareStringsUtf16(true); }
void compareStringsCaseSensitiveUtf8_data() { compareStringsCaseSensitive_data(); }
void compareStringsCaseSensitiveUtf8() { compareStringsUtf8(true); }
void compareStringsCaseInsensitiveLatin1_data() { compareStringsCaseInsensitive_data(); }
void compareStringsCaseInsensitiveLatin1() { compareStringsLatin1(false); }
void compareStringsCaseInsensitiveUtf16_data() { compareStringsCaseInsensitive_data(); }
void compareStringsCaseInsensitiveUtf16() { compareStringsUtf16(false); }
void compareStringsCaseInsensitiveUtf8_data() { compareStringsCaseInsensitive_data(); }
void compareStringsCaseInsensitiveUtf8() { compareStringsUtf8(false); }
void compareStringsWithErrors_data();
void compareStringsWithErrors();
private:
void equalStrings_data();
void compareStringsCaseSensitive_data();
void compareStringsCaseInsensitive_data();
void compareStringsLatin1(bool caseSensitive);
void compareStringsUtf16(bool caseSensitive);
void compareStringsUtf8(bool caseSensitive);
};
void tst_QUtf8StringView::equalStrings_data()
{
QTest::addColumn<QString>("lhs");
QTest::addColumn<QString>("rhs");
QTest::addColumn<bool>("isEqual");
QTest::newRow("EqualStrings") << "Test"
<< "Test" << true;
QTest::newRow("EqualStringsLong")
<< "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
<< "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("DifferentCase") << "test"
<< "Test" << false;
QTest::newRow("DifferentCaseLong")
<< "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
<< "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" << false;
QTest::newRow("ReverseStrings") << "Test"
<< "tseT" << false;
QTest::newRow("Latin1RangeCharacter") << u8"B\u00d8" << u8"B\u00d8" << true;
QTest::newRow("Latin1RangeCharacterDifferentCase") << u8"B\u00d8" << u8"B\u00f8" << false;
}
void tst_QUtf8StringView::equalStringsLatin1()
{
QFETCH(QString, lhs);
QFETCH(QString, rhs);
QFETCH(bool, isEqual);
QByteArray left = lhs.toUtf8();
QByteArray right = rhs.toLatin1();
QBasicUtf8StringView<false> lhv(left);
QLatin1StringView rhv(right);
bool result;
QBENCHMARK {
result = QtPrivate::equalStrings(lhv, rhv);
};
QCOMPARE(result, isEqual);
}
void tst_QUtf8StringView::equalStringsUtf16()
{
QFETCH(QString, lhs);
QFETCH(QString, rhs);
QFETCH(bool, isEqual);
QByteArray left = lhs.toUtf8();
QBasicUtf8StringView<false> lhv(left);
QStringView rhv(rhs);
bool result;
QBENCHMARK {
result = QtPrivate::equalStrings(lhv, rhv);
};
QCOMPARE(result, isEqual);
}
void tst_QUtf8StringView::equalStringsUtf8()
{
QFETCH(QString, lhs);
QFETCH(QString, rhs);
QFETCH(bool, isEqual);
QByteArray left = lhs.toUtf8();
QByteArray right = rhs.toUtf8();
QBasicUtf8StringView<false> lhv(left);
QBasicUtf8StringView<false> rhv(right);
bool result;
QBENCHMARK {
result = QtPrivate::equalStrings(lhv, rhv);
};
QCOMPARE(result, isEqual);
}
void tst_QUtf8StringView::compareStringsCaseSensitive_data()
{
QTest::addColumn<QString>("lhs");
QTest::addColumn<QString>("rhs");
QTest::addColumn<int>("compareValue");
QTest::newRow("EqualStrings") << "Test"
<< "Test" << 0;
QTest::newRow("EqualStringsLong") << "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"
<< "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ" << 0;
QTest::newRow("DifferentCase") << "test"
<< "Test" << 32;
QTest::newRow("DifferentCaseLong")
<< "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"
<< "abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz" << -32;
QTest::newRow("ReverseStrings") << "Test"
<< "tseT" << -32;
QTest::newRow("Different Strings") << "Testing and testing"
<< "Testing and resting" << 2;
QTest::newRow("Latin1RangeCharacter") << u8"B\u00d8" << u8"B\u00d8" << 0;
QTest::newRow("Latin1RangeCharacterDifferentCase") << u8"B\u00d8" << u8"B\u00f8" << -32;
}
void tst_QUtf8StringView::compareStringsCaseInsensitive_data()
{
QTest::addColumn<QString>("lhs");
QTest::addColumn<QString>("rhs");
QTest::addColumn<int>("compareValue");
QTest::newRow("EqualStrings") << "Test"
<< "Test" << 0;
QTest::newRow("EqualStringsLong") << "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"
<< "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ" << 0;
QTest::newRow("DifferentCase") << "test"
<< "Test" << 0;
QTest::newRow("DifferentCaseLong") << "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"
<< "abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz" << 0;
QTest::newRow("ReverseStrings") << "Test"
<< "tseT" << -14;
QTest::newRow("Different Strings") << "Testing and testing"
<< "Testing and resting" << 2;
QTest::newRow("Latin1RangeCharacter") << u8"B\u00d8" << u8"B\u00d8" << 0;
QTest::newRow("Latin1RangeCharacterDifferentCase") << u8"B\u00d8" << u8"B\u00f8" << 0;
}
void tst_QUtf8StringView::compareStringsLatin1(bool caseSensitive)
{
QFETCH(QString, lhs);
QFETCH(QString, rhs);
QFETCH(int, compareValue);
QByteArray left = lhs.toUtf8();
QByteArray right = rhs.toLatin1();
QBasicUtf8StringView<false> lhv(left);
QLatin1StringView rhv(right);
Qt::CaseSensitivity cs = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
int result;
QBENCHMARK {
result = lhv.compare(rhv, cs);
};
QCOMPARE(result, compareValue);
}
void tst_QUtf8StringView::compareStringsUtf16(bool caseSensitive)
{
QFETCH(QString, lhs);
QFETCH(QString, rhs);
QFETCH(int, compareValue);
QByteArray left = lhs.toUtf8();
QBasicUtf8StringView<false> lhv(left);
QStringView rhv(rhs);
Qt::CaseSensitivity cs = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
int result;
QBENCHMARK {
result = lhv.compare(rhv, cs);
};
QCOMPARE(result, compareValue);
}
void tst_QUtf8StringView::compareStringsUtf8(bool caseSensitive)
{
QFETCH(QString, lhs);
QFETCH(QString, rhs);
QFETCH(int, compareValue);
QByteArray left = lhs.toUtf8();
QByteArray right = rhs.toUtf8();
QBasicUtf8StringView<false> lhv(left);
QBasicUtf8StringView<false> rhv(right);
Qt::CaseSensitivity cs = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
int result;
QBENCHMARK {
result = lhv.compare(rhv, cs);
};
QCOMPARE(result, compareValue);
}
void tst_QUtf8StringView::compareStringsWithErrors_data()
{
QTest::addColumn<QByteArray>("lhs");
QTest::addColumn<QByteArray>("rhs");
QTest::addColumn<int>("compare");
QTest::addColumn<bool>("caseSensitive");
QTest::newRow("Compare errors 0xfe vs 0xff case-insensitive")
<< QByteArray("\xfe") << QByteArray("\xff") << 0 << false;
QTest::newRow("Compare errors 0xff vs 0xff case-insensitive")
<< QByteArray("\xff") << QByteArray("\xff") << 0 << false;
QTest::newRow("Compare 'a' with error 0xff case-insensitive")
<< QByteArray("a") << QByteArray("\xff") << -65436 << false;
QTest::newRow("Compare errors 0xfe vs 0xff case-sensitive")
<< QByteArray("\xfe") << QByteArray("\xff") << -1 << true;
QTest::newRow("Compare errors 0xff vs 0xff case-sensitive")
<< QByteArray("\xff") << QByteArray("\xff") << 0 << true;
QTest::newRow("Compare 'a' with error 0xff case-sensitive")
<< QByteArray("a") << QByteArray("\xff") << -158 << true;
}
void tst_QUtf8StringView::compareStringsWithErrors()
{
QFETCH(QByteArray, lhs);
QFETCH(QByteArray, rhs);
QFETCH(int, compare);
QFETCH(bool, caseSensitive);
QBasicUtf8StringView<false> lhv(lhs);
QBasicUtf8StringView<false> rhv(rhs);
Qt::CaseSensitivity cs = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
int result;
QBENCHMARK {
result = lhv.compare(rhv, cs);
};
QCOMPARE(result, compare);
QCOMPARE(-result, rhv.compare(lhv, cs));
}
QTEST_MAIN(tst_QUtf8StringView)
#include "tst_bench_qutf8stringview.moc"