From 681bd76e671939b6717f1a35ec9b8383f48fb294 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 25 Mar 2019 14:42:19 +0300 Subject: QStringView, QLatin1String: add indexOf methods [ChangeLog][QtCore][QLatin1String] Added indexOf(). [ChangeLog][QtCore][QStringView] Added indexOf(). Change-Id: I9f56e5b40030e39b29e50914a46beb58013b537b Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 102 +++++++++++++-- src/corelib/tools/qstring.h | 22 +++- src/corelib/tools/qstringalgorithms.h | 3 +- src/corelib/tools/qstringview.cpp | 19 +++ src/corelib/tools/qstringview.h | 7 + .../qstringapisymmetry/tst_qstringapisymmetry.cpp | 145 +++++++++++++++++++++ 6 files changed, 286 insertions(+), 12 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 93d81b89b6..9cfbbead30 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -144,6 +144,7 @@ extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const ushort *src, int leng // internal qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs); +static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept; static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs); static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs); static inline qsizetype qt_string_count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs); @@ -3680,6 +3681,7 @@ bool QString::operator>(QLatin1String other) const noexcept \sa QT_NO_CAST_FROM_ASCII */ +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns the index position of the first occurrence of the string \a str in this string, searching forward from index position \a @@ -3702,6 +3704,25 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const // ### Qt6: qsize return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } +#endif // QT_STRINGVIEW_LEVEL < 2 + +/*! + \fn int QString::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const + \since 5.14 + \overload indexOf() + + Returns the index position of the first occurrence of the string view \a str + in this string, searching forward from index position \a from. + Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QStringView::indexOf(), lastIndexOf(), contains(), count() +*/ /*! \since 4.5 @@ -3738,9 +3759,10 @@ int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { // ### Qt6: qsize - return int(QtPrivate::findChar(QStringView(unicode(), length()), ch, from, cs)); + return int(qFindChar(QStringView(unicode(), length()), ch, from, cs)); } +#if QT_STRINGVIEW_LEVEL < 2 /*! \since 4.8 @@ -3758,6 +3780,7 @@ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) co // ### Qt6: qsize return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } +#endif // QT_STRINGVIEW_LEVEL < 2 static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs) { @@ -9480,6 +9503,25 @@ QString &QString::setRawData(const QChar *unicode, int size) \sa startsWith() */ +/*! + \fn int QLatin1String::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const + \fn int QLatin1String::indexOf(QLatin1String l1, int from Qt::CaseSensitivity cs) const + \fn int QLatin1String::indexOf(QChar c, int from, Qt::CaseSensitivity cs) const + \since 5.14 + + Returns the index position of the first occurrence of the string-view \a str, + Latin-1 string \a l1, or character \a ch, respectively, in this Latin-1 string, + searching forward from index position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf() +*/ + /*! \fn QLatin1String::const_iterator QLatin1String::begin() const \since 5.10 @@ -11035,6 +11077,7 @@ QStringRef QString::midRef(int position, int n) const \sa QString::chop(), truncate() */ +#if QT_STRINGVIEW_LEVEL < 2 /*! \since 4.8 @@ -11055,6 +11098,25 @@ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) co // ### Qt6: qsize return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } +#endif // QT_STRINGVIEW_LEVEL < 2 + +/*! + \fn int QStringRef::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const + \since 5.14 + \overload indexOf() + + Returns the index position of the first occurrence of the string view \a str + in this string reference, searching forward from index position \a from. + Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), QStringView::indexOf(), lastIndexOf(), contains(), count() +*/ /*! \since 4.8 @@ -11069,7 +11131,7 @@ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) co int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { // ### Qt6: qsize - return int(QtPrivate::findChar(QStringView(unicode(), length()), ch, from, cs)); + return int(qFindChar(QStringView(unicode(), length()), ch, from, cs)); } /*! @@ -11093,6 +11155,7 @@ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) con return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs)); } +#if QT_STRINGVIEW_LEVEL < 2 /*! \since 4.8 @@ -11112,6 +11175,7 @@ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) // ### Qt6: qsize return int(QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs)); } +#endif // QT_STRINGVIEW_LEVEL < 2 /*! \since 4.8 @@ -11711,7 +11775,7 @@ bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseS position \a from. Returns -1 if \a ch could not be found. */ -qsizetype QtPrivate::findChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept +static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept { if (from < 0) from = qMax(from + str.size(), qsizetype(0)); @@ -11749,7 +11813,7 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi return -1; if (sl == 1) - return QtPrivate::findChar(haystack0, needle0[0], from, cs); + return qFindChar(haystack0, needle0[0], from, cs); /* We use the Boyer-Moore algorithm in cases where the overhead @@ -11815,12 +11879,32 @@ qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1Str if (haystack.size() < needle.size()) return -1; - const char *latin1 = needle.latin1(); - const qsizetype len = needle.size(); - QVarLengthArray s(len); - qt_from_latin1(s.data(), latin1, len); + QVarLengthArray s(needle.size()); + qt_from_latin1(s.data(), needle.latin1(), needle.size()); + return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast(s.constData()), s.size()), cs); +} + +qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept +{ + if (haystack.size() < needle.size()) + return -1; + + QVarLengthArray s(haystack.size()); + qt_from_latin1(s.data(), haystack.latin1(), haystack.size()); + return QtPrivate::findString(QStringView(reinterpret_cast(s.constData()), s.size()), from, needle, cs); +} + +qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept +{ + if (haystack.size() < needle.size()) + return -1; - return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast(s.constData()), len), cs); + QVarLengthArray h(haystack.size()); + qt_from_latin1(h.data(), haystack.latin1(), haystack.size()); + QVarLengthArray n(needle.size()); + qt_from_latin1(n.data(), needle.latin1(), needle.size()); + return QtPrivate::findString(QStringView(reinterpret_cast(h.constData()), h.size()), from, + QStringView(reinterpret_cast(n.constData()), n.size()), cs); } /*! diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index e4798eb51b..0c80cb864a 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -2,6 +2,7 @@ ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2019 Mail.ru Group. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -130,6 +131,13 @@ public: Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); } + Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize + Q_REQUIRED_RESULT int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize + Q_REQUIRED_RESULT inline int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return int(QtPrivate::findString(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsize + using value_type = const char; using reference = value_type&; using const_reference = reference; @@ -214,6 +222,8 @@ bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const noex { return QtPrivate::startsWith(*this, s, cs); } bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::endsWith(*this, s, cs); } +qsizetype QStringView::indexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept +{ return QtPrivate::findString(*this, from, s, cs); } class Q_CORE_EXPORT QString { @@ -328,9 +338,13 @@ public: static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2); int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; - int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#if QT_STRINGVIEW_LEVEL < 2 + int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QStringRef &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#endif + Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -1451,10 +1465,14 @@ public: inline int count() const { return m_size; } inline int length() const { return m_size; } +#if QT_STRINGVIEW_LEVEL < 2 int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#endif + Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; - int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h index 8e7fc0af9b..51a86cfeb5 100644 --- a/src/corelib/tools/qstringalgorithms.h +++ b/src/corelib/tools/qstringalgorithms.h @@ -75,9 +75,10 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; -Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) noexcept; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) noexcept; diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp index c863ca7ce2..160654b419 100644 --- a/src/corelib/tools/qstringview.cpp +++ b/src/corelib/tools/qstringview.cpp @@ -720,6 +720,25 @@ QT_BEGIN_NAMESPACE \sa startsWith() */ +/*! + \fn qsizetype QStringView::indexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const + \fn qsizetype QStringView::indexOf(QLatin1String l1, qsizetype from Qt::CaseSensitivity cs) const + \fn qsizetype QStringView::indexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const + \since 5.14 + + Returns the index position of the first occurrence of the string-view \a str, + Latin-1 string \a l1, or character \a ch, respectively, in this string-view, + searching forward from index position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf() +*/ + /*! \fn QByteArray QStringView::toLatin1() const diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h index 5b6d63b71c..bbf51b24f6 100644 --- a/src/corelib/tools/qstringview.h +++ b/src/corelib/tools/qstringview.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz +** Copyright (C) 2019 Mail.ru Group. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -269,6 +270,12 @@ public: Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); } + Q_REQUIRED_RESULT qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); } + Q_REQUIRED_RESULT qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return QtPrivate::findString(*this, from, s, cs); } + Q_REQUIRED_RESULT inline qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + Q_REQUIRED_RESULT bool isRightToLeft() const noexcept { return QtPrivate::isRightToLeft(*this); } diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp index cb1fd9eb7d..b52c15fd73 100644 --- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -416,6 +416,47 @@ private Q_SLOTS: void toUcs4_QStringRef() { toUcs4_impl(); } void toUcs4_QStringView_data() { toUcs4_data(); } void toUcs4_QStringView() { toUcs4_impl(); } + +private: + template void indexOf_impl() const; + void indexOf_data(); + +private Q_SLOTS: + void indexOf_QString_QString_data() { indexOf_data(); } + void indexOf_QString_QString() { indexOf_impl(); } + void indexOf_QString_QLatin1String_data() { indexOf_data(); } + void indexOf_QString_QLatin1String() { indexOf_impl(); } + void indexOf_QString_QStringRef_data() { indexOf_data(); } + void indexOf_QString_QStringRef() { indexOf_impl(); } + void indexOf_QString_QStringView_data() { indexOf_data(); } + void indexOf_QString_QStringView() { indexOf_impl(); } + + void indexOf_QLatin1String_QString_data() { indexOf_data(); } + void indexOf_QLatin1String_QString() { indexOf_impl(); } + void indexOf_QLatin1String_QLatin1String_data() { indexOf_data(); } + void indexOf_QLatin1String_QLatin1String() { indexOf_impl(); } + void indexOf_QLatin1String_QStringRef_data() { indexOf_data(); } + void indexOf_QLatin1String_QStringRef() { indexOf_impl(); } + void indexOf_QLatin1String_QStringView_data() { indexOf_data(); } + void indexOf_QLatin1String_QStringView() { indexOf_impl(); } + + void indexOf_QStringRef_QString_data() { indexOf_data(); } + void indexOf_QStringRef_QString() { indexOf_impl(); } + void indexOf_QStringRef_QLatin1String_data() { indexOf_data(); } + void indexOf_QStringRef_QLatin1String() { indexOf_impl(); } + void indexOf_QStringRef_QStringRef_data() { indexOf_data(); } + void indexOf_QStringRef_QStringRef() { indexOf_impl(); } + void indexOf_QStringRef_QStringView_data() { indexOf_data(); } + void indexOf_QStringRef_QStringView() { indexOf_impl(); } + + void indexOf_QStringView_QString_data() { indexOf_data(); } + void indexOf_QStringView_QString() { indexOf_impl(); } + void indexOf_QStringView_QLatin1String_data() { indexOf_data(); } + void indexOf_QStringView_QLatin1String() { indexOf_impl(); } + void indexOf_QStringView_QStringRef_data() { indexOf_data(); } + void indexOf_QStringView_QStringRef() { indexOf_impl(); } + void indexOf_QStringView_QStringView_data() { indexOf_data(); } + void indexOf_QStringView_QStringView() { indexOf_impl(); } }; void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty) @@ -540,6 +581,7 @@ void tst_QStringApiSymmetry::compare_impl() const } static QString empty = QLatin1String(""); +static QString null; // the tests below rely on the fact that these objects' names match their contents: static QString a = QStringLiteral("a"); static QString A = QStringLiteral("A"); @@ -1216,6 +1258,109 @@ void tst_QStringApiSymmetry::toUcs4_impl() QCOMPARE(unicode.isEmpty(), ucs4.isEmpty()); } +void tst_QStringApiSymmetry::indexOf_data() +{ + QTest::addColumn("haystackU16"); + QTest::addColumn("haystackL1"); + QTest::addColumn("needleU16"); + QTest::addColumn("needleL1"); + QTest::addColumn("startpos"); + QTest::addColumn("resultCS"); + QTest::addColumn("resultCIS"); + + constexpr qsizetype zeroPos = 0; + constexpr qsizetype minus1Pos = -1; + + QTest::addRow("haystack: null, needle: null") << null << QLatin1String() + << null << QLatin1String() << zeroPos << zeroPos << zeroPos; + QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") + << null << QLatin1String() << zeroPos << zeroPos << zeroPos; + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + << null << QLatin1String() << zeroPos << zeroPos << zeroPos; + QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() + << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; + QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") + << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; + QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") + << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos; + QTest::addRow("haystack: null, needle: a") << null << QLatin1String() + << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos; + + +#define ROW(h, n, st, cs, cis) \ + QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \ + << n << QLatin1String(#n) \ + << qsizetype(st) << qsizetype(cs) << qsizetype(cis) + + ROW(abc, a, 0, 0, 0); + ROW(abc, A, 0, -1, 0); + ROW(abc, a, 1, -1, -1); + ROW(abc, A, 1, -1, -1); + ROW(abc, b, 0, 1, 1); + ROW(abc, B, 0, -1, 1); + ROW(abc, b, 1, 1, 1); + ROW(abc, B, 1, -1, 1); + ROW(abc, B, 2, -1, -1); + + ROW(ABC, A, 0, 0, 0); + ROW(ABC, a, 0, -1, 0); + ROW(ABC, A, 1, -1, -1); + ROW(ABC, a, 1, -1, -1); + ROW(ABC, B, 0, 1, 1); + ROW(ABC, b, 0, -1, 1); + ROW(ABC, B, 1, 1, 1); + ROW(ABC, b, 1, -1, 1); + ROW(ABC, B, 2, -1, -1); + + ROW(aBc, bc, 0, -1, 1); + ROW(aBc, Bc, 0, 1, 1); + ROW(aBc, bC, 0, -1, 1); + ROW(aBc, BC, 0, -1, 1); + + ROW(AbC, bc, 0, -1, 1); + ROW(AbC, Bc, 0, -1, 1); + ROW(AbC, bC, 0, 1, 1); + ROW(AbC, BC, 0, -1, 1); + ROW(AbC, BC, 1, -1, 1); + ROW(AbC, BC, 2, -1, -1); +#undef ROW + +} + +template +void tst_QStringApiSymmetry::indexOf_impl() const +{ + QFETCH(const QString, haystackU16); + QFETCH(const QLatin1String, haystackL1); + QFETCH(const QString, needleU16); + QFETCH(const QLatin1String, needleL1); + QFETCH(const qsizetype, startpos); + QFETCH(const qsizetype, resultCS); + QFETCH(const qsizetype, resultCIS); + + const auto haystackU8 = haystackU16.toUtf8(); + const auto needleU8 = needleU16.toUtf8(); + + const auto haystack = make(QStringRef(&haystackU16), haystackL1, haystackU8); + const auto needle = make(QStringRef(&needleU16), needleL1, needleU8); + + using size_type = typename Haystack::size_type; + + QCOMPARE(haystack.indexOf(needle, startpos), size_type(resultCS)); + QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS)); + QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS)); + + if (needle.size() == 1) + { + QCOMPARE(haystack.indexOf(needle[0], startpos), size_type(resultCS)); + QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS)); + QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS)); + } +} + + QTEST_APPLESS_MAIN(tst_QStringApiSymmetry) #include "tst_qstringapisymmetry.moc" -- cgit v1.2.3