diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2022-07-05 19:01:08 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2022-07-29 23:04:27 +0200 |
commit | e540d4a8647c41a3e710a555f5dcc44edb7dfcb4 (patch) | |
tree | 25c6441166d1647b95e8983ac48a2204e3390fe4 | |
parent | 8d6b274fa4c65e87443c0fbf8425229230385405 (diff) |
QRegularExpression: introduce (global)matchView
QRegularExpression::match (and globalMatch) is currently overloaded
for QString and QStringView. This creates a subtle API asymmetry:
QRegularExpression re;
auto m1 = re.match(getQString()); // OK
auto m2 = re.match(getStdU16String()); // Dangling
This goes against our decision that every time that there's a possible
lifetime issue at play, it should be "evident". Solving the lifetime
issue here is possible, but tricky -- since QRegularExpression
is out-of-line, one needs a type-erased container for the input
string (basically, std::any) to keep it alive and so on.
Instead I went for the simpler solution: deprecate match(QStringView)
and introduce matchView(QStringView) (same for globalMatch). This
makes it clear that the call is matching over a view and therefore
users are supposed to keep the source object alive.
Drive-by, remove the documentation that says that the QString
overloads might not keep the string alive: they do and forever will.
[ChangeLog][QtCore][QRegularExpression] Added the matchView()
and globalMatchView() functions that operate on string views.
The match(QStringView) and globalMatch(QStringView) overloads
have been deprecated.
Change-Id: I054b8605c2fdea59b556dcfea8920ef4eee78ee9
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/text/qregularexpression.cpp | 62 | ||||
-rw-r--r-- | src/corelib/text/qregularexpression.h | 18 | ||||
-rw-r--r-- | src/corelib/text/qstring.cpp | 25 | ||||
-rw-r--r-- | tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp | 33 |
4 files changed, 95 insertions, 43 deletions
diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp index a9b7f99975..f736f47059 100644 --- a/src/corelib/text/qregularexpression.cpp +++ b/src/corelib/text/qregularexpression.cpp @@ -1588,11 +1588,6 @@ qsizetype QRegularExpression::patternErrorOffset() const The returned QRegularExpressionMatch object contains the results of the match. - \note The data referenced by \a subject should remain valid as long - as there are QRegularExpressionMatch objects using it. At the moment - Qt makes a (shallow) copy of the data, but this behavior may change - in a future version of Qt. - \sa QRegularExpressionMatch, {normal matching} */ QRegularExpressionMatch QRegularExpression::match(const QString &subject, @@ -1610,9 +1605,26 @@ QRegularExpressionMatch QRegularExpression::match(const QString &subject, return QRegularExpressionMatch(*priv); } +#if QT_DEPRECATED_SINCE(6, 8) /*! \since 6.0 \overload + \obsolete + + Use matchView() instead. +*/ +QRegularExpressionMatch QRegularExpression::match(QStringView subjectView, + qsizetype offset, + MatchType matchType, + MatchOptions matchOptions) const +{ + return matchView(subjectView, offset, matchType, matchOptions); +} +#endif // QT_DEPRECATED_SINCE(6, 8) + +/*! + \since 6.5 + \overload Attempts to match the regular expression against the given \a subjectView string view, starting at the position \a offset inside the subject, using a @@ -1626,10 +1638,10 @@ QRegularExpressionMatch QRegularExpression::match(const QString &subject, \sa QRegularExpressionMatch, {normal matching} */ -QRegularExpressionMatch QRegularExpression::match(QStringView subjectView, - qsizetype offset, - MatchType matchType, - MatchOptions matchOptions) const +QRegularExpressionMatch QRegularExpression::matchView(QStringView subjectView, + qsizetype offset, + MatchType matchType, + MatchOptions matchOptions) const { d.data()->compilePattern(); auto priv = new QRegularExpressionMatchPrivate(*this, @@ -1650,11 +1662,6 @@ QRegularExpressionMatch QRegularExpression::match(QStringView subjectView, The returned QRegularExpressionMatchIterator is positioned before the first match result (if any). - \note The data referenced by \a subject should remain valid as long - as there are QRegularExpressionMatch objects using it. At the moment - Qt makes a (shallow) copy of the data, but this behavior may change - in a future version of Qt. - \sa QRegularExpressionMatchIterator, {global matching} */ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &subject, @@ -1671,9 +1678,26 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s return QRegularExpressionMatchIterator(*priv); } +#if QT_DEPRECATED_SINCE(6, 8) /*! \since 6.0 \overload + \obsolete + + Use globalMatchView() instead. +*/ +QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView, + qsizetype offset, + MatchType matchType, + MatchOptions matchOptions) const +{ + return globalMatchView(subjectView, offset, matchType, matchOptions); +} +#endif // QT_DEPRECATED_SINCE(6, 8) + +/*! + \since 6.5 + \overload Attempts to perform a global match of the regular expression against the given \a subjectView string view, starting at the position \a offset inside the @@ -1689,16 +1713,16 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s \sa QRegularExpressionMatchIterator, {global matching} */ -QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView, - qsizetype offset, - MatchType matchType, - MatchOptions matchOptions) const +QRegularExpressionMatchIterator QRegularExpression::globalMatchView(QStringView subjectView, + qsizetype offset, + MatchType matchType, + MatchOptions matchOptions) const { QRegularExpressionMatchIteratorPrivate *priv = new QRegularExpressionMatchIteratorPrivate(*this, matchType, matchOptions, - match(subjectView, offset, matchType, matchOptions)); + matchView(subjectView, offset, matchType, matchOptions)); return QRegularExpressionMatchIterator(*priv); } diff --git a/src/corelib/text/qregularexpression.h b/src/corelib/text/qregularexpression.h index 9b7de26d07..fc0f1302e3 100644 --- a/src/corelib/text/qregularexpression.h +++ b/src/corelib/text/qregularexpression.h @@ -91,11 +91,20 @@ public: MatchType matchType = NormalMatch, MatchOptions matchOptions = NoMatchOption) const; +#if QT_DEPRECATED_SINCE(6, 8) [[nodiscard]] + QT_DEPRECATED_VERSION_X_6_8("Use matchView instead.") QRegularExpressionMatch match(QStringView subjectView, qsizetype offset = 0, MatchType matchType = NormalMatch, MatchOptions matchOptions = NoMatchOption) const; +#endif + + [[nodiscard]] + QRegularExpressionMatch matchView(QStringView subjectView, + qsizetype offset = 0, + MatchType matchType = NormalMatch, + MatchOptions matchOptions = NoMatchOption) const; [[nodiscard]] QRegularExpressionMatchIterator globalMatch(const QString &subject, @@ -103,11 +112,20 @@ public: MatchType matchType = NormalMatch, MatchOptions matchOptions = NoMatchOption) const; +#if QT_DEPRECATED_SINCE(6, 8) [[nodiscard]] + QT_DEPRECATED_VERSION_X_6_8("Use globalMatchView instead.") QRegularExpressionMatchIterator globalMatch(QStringView subjectView, qsizetype offset = 0, MatchType matchType = NormalMatch, MatchOptions matchOptions = NoMatchOption) const; +#endif + + [[nodiscard]] + QRegularExpressionMatchIterator globalMatchView(QStringView subjectView, + qsizetype offset = 0, + MatchType matchType = NormalMatch, + MatchOptions matchOptions = NoMatchOption) const; void optimize() const; diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 5fbc3c6a48..f52f7317b9 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -7690,8 +7690,9 @@ QList<QStringView> QStringView::split(QChar sep, Qt::SplitBehavior behavior, Qt: #if QT_CONFIG(regularexpression) namespace { -template<class ResultList, typename String> +template<class ResultList, typename String, typename MatchingFunction> static ResultList splitString(const String &source, const QRegularExpression &re, + MatchingFunction matchingFunction, Qt::SplitBehavior behavior) { ResultList list; @@ -7702,7 +7703,7 @@ static ResultList splitString(const String &source, const QRegularExpression &re qsizetype start = 0; qsizetype end = 0; - QRegularExpressionMatchIterator iterator = re.globalMatch(source); + QRegularExpressionMatchIterator iterator = (re.*matchingFunction)(source, 0, QRegularExpression::NormalMatch, QRegularExpression::NoMatchOption); while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); end = match.capturedStart(); @@ -7747,7 +7748,15 @@ static ResultList splitString(const String &source, const QRegularExpression &re */ QStringList QString::split(const QRegularExpression &re, Qt::SplitBehavior behavior) const { - return splitString<QStringList>(*this, re, behavior); +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + const auto matchingFunction = qOverload<const QString &, qsizetype, QRegularExpression::MatchType, QRegularExpression::MatchOptions>(&QRegularExpression::globalMatch); +#else + const auto matchingFunction = &QRegularExpression::globalMatch; +#endif + return splitString<QStringList>(*this, + re, + matchingFunction, + behavior); } /*! @@ -7764,7 +7773,7 @@ QStringList QString::split(const QRegularExpression &re, Qt::SplitBehavior behav */ QList<QStringView> QStringView::split(const QRegularExpression &re, Qt::SplitBehavior behavior) const { - return splitString<QList<QStringView>>(*this, re, behavior); + return splitString<QList<QStringView>>(*this, re, &QRegularExpression::globalMatchView, behavior); } #endif // QT_CONFIG(regularexpression) @@ -10793,7 +10802,7 @@ qsizetype QtPrivate::indexOf(QStringView viewHaystack, const QString *stringHays QRegularExpressionMatch match = stringHaystack ? re.match(*stringHaystack, from) - : re.match(viewHaystack, from); + : re.matchView(viewHaystack, from); if (match.hasMatch()) { const qsizetype ret = match.capturedStart(); if (rmatch) @@ -10819,7 +10828,7 @@ qsizetype QtPrivate::lastIndexOf(QStringView viewHaystack, const QString *string qsizetype endpos = (from < 0) ? (viewHaystack.size() + from + 1) : (from + 1); QRegularExpressionMatchIterator iterator = stringHaystack ? re.globalMatch(*stringHaystack) - : re.globalMatch(viewHaystack); + : re.globalMatchView(viewHaystack); qsizetype lastIndex = -1; while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); @@ -10849,7 +10858,7 @@ bool QtPrivate::contains(QStringView viewHaystack, const QString *stringHaystack } QRegularExpressionMatch m = stringHaystack ? re.match(*stringHaystack) - : re.match(viewHaystack); + : re.matchView(viewHaystack); bool hasMatch = m.hasMatch(); if (hasMatch && rmatch) *rmatch = std::move(m); @@ -10871,7 +10880,7 @@ qsizetype QtPrivate::count(QStringView haystack, const QRegularExpression &re) qsizetype index = -1; qsizetype len = haystack.length(); while (index <= len - 1) { - QRegularExpressionMatch match = re.match(haystack, index + 1); + QRegularExpressionMatch match = re.matchView(haystack, index + 1); if (!match.hasMatch()) break; index = match.capturedStart(); diff --git a/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp index 37fa8147ed..7f3bef66e6 100644 --- a/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp @@ -393,6 +393,7 @@ static void testMatch(const QRegularExpression ®exp, result); } +// ### Qt 7: there should no longer be the need for these typedef QRegularExpressionMatch (QRegularExpression::*QREMatchStringPMF)(const QString &, qsizetype, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; typedef QRegularExpressionMatch (QRegularExpression::*QREMatchStringViewPMF)(QStringView, qsizetype, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; typedef QRegularExpressionMatchIterator (QRegularExpression::*QREGlobalMatchStringPMF)(const QString &, qsizetype, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; @@ -1096,7 +1097,7 @@ void tst_QRegularExpression::normalMatch() testMatch<QRegularExpressionMatch>(regexp, static_cast<QREMatchStringPMF>(&QRegularExpression::match), - static_cast<QREMatchStringViewPMF>(&QRegularExpression::match), + static_cast<QREMatchStringViewPMF>(&QRegularExpression::matchView), subject, offset, QRegularExpression::NormalMatch, @@ -1368,7 +1369,7 @@ void tst_QRegularExpression::partialMatch() testMatch<QRegularExpressionMatch>(regexp, static_cast<QREMatchStringPMF>(&QRegularExpression::match), - static_cast<QREMatchStringViewPMF>(&QRegularExpression::match), + static_cast<QREMatchStringViewPMF>(&QRegularExpression::matchView), subject, offset, matchType, @@ -1645,7 +1646,7 @@ void tst_QRegularExpression::globalMatch() testMatch<QRegularExpressionMatchIterator>(regexp, static_cast<QREGlobalMatchStringPMF>(&QRegularExpression::globalMatch), - static_cast<QREGlobalMatchStringViewPMF>(&QRegularExpression::globalMatch), + static_cast<QREGlobalMatchStringViewPMF>(&QRegularExpression::globalMatchView), subject, offset, matchType, @@ -1985,7 +1986,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QCOMPARE(match.capturedEnd(), 4); } { - const QRegularExpressionMatch match = re.match(QStringView(subject)); + const QRegularExpressionMatch match = re.matchView(QStringView(subject)); consistencyCheck(match); QVERIFY(match.isValid()); QVERIFY(match.hasMatch()); @@ -2003,7 +2004,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QCOMPARE(match.capturedEnd(), 4); } { - const QRegularExpressionMatch match = re.match(QStringView(subject), 1); + const QRegularExpressionMatch match = re.matchView(QStringView(subject), 1); consistencyCheck(match); QVERIFY(match.isValid()); QVERIFY(match.hasMatch()); @@ -2021,7 +2022,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QCOMPARE(match.capturedEnd(), 6); } { - const QRegularExpressionMatch match = re.match(QStringView(subject).mid(1)); + const QRegularExpressionMatch match = re.matchView(QStringView(subject).mid(1)); consistencyCheck(match); QVERIFY(match.isValid()); QVERIFY(match.hasMatch()); @@ -2039,7 +2040,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QCOMPARE(match.capturedEnd(), 6); } { - const QRegularExpressionMatch match = re.match(QStringView(subject).mid(1), 1); + const QRegularExpressionMatch match = re.matchView(QStringView(subject).mid(1), 1); consistencyCheck(match); QVERIFY(match.isValid()); QVERIFY(match.hasMatch()); @@ -2057,7 +2058,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QCOMPARE(match.capturedEnd(), 7); } { - const QRegularExpressionMatch match = re.match(QStringView(subject), 4); + const QRegularExpressionMatch match = re.matchView(QStringView(subject), 4); consistencyCheck(match); QVERIFY(match.isValid()); QVERIFY(match.hasMatch()); @@ -2072,7 +2073,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!match.hasMatch()); } { - const QRegularExpressionMatch match = re.match(QStringView(subject).mid(4)); + const QRegularExpressionMatch match = re.matchView(QStringView(subject).mid(4)); consistencyCheck(match); QVERIFY(match.isValid()); QVERIFY(!match.hasMatch()); @@ -2105,7 +2106,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject)); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject)); QVERIFY(i.isValid()); consistencyCheck(i); @@ -2157,7 +2158,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject), 1); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject), 1); QVERIFY(i.isValid()); consistencyCheck(i); @@ -2199,7 +2200,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject).mid(1)); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject).mid(1)); QVERIFY(i.isValid()); consistencyCheck(i); @@ -2231,7 +2232,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject).mid(1), 1); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject).mid(1), 1); QVERIFY(i.isValid()); consistencyCheck(i); @@ -2263,7 +2264,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject).mid(1), 1); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject).mid(1), 1); QVERIFY(i.isValid()); consistencyCheck(i); @@ -2296,7 +2297,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject), 4); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject), 4); QVERIFY(i.isValid()); consistencyCheck(i); @@ -2318,7 +2319,7 @@ void tst_QRegularExpression::QStringAndQStringViewEquivalence() QVERIFY(!i.hasNext()); } { - QRegularExpressionMatchIterator i = re.globalMatch(QStringView(subject).mid(4)); + QRegularExpressionMatchIterator i = re.globalMatchView(QStringView(subject).mid(4)); consistencyCheck(i); QVERIFY(i.isValid()); QVERIFY(!i.hasNext()); |