summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2020-12-02 12:31:41 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2020-12-10 02:15:18 +0100
commitce0b76731042412a0fa5a5f633fc48a52f79ef81 (patch)
treeb0e697beba8c24158a6312341417b82b6a561d2c
parentbe83ff65c424cff1036e7da19d6175826d9f7ed9 (diff)
QStringView: add some QRegularExpression-related overloads
[ChangeLog][QtCore][QStringView] Added the indexOf(), contains(), lastIndexOf() and count() methods taking a QRegularExpression. Fixes: QTBUG-89050 Change-Id: Ic726754f67e06b3764302d2fad252e0378a77afc Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/text/qstring.cpp78
-rw-r--r--src/corelib/text/qstringalgorithms.h17
-rw-r--r--src/corelib/text/qstringview.cpp61
-rw-r--r--src/corelib/text/qstringview.h20
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp207
5 files changed, 383 insertions, 0 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 92eed93251..07b8c8512b 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -10259,6 +10259,84 @@ qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1
return qLastIndexOf(haystack, from, needle, cs);
}
+#if QT_CONFIG(regularexpression)
+qsizetype QtPrivate::indexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
+{
+ if (!re.isValid()) {
+ qWarning("QStringView::indexOf: invalid QRegularExpression object");
+ return -1;
+ }
+
+ QRegularExpressionMatch match = re.match(haystack, from);
+ if (match.hasMatch()) {
+ const qsizetype ret = match.capturedStart();
+ if (rmatch)
+ *rmatch = std::move(match);
+ return ret;
+ }
+
+ return -1;
+}
+
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
+{
+ if (!re.isValid()) {
+ qWarning("QStringView::lastIndexOf: invalid QRegularExpression object");
+ return -1;
+ }
+
+ qsizetype endpos = (from < 0) ? (haystack.size() + from + 1) : (from);
+ QRegularExpressionMatchIterator iterator = re.globalMatch(haystack);
+ qsizetype lastIndex = -1;
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ qsizetype start = match.capturedStart();
+ if (start <= endpos) {
+ lastIndex = start;
+ if (rmatch)
+ *rmatch = std::move(match);
+ } else {
+ break;
+ }
+ }
+
+ return lastIndex;
+}
+
+bool QtPrivate::contains(QStringView haystack, const QRegularExpression &re, QRegularExpressionMatch *rmatch)
+{
+ if (!re.isValid()) {
+ qWarning("QStringView::contains: invalid QRegularExpression object");
+ return false;
+ }
+ QRegularExpressionMatch m = re.match(haystack);
+ bool hasMatch = m.hasMatch();
+ if (hasMatch && rmatch)
+ *rmatch = std::move(m);
+ return hasMatch;
+}
+
+qsizetype QtPrivate::count(QStringView haystack, const QRegularExpression &re)
+{
+ if (!re.isValid()) {
+ qWarning("QStringView::count: invalid QRegularExpression object");
+ return 0;
+ }
+ qsizetype count = 0;
+ qsizetype index = -1;
+ qsizetype len = haystack.length();
+ while (index <= len - 1) {
+ QRegularExpressionMatch match = re.match(haystack, index + 1);
+ if (!match.hasMatch())
+ break;
+ index = match.capturedStart();
+ count++;
+ }
+ return count;
+}
+
+#endif // QT_CONFIG(regularexpression)
+
/*!
\since 5.0
diff --git a/src/corelib/text/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h
index 6d8fe114f1..870ae42af8 100644
--- a/src/corelib/text/qstringalgorithms.h
+++ b/src/corelib/text/qstringalgorithms.h
@@ -70,6 +70,8 @@ class QStringView;
template <bool> class QBasicUtf8StringView;
class QAnyStringView;
class QChar;
+class QRegularExpression;
+class QRegularExpressionMatch;
namespace QtPrivate {
@@ -122,6 +124,21 @@ namespace QtPrivate {
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+#if QT_CONFIG(regularexpression)
+[[nodiscard]] Q_CORE_EXPORT qsizetype indexOf(QStringView haystack,
+ const QRegularExpression &re,
+ qsizetype from = 0,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT qsizetype lastIndexOf(QStringView haystack,
+ const QRegularExpression &re,
+ qsizetype from = -1,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT bool contains(QStringView haystack,
+ const QRegularExpression &re,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT qsizetype count(QStringView haystack, const QRegularExpression &re);
+#endif
+
[[nodiscard]] Q_CORE_EXPORT QString convertToQString(QAnyStringView s);
[[nodiscard]] Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str);
diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp
index 1b8db705b4..b64d128a65 100644
--- a/src/corelib/text/qstringview.cpp
+++ b/src/corelib/text/qstringview.cpp
@@ -881,6 +881,67 @@ QT_BEGIN_NAMESPACE
\sa QString::lastIndexOf()
*/
+#if QT_CONFIG(regularexpression)
+/*!
+ \fn qsizetype QStringView::indexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
+ \since 6.1
+
+ Returns the index position of the first match of the regular
+ expression \a re in the string view, searching forward from index
+ position \a from. Returns -1 if \a re didn't match anywhere.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ \note Due to how the regular expression matching algorithm works,
+ this function will actually match repeatedly from the beginning of
+ the string view until the position \a from is reached.
+*/
+
+/*!
+ \fn qsizetype QStringView::lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
+ \since 6.1
+
+ Returns the index position of the last match of the regular
+ expression \a re in the string view, which starts before the index
+ position \a from. Returns -1 if \a re didn't match anywhere.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+*/
+
+/*!
+ \fn bool QStringView::contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const
+ \since 6.1
+
+ Returns \c true if the regular expression \a re matches somewhere in this
+ string view; otherwise returns \c false.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ \sa QRegularExpression::match()
+*/
+
+/*!
+ \fn qsizetype QStringView::count(const QRegularExpression &re) const
+ \since 6.1
+
+ Returns the number of times the regular expression \a re matches
+ in the string view.
+
+ For historical reasons, this function counts overlapping matches.
+ This behavior is different from simply iterating over the matches
+ in the string using QRegularExpressionMatchIterator.
+
+ \sa QRegularExpression::globalMatch()
+
+*/
+#endif // QT_CONFIG(regularexpression)
+
/*!
\fn QByteArray QStringView::toLatin1() const
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h
index df05fce252..42935440f3 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE
class QString;
class QStringView;
class QRegularExpression;
+class QRegularExpressionMatch;
namespace QtPrivate {
template <typename Char>
@@ -347,6 +348,25 @@ public:
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
[[nodiscard]] inline qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+#if QT_CONFIG(regularexpression)
+ [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const
+ {
+ return QtPrivate::indexOf(*this, re, from, rmatch);
+ }
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from = -1, QRegularExpressionMatch *rmatch = nullptr) const
+ {
+ return QtPrivate::lastIndexOf(*this, re, from, rmatch);
+ }
+ [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
+ {
+ return QtPrivate::contains(*this, re, rmatch);
+ }
+ [[nodiscard]] qsizetype count(const QRegularExpression &re) const
+ {
+ return QtPrivate::count(*this, re);
+ }
+#endif
+
[[nodiscard]] bool isRightToLeft() const noexcept
{ return QtPrivate::isRightToLeft(*this); }
[[nodiscard]] bool isValidUtf16() const noexcept
diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
index 7a3448fdd6..58a3b56b68 100644
--- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -830,6 +830,16 @@ private Q_SLOTS:
void lastIndexOf_QStringView_QChar() { lastIndexOf_impl<QStringView, QChar>(); }
void lastIndexOf_QStringView_char16_t_data() { lastIndexOf_data(false); }
void lastIndexOf_QStringView_char16_t() { lastIndexOf_impl<QStringView, char16_t>(); }
+
+private:
+ void indexOf_contains_lastIndexOf_count_regexp_data();
+ template <typename String> void indexOf_contains_lastIndexOf_count_regexp_impl() const;
+
+private Q_SLOTS:
+ void indexOf_regexp_QString_data() { indexOf_contains_lastIndexOf_count_regexp_data(); }
+ void indexOf_regexp_QString() { indexOf_contains_lastIndexOf_count_regexp_impl<QString>(); }
+ void indexOf_regexp_QStringView_data() { indexOf_contains_lastIndexOf_count_regexp_data(); }
+ void indexOf_regexp_QStringView() { indexOf_contains_lastIndexOf_count_regexp_impl<QStringView>(); }
};
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
@@ -2496,6 +2506,203 @@ void tst_QStringApiSymmetry::lastIndexOf_impl() const
}
+void tst_QStringApiSymmetry::indexOf_contains_lastIndexOf_count_regexp_data()
+{
+ QTest::addColumn<QString>("subject");
+ QTest::addColumn<QRegularExpression>("regexp");
+ QTest::addColumn<qsizetype>("leftFrom");
+ QTest::addColumn<qsizetype>("indexOf");
+ QTest::addColumn<qsizetype>("count");
+ QTest::addColumn<qsizetype>("rightFrom");
+ QTest::addColumn<qsizetype>("lastIndexOf");
+
+ const auto ROW = [](const char *subject,
+ const char *pattern,
+ QRegularExpression::PatternOptions options,
+ qsizetype leftFrom, qsizetype indexOf, qsizetype count,
+ qsizetype rightFrom, qsizetype lastIndexOf)
+ {
+ QTest::addRow("subject \"%s\" pattern \"%s\" options %d leftFrom %d rightFrom %d",
+ subject, pattern, (int)options, (int)leftFrom, (int)rightFrom)
+ << subject
+ << QRegularExpression(pattern, options)
+ << leftFrom
+ << indexOf
+ << count
+ << rightFrom
+ << lastIndexOf;
+ };
+
+ ROW("", "", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
+ ROW("test", "", QRegularExpression::NoPatternOption, 0, 0, 5, -1, 4);
+ ROW("", "^", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
+ ROW("", "$", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
+ ROW("", "^$", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
+ ROW("", "x", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("", "^x", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("", "x$", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("", "^x$", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+
+ ROW("test", "e", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "es", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "es", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "es?", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "es?", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "es+", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "es+", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "e.", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e.", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "e.*", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e.*", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "e(?=s)", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e(?!x)", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "ex?s", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "(?<=t)e", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "(?<!x)e", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, 0, 0);
+ ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, 1, 0);
+ ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, -1, 3);
+ ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, -2, 3);
+ ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, -3, 0);
+
+ ROW("test", "^es", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("test", "^es", QRegularExpression::NoPatternOption, 0, -1, 0, -2, -1);
+ ROW("test", "es$", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("test", "ex", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("test", "ex?", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "ex+", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("test", "e(?=x)", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+ ROW("test", "e(?!s)", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
+
+
+ ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -3, 1);
+ ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -4, 1);
+ ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -5, -1);
+ ROW("test", "e.*t$", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e.*t$", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
+ ROW("test", "e.*st", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "e.*st$", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
+ ROW("test", "t.*t", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
+ ROW("test", "t.*t", QRegularExpression::NoPatternOption, 0, 0, 1, -2, 0);
+ ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -1, 2);
+ ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -2, 2);
+ ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -3, 2);
+ ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -4, -1);
+
+ ROW("", "", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
+ ROW("test", "", QRegularExpression::CaseInsensitiveOption, 0, 0, 5, -1, 4);
+ ROW("test", "^", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
+ ROW("test", "^t", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
+ ROW("TEST", "^t", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
+ ROW("test", "e", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
+ ROW("TEST", "e", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
+ ROW("TEST", "es", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
+ ROW("test", "ES", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
+ ROW("TEST", "ex?s", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
+
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -1, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -2, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -3, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -4, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -5, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -6, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -7, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -8, 1);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 0, 1, 2, -1, 5);
+ ROW("testtest", "e.*s", QRegularExpression::NoPatternOption, 0, 1, 2, -1, 1);
+
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 1, 1, 2, -1, 5);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 1, 1, 2, -1, 5);
+ ROW("testtest", "e.*s", QRegularExpression::NoPatternOption, 1, 1, 2, -1, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 5);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 5);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -2, 5);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -3, 5);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -4, 5);
+ ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -5, 1);
+ ROW("testtest", "e.*s", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 1);
+
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 0, -1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 1, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 2, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 3, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 4, 1);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 5, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 6, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 7, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -2, -1, 0, -1, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -3, 5, 1, -1, 5);
+ ROW("testtest", "e", QRegularExpression::NoPatternOption, -4, 5, 1, -1, 5);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 0, 0);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 1, 0);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 2, 0);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 3, 3);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 4, 4);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 5, 4);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 6, 4);
+ ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 7, 7);
+ ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 0, -1);
+ ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 1, -1);
+ ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 2, -1);
+ ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 3, 3);
+ ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 4, 3);
+ ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, -1, 7);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 0, -1);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 1, -1);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 2, -1);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 3, 3);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 4, 3);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -2, -1, 0, 0, -1);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -3, -1, 0, 0, -1);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -4, -1, 0, 0, -1);
+ ROW("testtest", "tt", QRegularExpression::NoPatternOption, -5, 3, 1, -1, 3);
+
+ ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 1, 1, 1, -1, 5); // the count is 1 because in the test we _cut_ the string before the lookbehind
+ ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 5);
+ ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 3, 5, 1, -1, 5);
+ ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 4, 5, 1, -1, 5);
+ ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 5, 5, 0, -1, 5); // the count is 0 because in the test we _cut_ the string before the lookbehind
+ ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 6, -1, 0, -1, 5);
+
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::indexOf_contains_lastIndexOf_count_regexp_impl() const
+{
+ QFETCH(QString, subject);
+ QFETCH(QRegularExpression, regexp);
+ QFETCH(qsizetype, leftFrom);
+ QFETCH(qsizetype, indexOf);
+ QFETCH(qsizetype, count);
+ QFETCH(qsizetype, rightFrom);
+ QFETCH(qsizetype, lastIndexOf);
+
+ // indexOf
+ String s = subject;
+ qsizetype result = s.indexOf(regexp, leftFrom);
+ QCOMPARE(result, indexOf);
+
+ // contains
+ if (result >= 0)
+ QVERIFY(s.contains(regexp));
+ else if (leftFrom == 0)
+ QVERIFY(!s.contains(regexp));
+
+ // count
+ if (leftFrom >= 0)
+ QCOMPARE(s.mid(leftFrom).count(regexp), count);
+ else
+ QCOMPARE(s.mid(leftFrom + s.size()).count(regexp), count);
+
+ // lastIndexOf
+ result = s.lastIndexOf(regexp, rightFrom);
+ QCOMPARE(result, lastIndexOf);
+}
+
QTEST_APPLESS_MAIN(tst_QStringApiSymmetry)
#include "tst_qstringapisymmetry.moc"