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
|
bool QtPrivate::equalStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs) noexcept
|
||||||
{
|
{
|
||||||
QString r = rhs.toString();
|
return QUtf8::compareUtf8(QByteArrayView(rhs), lhs) == 0;
|
||||||
return QtPrivate::equalStrings(lhs, r); // ### optimize!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView rhs) noexcept
|
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
|
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
|
int QtPrivate::compareStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs) noexcept
|
||||||
{
|
{
|
||||||
if (lhs.isEmpty())
|
return QUtf8::compareUtf8(QByteArrayView(lhs), QByteArrayView(rhs), cs);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs) noexcept
|
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(); }
|
{ return isEmpty() ? -1 : front() == c ? int(size() > 1) : uchar(m_data[0]) - c.unicode(); }
|
||||||
[[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
|
[[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
|
||||||
{ return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
|
{ 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
|
[[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||||
{ return QtPrivate::startsWith(*this, s, cs); }
|
{ return QtPrivate::startsWith(*this, s, cs); }
|
||||||
@ -1230,6 +1236,13 @@ QString QBasicUtf8StringView<UseChar8T>::toString() const
|
|||||||
return QString::fromUtf8(data(), size());
|
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:
|
// QAnyStringView inline members that require QString:
|
||||||
//
|
//
|
||||||
|
@ -820,7 +820,7 @@ QUtf8::ValidUtf8Result QUtf8::isValidUtf8(QByteArrayView in)
|
|||||||
return { true, isValidAscii };
|
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 src1 = reinterpret_cast<const qchar8_t *>(utf8.data());
|
||||||
auto end1 = src1 + utf8.size();
|
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))
|
if (QChar::isHighSurrogate(uc2) && src2 < end2 && QChar::isLowSurrogate(*src2))
|
||||||
uc2 = QChar::surrogateToUcs4(uc2, *src2++);
|
uc2 = QChar::surrogateToUcs4(uc2, *src2++);
|
||||||
}
|
}
|
||||||
|
if (cs == Qt::CaseInsensitive) {
|
||||||
|
uc1 = QChar::toCaseFolded(uc1);
|
||||||
|
uc2 = QChar::toCaseFolded(uc2);
|
||||||
|
}
|
||||||
if (uc1 != uc2)
|
if (uc1 != uc2)
|
||||||
return int(uc1) - int(uc2);
|
return int(uc1) - int(uc2);
|
||||||
}
|
}
|
||||||
@ -857,7 +860,7 @@ int QUtf8::compareUtf8(QByteArrayView utf8, QStringView utf16) noexcept
|
|||||||
return (end1 > src1) - int(end2 > src2);
|
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;
|
char32_t uc1 = QChar::Null;
|
||||||
auto src1 = reinterpret_cast<const uchar *>(utf8.data());
|
auto src1 = reinterpret_cast<const uchar *>(utf8.data());
|
||||||
@ -875,6 +878,62 @@ int QUtf8::compareUtf8(QByteArrayView utf8, QLatin1StringView s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char32_t uc2 = *src2++;
|
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)
|
if (uc1 != uc2)
|
||||||
return int(uc1) - int(uc2);
|
return int(uc1) - int(uc2);
|
||||||
}
|
}
|
||||||
|
@ -276,8 +276,12 @@ struct QUtf8
|
|||||||
bool isValidAscii;
|
bool isValidAscii;
|
||||||
};
|
};
|
||||||
static ValidUtf8Result isValidUtf8(QByteArrayView in);
|
static ValidUtf8Result isValidUtf8(QByteArrayView in);
|
||||||
static int compareUtf8(QByteArrayView utf8, QStringView utf16) noexcept;
|
static int compareUtf8(QByteArrayView utf8, QStringView utf16,
|
||||||
static int compareUtf8(QByteArrayView utf8, QLatin1StringView s);
|
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
|
struct QUtf16
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <QtCore/qbytearray.h>
|
#include <QtCore/qbytearray.h>
|
||||||
#include <QtCore/qstringliteral.h>
|
#include <QtCore/qstringliteral.h>
|
||||||
#include <QtCore/qstringalgorithms.h>
|
#include <QtCore/qstringalgorithms.h>
|
||||||
|
#include <QtCore/qutf8stringview.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -254,6 +255,12 @@ public:
|
|||||||
[[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
[[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||||
{ return QtPrivate::compareStrings(*this, other, cs); }
|
{ return QtPrivate::compareStrings(*this, other, cs); }
|
||||||
[[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
|
[[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
|
[[nodiscard]] constexpr int compare(QChar c) const noexcept
|
||||||
{ return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
|
{ return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
|
||||||
[[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
|
[[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'}} ;
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif /* QSTRINGVIEW_H */
|
#endif /* QSTRINGVIEW_H */
|
||||||
|
@ -280,6 +280,17 @@ public:
|
|||||||
[[nodiscard]] constexpr qsizetype length() const noexcept
|
[[nodiscard]] constexpr qsizetype length() const noexcept
|
||||||
{ return size(); }
|
{ 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:
|
private:
|
||||||
[[nodiscard]] static inline int compare(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
|
[[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_QStringView() { member_compare_impl<QStringView, QStringView>(); }
|
||||||
void member_compare_QStringView_QLatin1String_data() { member_compare_data(); }
|
void member_compare_QStringView_QLatin1String_data() { member_compare_data(); }
|
||||||
void member_compare_QStringView_QLatin1String() { member_compare_impl<QStringView, QLatin1String>(); }
|
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
|
#ifdef NOT_YET_IMPLEMENTED
|
||||||
void member_compare_QStringView_QByteArray_data() { member_compare_data(); }
|
void member_compare_QStringView_QByteArray_data() { member_compare_data(); }
|
||||||
void member_compare_QStringView_QByteArray() { member_compare_impl<QStringView, QByteArray>(); }
|
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_QStringView() { member_compare_impl<QLatin1String, QStringView>(); }
|
||||||
void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); }
|
void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); }
|
||||||
void member_compare_QLatin1String_QLatin1String() { member_compare_impl<QLatin1String, QLatin1String>(); }
|
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
|
#ifdef NOT_YET_IMPLEMENTED
|
||||||
void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); }
|
void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); }
|
||||||
void member_compare_QLatin1String_QByteArray() { member_compare_impl<QLatin1String, QByteArray>(); }
|
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_data() { member_compare_data(); }
|
||||||
void member_compare_QByteArrayView_const_char_star() { member_compare_impl<QByteArrayView, const char *>(); }
|
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:
|
private:
|
||||||
void localeAwareCompare_data();
|
void localeAwareCompare_data();
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
|
@ -11,3 +11,4 @@ add_subdirectory(qstringlist)
|
|||||||
add_subdirectory(qstringtokenizer)
|
add_subdirectory(qstringtokenizer)
|
||||||
add_subdirectory(qregularexpression)
|
add_subdirectory(qregularexpression)
|
||||||
add_subdirectory(qstring)
|
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