summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-07-05 19:01:08 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-07-29 23:04:27 +0200
commite540d4a8647c41a3e710a555f5dcc44edb7dfcb4 (patch)
tree25c6441166d1647b95e8983ac48a2204e3390fe4
parent8d6b274fa4c65e87443c0fbf8425229230385405 (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.cpp62
-rw-r--r--src/corelib/text/qregularexpression.h18
-rw-r--r--src/corelib/text/qstring.cpp25
-rw-r--r--tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp33
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 &regexp,
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());