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:
parent
724329b79e
commit
b977ae371a
@ -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
|
||||
|
@ -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:
|
||||
//
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -11,3 +11,4 @@ add_subdirectory(qstringlist)
|
||||
add_subdirectory(qstringtokenizer)
|
||||
add_subdirectory(qregularexpression)
|
||||
add_subdirectory(qstring)
|
||||
add_subdirectory(qutf8stringview)
|
||||
|
14
tests/benchmarks/corelib/text/qutf8stringview/CMakeLists.txt
Normal file
14
tests/benchmarks/corelib/text/qutf8stringview/CMakeLists.txt
Normal 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
|
||||
)
|
@ -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"
|
Loading…
Reference in New Issue
Block a user