Port QRegularExpression to QStringView, drop QStringRef

The idea is pretty simple -- add QRegularExpression matching over
QStringView. When matching over a QString, keep the string
alive (by taking a copy), and set the view onto that string.
Otherwise, just use the view provided by the user (who is then
responsible for ensuring the data stays valid while matching).

Do just minor refactorings to support this use case in a cleaner
fashion.

In QRegularExpressionMatch drop the QStringRef-returning methods, as
they cannot work any more -- in the general case there won't be a
QString to build a QStringRef from.

[ChangeLog][QtCore][QRegularExpression] All the APIs dealing
with QStringRef have been ported to QStringView, following
QStringRef deprecation in Qt 6.0.

Change-Id: Ic367991d9583cc108c045e4387c9b7288c8f1ffd
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Giuseppe D'Angelo 2020-05-31 18:04:04 +02:00
parent 32a39c4ed1
commit 529f052add
6 changed files with 120 additions and 191 deletions

View File

@ -162,7 +162,7 @@ void MainWindow::findCodecs()
} else if (sortKey.startsWith(QLatin1String("UTF-16"))) { } else if (sortKey.startsWith(QLatin1String("UTF-16"))) {
rank = 2; rank = 2;
} else if ((match = iso8859RegExp.match(sortKey)).hasMatch()) { } else if ((match = iso8859RegExp.match(sortKey)).hasMatch()) {
if (match.capturedRef(1).size() == 1) if (match.capturedView(1).size() == 1)
rank = 3; rank = 3;
else else
rank = 4; rank = 4;

View File

@ -1210,7 +1210,7 @@ void QMessagePattern::setPattern(const QString &pattern)
static const QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))")); static const QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))"));
QRegularExpressionMatch m = depthRx.match(lexeme); QRegularExpressionMatch m = depthRx.match(lexeme);
if (m.hasMatch()) { if (m.hasMatch()) {
int depth = m.capturedRef(1).toInt(); int depth = m.capturedView(1).toInt();
if (depth <= 0) if (depth <= 0)
error += QLatin1String("QT_MESSAGE_PATTERN: %{backtrace} depth must be a number greater than 0\n"); error += QLatin1String("QT_MESSAGE_PATTERN: %{backtrace} depth must be a number greater than 0\n");
else else

View File

@ -737,14 +737,10 @@ struct QRegularExpressionPrivate : QSharedData
DontCheckSubjectString DontCheckSubjectString
}; };
QRegularExpressionMatchPrivate *doMatch(const QString &subject, void doMatch(QRegularExpressionMatchPrivate *priv,
int subjectStartPos, int offset,
int subjectLength, CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
int offset, const QRegularExpressionMatchPrivate *previous = nullptr) const;
QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions,
CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
const QRegularExpressionMatchPrivate *previous = nullptr) const;
int captureIndexForName(QStringView name) const; int captureIndexForName(QStringView name) const;
@ -771,31 +767,33 @@ struct QRegularExpressionPrivate : QSharedData
struct QRegularExpressionMatchPrivate : QSharedData struct QRegularExpressionMatchPrivate : QSharedData
{ {
QRegularExpressionMatchPrivate(const QRegularExpression &re, QRegularExpressionMatchPrivate(const QRegularExpression &re,
const QString &subject, const QString &subjectStorage,
int subjectStart, QStringView subject,
int subjectLength,
QRegularExpression::MatchType matchType, QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions); QRegularExpression::MatchOptions matchOptions);
QRegularExpressionMatch nextMatch() const; QRegularExpressionMatch nextMatch() const;
const QRegularExpression regularExpression; const QRegularExpression regularExpression;
const QString subject;
// the capturedOffsets vector contains pairs of (start, end) positions
// for each captured substring
QVector<int> capturedOffsets;
const int subjectStart; // subject is what we match upon. If we've been asked to match over
const int subjectLength; // a QString, then subjectStorage is a copy of that string
// (so that it's kept alive by us)
const QString subjectStorage;
const QStringView subject;
const QRegularExpression::MatchType matchType; const QRegularExpression::MatchType matchType;
const QRegularExpression::MatchOptions matchOptions; const QRegularExpression::MatchOptions matchOptions;
int capturedCount; // the capturedOffsets vector contains pairs of (start, end) positions
// for each captured substring
QVector<int> capturedOffsets;
bool hasMatch; int capturedCount = 0;
bool hasPartialMatch;
bool isValid; bool hasMatch = false;
bool hasPartialMatch = false;
bool isValid = false;
}; };
struct QRegularExpressionMatchIteratorPrivate : QSharedData struct QRegularExpressionMatchIteratorPrivate : QSharedData
@ -1057,7 +1055,7 @@ int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
and re-run pcre2_match_16. and re-run pcre2_match_16.
*/ */
static int safe_pcre2_match_16(const pcre2_code_16 *code, static int safe_pcre2_match_16(const pcre2_code_16 *code,
const unsigned short *subject, int length, PCRE2_SPTR16 subject, int length,
int startOffset, int options, int startOffset, int options,
pcre2_match_data_16 *matchData, pcre2_match_data_16 *matchData,
pcre2_match_context_16 *matchContext) pcre2_match_context_16 *matchContext)
@ -1079,20 +1077,19 @@ static int safe_pcre2_match_16(const pcre2_code_16 *code,
/*! /*!
\internal \internal
Performs a match on the substring of the given \a subject string, Performs a match on the subject string view held by \a priv. The
substring which starts from \a subjectStart and up to match will be of type priv->matchType and using the options
(but not including) \a subjectStart + \a subjectLength. The match priv->matchOptions; the matching \a offset is relative the
will be of type \a matchType and using the options \a matchOptions; substring, and if negative, it's taken as an offset from the end of
the matching \a offset is relative the substring, the substring.
and if negative, it's taken as an offset from the end of the substring.
It also advances a match if a previous result is given as \a It also advances a match if a previous result is given as \a
previous. The \a subject string goes a Unicode validity check if previous. The subject string goes a Unicode validity check if
\a checkSubjectString is CheckSubjectString and the match options don't \a checkSubjectString is CheckSubjectString and the match options don't
include DontCheckSubjectStringMatchOption (PCRE doesn't like illegal include DontCheckSubjectStringMatchOption (PCRE doesn't like illegal
UTF-16 sequences). UTF-16 sequences).
Returns the QRegularExpressionMatchPrivate of the result. \a priv is modified to hold the results of the match.
Advancing a match is a tricky algorithm. If the previous match matched a Advancing a match is a tricky algorithm. If the previous match matched a
non-empty string, we just do an ordinary match at the offset position. non-empty string, we just do an ordinary match at the offset position.
@ -1105,43 +1102,38 @@ static int safe_pcre2_match_16(const pcre2_code_16 *code,
the new advanced offset is pointing to the beginning of a CRLF sequence, we the new advanced offset is pointing to the beginning of a CRLF sequence, we
must advance over it. must advance over it.
*/ */
QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString &subject, void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
int subjectStart, int offset,
int subjectLength, CheckSubjectStringOption checkSubjectStringOption,
int offset, const QRegularExpressionMatchPrivate *previous) const
QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions,
CheckSubjectStringOption checkSubjectStringOption,
const QRegularExpressionMatchPrivate *previous) const
{ {
Q_ASSERT(priv);
Q_ASSUME(priv != previous);
const int subjectLength = priv->subject.length();
if (offset < 0) if (offset < 0)
offset += subjectLength; offset += subjectLength;
QRegularExpression re(*const_cast<QRegularExpressionPrivate *>(this));
QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject,
subjectStart, subjectLength,
matchType, matchOptions);
if (offset < 0 || offset > subjectLength) if (offset < 0 || offset > subjectLength)
return priv; return;
if (Q_UNLIKELY(!compiledPattern)) { if (Q_UNLIKELY(!compiledPattern)) {
qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object"); qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
return priv; return;
} }
// skip doing the actual matching if NoMatch type was requested // skip doing the actual matching if NoMatch type was requested
if (matchType == QRegularExpression::NoMatch) { if (priv->matchType == QRegularExpression::NoMatch) {
priv->isValid = true; priv->isValid = true;
return priv; return;
} }
int pcreOptions = convertToPcreOptions(matchOptions); int pcreOptions = convertToPcreOptions(priv->matchOptions);
if (matchType == QRegularExpression::PartialPreferCompleteMatch) if (priv->matchType == QRegularExpression::PartialPreferCompleteMatch)
pcreOptions |= PCRE2_PARTIAL_SOFT; pcreOptions |= PCRE2_PARTIAL_SOFT;
else if (matchType == QRegularExpression::PartialPreferFirstMatch) else if (priv->matchType == QRegularExpression::PartialPreferFirstMatch)
pcreOptions |= PCRE2_PARTIAL_HARD; pcreOptions |= PCRE2_PARTIAL_HARD;
if (checkSubjectStringOption == DontCheckSubjectString) if (checkSubjectStringOption == DontCheckSubjectString)
@ -1157,7 +1149,7 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
pcre2_jit_stack_assign_16(matchContext, &qtPcreCallback, nullptr); pcre2_jit_stack_assign_16(matchContext, &qtPcreCallback, nullptr);
pcre2_match_data_16 *matchData = pcre2_match_data_create_from_pattern_16(compiledPattern, nullptr); pcre2_match_data_16 *matchData = pcre2_match_data_create_from_pattern_16(compiledPattern, nullptr);
const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart; const char16_t * const subjectUtf16 = priv->subject.utf16();
int result; int result;
@ -1194,9 +1186,8 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
#ifdef QREGULAREXPRESSION_DEBUG #ifdef QREGULAREXPRESSION_DEBUG
qDebug() << "Matching" << pattern << "against" << subject qDebug() << "Matching" << pattern << "against" << subject
<< "starting at" << subjectStart << "len" << subjectLength
<< "offset" << offset << "offset" << offset
<< matchType << matchOptions << previousMatchWasEmpty << priv->matchType << priv->matchOptions << previousMatchWasEmpty
<< "result" << result; << "result" << result;
#endif #endif
@ -1254,28 +1245,24 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
pcre2_match_data_free_16(matchData); pcre2_match_data_free_16(matchData);
pcre2_match_context_free_16(matchContext); pcre2_match_context_free_16(matchContext);
return priv;
} }
/*! /*!
\internal \internal
*/ */
QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(const QRegularExpression &re, QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(const QRegularExpression &re,
const QString &subject, const QString &subjectStorage,
int subjectStart, QStringView subject,
int subjectLength,
QRegularExpression::MatchType matchType, QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions) QRegularExpression::MatchOptions matchOptions)
: regularExpression(re), subject(subject), : regularExpression(re),
subjectStart(subjectStart), subjectLength(subjectLength), subjectStorage(subjectStorage),
matchType(matchType), matchOptions(matchOptions), subject(subject),
capturedCount(0), matchType(matchType),
hasMatch(false), hasPartialMatch(false), isValid(false) matchOptions(matchOptions)
{ {
} }
/*! /*!
\internal \internal
*/ */
@ -1284,18 +1271,20 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
Q_ASSERT(isValid); Q_ASSERT(isValid);
Q_ASSERT(hasMatch || hasPartialMatch); Q_ASSERT(hasMatch || hasPartialMatch);
auto nextPrivate = new QRegularExpressionMatchPrivate(regularExpression,
subjectStorage,
subject,
matchType,
matchOptions);
// Note the DontCheckSubjectString passed for the check of the subject string: // Note the DontCheckSubjectString passed for the check of the subject string:
// if we're advancing a match on the same subject, // if we're advancing a match on the same subject,
// then that subject was already checked at least once (when this object // then that subject was already checked at least once (when this object
// was created, or when the object that created this one was created, etc.) // was created, or when the object that created this one was created, etc.)
QRegularExpressionMatchPrivate *nextPrivate = regularExpression.d->doMatch(subject, regularExpression.d->doMatch(nextPrivate,
subjectStart, capturedOffsets.at(1),
subjectLength, QRegularExpressionPrivate::DontCheckSubjectString,
capturedOffsets.at(1), this);
matchType,
matchOptions,
QRegularExpressionPrivate::DontCheckSubjectString,
this);
return QRegularExpressionMatch(*nextPrivate); return QRegularExpressionMatch(*nextPrivate);
} }
@ -1577,34 +1566,43 @@ QRegularExpressionMatch QRegularExpression::match(const QString &subject,
MatchOptions matchOptions) const MatchOptions matchOptions) const
{ {
d.data()->compilePattern(); d.data()->compilePattern();
auto priv = new QRegularExpressionMatchPrivate(*this,
QRegularExpressionMatchPrivate *priv = d->doMatch(subject, 0, subject.length(), offset, matchType, matchOptions); subject,
qToStringViewIgnoringNull(subject),
matchType,
matchOptions);
d->doMatch(priv, offset);
return QRegularExpressionMatch(*priv); return QRegularExpressionMatch(*priv);
} }
/*! /*!
\since 5.5 \since 6.0
\overload \overload
Attempts to match the regular expression against the given \a subjectRef Attempts to match the regular expression against the given \a subjectView
string reference, starting at the position \a offset inside the subject, using a string view, starting at the position \a offset inside the subject, using a
match of type \a matchType and honoring the given \a matchOptions. match of type \a matchType and honoring the given \a matchOptions.
The returned QRegularExpressionMatch object contains the results of the The returned QRegularExpressionMatch object contains the results of the
match. match.
\note The data referenced by \a subjectView must remain valid as long
as there are QRegularExpressionMatch objects using it.
\sa QRegularExpressionMatch, {normal matching} \sa QRegularExpressionMatch, {normal matching}
*/ */
QRegularExpressionMatch QRegularExpression::match(const QStringRef &subjectRef, QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
int offset, int offset,
MatchType matchType, MatchType matchType,
MatchOptions matchOptions) const MatchOptions matchOptions) const
{ {
d.data()->compilePattern(); d.data()->compilePattern();
auto priv = new QRegularExpressionMatchPrivate(*this,
const QString subject = subjectRef.string() ? *subjectRef.string() : QString(); QString(),
subjectView,
QRegularExpressionMatchPrivate *priv = d->doMatch(subject, subjectRef.position(), subjectRef.length(), offset, matchType, matchOptions); matchType,
matchOptions);
d->doMatch(priv, offset);
return QRegularExpressionMatch(*priv); return QRegularExpressionMatch(*priv);
} }
@ -1634,20 +1632,24 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
} }
/*! /*!
\since 5.5 \since 6.0
\overload \overload
Attempts to perform a global match of the regular expression against the Attempts to perform a global match of the regular expression against the
given \a subjectRef string reference, starting at the position \a offset inside the given \a subjectView string view, starting at the position \a offset inside the
subject, using a match of type \a matchType and honoring the given \a subject, using a match of type \a matchType and honoring the given \a
matchOptions. matchOptions.
The returned QRegularExpressionMatchIterator is positioned before the The returned QRegularExpressionMatchIterator is positioned before the
first match result (if any). first match result (if any).
\note The data referenced by \a subjectView must remain valid as
long as there are QRegularExpressionMatchIterator or
QRegularExpressionMatch objects using it.
\sa QRegularExpressionMatchIterator, {global matching} \sa QRegularExpressionMatchIterator, {global matching}
*/ */
QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QStringRef &subjectRef, QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView,
int offset, int offset,
MatchType matchType, MatchType matchType,
MatchOptions matchOptions) const MatchOptions matchOptions) const
@ -1656,7 +1658,7 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QStringRef
new QRegularExpressionMatchIteratorPrivate(*this, new QRegularExpressionMatchIteratorPrivate(*this,
matchType, matchType,
matchOptions, matchOptions,
match(subjectRef, offset, matchType, matchOptions)); match(subjectView, offset, matchType, matchOptions));
return QRegularExpressionMatchIterator(*priv); return QRegularExpressionMatchIterator(*priv);
} }
@ -1987,8 +1989,7 @@ QString QRegularExpression::anchoredPattern(QStringView expression)
QRegularExpressionMatch::QRegularExpressionMatch() QRegularExpressionMatch::QRegularExpressionMatch()
: d(new QRegularExpressionMatchPrivate(QRegularExpression(), : d(new QRegularExpressionMatchPrivate(QRegularExpression(),
QString(), QString(),
0, QStringView(),
0,
QRegularExpression::NoMatch, QRegularExpression::NoMatch,
QRegularExpression::NoMatchOption)) QRegularExpression::NoMatchOption))
{ {
@ -2108,45 +2109,12 @@ int QRegularExpressionMatch::lastCapturedIndex() const
\note The implicit capturing group number 0 captures the substring matched \note The implicit capturing group number 0 captures the substring matched
by the entire pattern. by the entire pattern.
\sa capturedRef(), capturedView(), lastCapturedIndex(), capturedStart(), capturedEnd(), \sa capturedView(), lastCapturedIndex(), capturedStart(), capturedEnd(),
capturedLength(), QString::isNull() capturedLength(), QString::isNull()
*/ */
QString QRegularExpressionMatch::captured(int nth) const QString QRegularExpressionMatch::captured(int nth) const
{ {
if (nth < 0 || nth > lastCapturedIndex()) return capturedView(nth).toString();
return QString();
int start = capturedStart(nth);
if (start == -1) // didn't capture
return QString();
return d->subject.mid(start + d->subjectStart, capturedLength(nth));
}
/*!
Returns a reference to the substring captured by the \a nth capturing group.
If the \a nth capturing group did not capture a string, or if there is no
such capturing group, returns a null QStringRef.
\note The implicit capturing group number 0 captures the substring matched
by the entire pattern.
\sa captured(), capturedView(), lastCapturedIndex(), capturedStart(), capturedEnd(),
capturedLength(), QStringRef::isNull()
*/
QStringRef QRegularExpressionMatch::capturedRef(int nth) const
{
if (nth < 0 || nth > lastCapturedIndex())
return QStringRef();
int start = capturedStart(nth);
if (start == -1) // didn't capture
return QStringRef();
return d->subject.midRef(start + d->subjectStart, capturedLength(nth));
} }
/*! /*!
@ -2160,12 +2128,20 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const
\note The implicit capturing group number 0 captures the substring matched \note The implicit capturing group number 0 captures the substring matched
by the entire pattern. by the entire pattern.
\sa captured(), capturedRef(), lastCapturedIndex(), capturedStart(), capturedEnd(), \sa captured(), lastCapturedIndex(), capturedStart(), capturedEnd(),
capturedLength(), QStringView::isNull() capturedLength(), QStringView::isNull()
*/ */
QStringView QRegularExpressionMatch::capturedView(int nth) const QStringView QRegularExpressionMatch::capturedView(int nth) const
{ {
return capturedRef(nth); if (nth < 0 || nth > lastCapturedIndex())
return QStringView();
int start = capturedStart(nth);
if (start == -1) // didn't capture
return QStringView();
return d->subject.mid(start, capturedLength(nth));
} }
#if QT_STRINGVIEW_LEVEL < 2 #if QT_STRINGVIEW_LEVEL < 2
@ -2175,28 +2151,13 @@ QStringView QRegularExpressionMatch::capturedView(int nth) const
If the named capturing group \a name did not capture a string, or if If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QString. there is no capturing group named \a name, returns a null QString.
\sa capturedRef(), capturedView(), capturedStart(), capturedEnd(), capturedLength(), \sa capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QString::isNull() QString::isNull()
*/ */
QString QRegularExpressionMatch::captured(const QString &name) const QString QRegularExpressionMatch::captured(const QString &name) const
{ {
return captured(qToStringViewIgnoringNull(name)); return captured(qToStringViewIgnoringNull(name));
} }
/*!
Returns a reference to the string captured by the capturing group named \a
name.
If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QStringRef.
\sa captured(), capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QStringRef::isNull()
*/
QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const
{
return capturedRef(qToStringViewIgnoringNull(name));
}
#endif // QT_STRINGVIEW_LEVEL < 2 #endif // QT_STRINGVIEW_LEVEL < 2
/*! /*!
@ -2207,7 +2168,7 @@ QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const
If the named capturing group \a name did not capture a string, or if If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QString. there is no capturing group named \a name, returns a null QString.
\sa capturedRef(), capturedView(), capturedStart(), capturedEnd(), capturedLength(), \sa capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QString::isNull() QString::isNull()
*/ */
QString QRegularExpressionMatch::captured(QStringView name) const QString QRegularExpressionMatch::captured(QStringView name) const
@ -2216,34 +2177,8 @@ QString QRegularExpressionMatch::captured(QStringView name) const
qWarning("QRegularExpressionMatch::captured: empty capturing group name passed"); qWarning("QRegularExpressionMatch::captured: empty capturing group name passed");
return QString(); return QString();
} }
int nth = d->regularExpression.d->captureIndexForName(name);
if (nth == -1)
return QString();
return captured(nth);
}
/*! return capturedView(name).toString();
\since 5.10
Returns a reference to the string captured by the capturing group named \a
name.
If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QStringRef.
\sa captured(), capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QStringRef::isNull()
*/
QStringRef QRegularExpressionMatch::capturedRef(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedRef: empty capturing group name passed");
return QStringRef();
}
int nth = d->regularExpression.d->captureIndexForName(name);
if (nth == -1)
return QStringRef();
return capturedRef(nth);
} }
/*! /*!
@ -2255,7 +2190,7 @@ QStringRef QRegularExpressionMatch::capturedRef(QStringView name) const
If the named capturing group \a name did not capture a string, or if If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QStringView. there is no capturing group named \a name, returns a null QStringView.
\sa captured(), capturedRef(), capturedStart(), capturedEnd(), capturedLength(), \sa captured(), capturedStart(), capturedEnd(), capturedLength(),
QStringRef::isNull() QStringRef::isNull()
*/ */
QStringView QRegularExpressionMatch::capturedView(QStringView name) const QStringView QRegularExpressionMatch::capturedView(QStringView name) const

View File

@ -121,7 +121,7 @@ public:
MatchType matchType = NormalMatch, MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const; MatchOptions matchOptions = NoMatchOption) const;
QRegularExpressionMatch match(const QStringRef &subjectRef, QRegularExpressionMatch match(QStringView subjectView,
int offset = 0, int offset = 0,
MatchType matchType = NormalMatch, MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const; MatchOptions matchOptions = NoMatchOption) const;
@ -131,7 +131,7 @@ public:
MatchType matchType = NormalMatch, MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const; MatchOptions matchOptions = NoMatchOption) const;
QRegularExpressionMatchIterator globalMatch(const QStringRef &subjectRef, QRegularExpressionMatchIterator globalMatch(QStringView subjectView,
int offset = 0, int offset = 0,
MatchType matchType = NormalMatch, MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const; MatchOptions matchOptions = NoMatchOption) const;
@ -221,16 +221,13 @@ public:
int lastCapturedIndex() const; int lastCapturedIndex() const;
QString captured(int nth = 0) const; QString captured(int nth = 0) const;
QStringRef capturedRef(int nth = 0) const;
QStringView capturedView(int nth = 0) const; QStringView capturedView(int nth = 0) const;
#if QT_STRINGVIEW_LEVEL < 2 #if QT_STRINGVIEW_LEVEL < 2
QString captured(const QString &name) const; QString captured(const QString &name) const;
QStringRef capturedRef(const QString &name) const;
#endif #endif
QString captured(QStringView name) const; QString captured(QStringView name) const;
QStringRef capturedRef(QStringView name) const;
QStringView capturedView(QStringView name) const; QStringView capturedView(QStringView name) const;
QStringList capturedTexts() const; QStringList capturedTexts() const;

View File

@ -1066,14 +1066,14 @@ static QPSQLDriver::Protocol qFindPSQLVersion(const QString &versionString)
// increasing the first part of the version, e.g. 10 to 11. // increasing the first part of the version, e.g. 10 to 11.
// Before version 10, a major release was indicated by increasing either // Before version 10, a major release was indicated by increasing either
// the first or second part of the version number, e.g. 9.5 to 9.6. // the first or second part of the version number, e.g. 9.5 to 9.6.
int vMaj = match.capturedRef(1).toInt(); int vMaj = match.capturedView(1).toInt();
int vMin; int vMin;
if (vMaj >= 10) { if (vMaj >= 10) {
vMin = 0; vMin = 0;
} else { } else {
if (match.capturedRef(2).isEmpty()) if (match.capturedView(2).isEmpty())
return QPSQLDriver::VersionUnknown; return QPSQLDriver::VersionUnknown;
vMin = match.capturedRef(2).toInt(); vMin = match.capturedView(2).toInt();
} }
return qMakePSQLVersion(vMaj, vMin); return qMakePSQLVersion(vMaj, vMin);
} }

View File

@ -217,7 +217,6 @@ void consistencyCheck(const QRegularExpressionMatch &match)
int endPos = match.capturedEnd(i); int endPos = match.capturedEnd(i);
int length = match.capturedLength(i); int length = match.capturedLength(i);
QString captured = match.captured(i); QString captured = match.captured(i);
QStringRef capturedRef = match.capturedRef(i);
QStringView capturedView = match.capturedView(i); QStringView capturedView = match.capturedView(i);
if (!captured.isNull()) { if (!captured.isNull()) {
@ -226,13 +225,11 @@ void consistencyCheck(const QRegularExpressionMatch &match)
QVERIFY(length >= 0); QVERIFY(length >= 0);
QVERIFY(endPos >= startPos); QVERIFY(endPos >= startPos);
QVERIFY((endPos - startPos) == length); QVERIFY((endPos - startPos) == length);
QVERIFY(captured == capturedRef);
QVERIFY(captured == capturedView); QVERIFY(captured == capturedView);
} else { } else {
QVERIFY(startPos == -1); QVERIFY(startPos == -1);
QVERIFY(endPos == -1); QVERIFY(endPos == -1);
QVERIFY((endPos - startPos) == length); QVERIFY((endPos - startPos) == length);
QVERIFY(capturedRef.isNull());
QVERIFY(capturedView.isNull()); QVERIFY(capturedView.isNull());
} }
} }
@ -344,10 +341,10 @@ static void testMatch(const QRegularExpression &regexp,
// test with QString as subject type // test with QString as subject type
testMatchImpl<QREMatch>(regexp, matchingMethodForString, subject, offset, matchType, matchOptions, result); testMatchImpl<QREMatch>(regexp, matchingMethodForString, subject, offset, matchType, matchOptions, result);
// test with QStringRef as subject type // test with QStringView as subject type
testMatchImpl<QREMatch>(regexp, testMatchImpl<QREMatch>(regexp,
matchingMethodForStringRef, matchingMethodForStringRef,
QStringRef(&subject, 0, subject.length()), QStringView(subject),
offset, offset,
matchType, matchType,
matchOptions, matchOptions,
@ -355,9 +352,9 @@ static void testMatch(const QRegularExpression &regexp,
} }
typedef QRegularExpressionMatch (QRegularExpression::*QREMatchStringPMF)(const QString &, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; typedef QRegularExpressionMatch (QRegularExpression::*QREMatchStringPMF)(const QString &, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const;
typedef QRegularExpressionMatch (QRegularExpression::*QREMatchStringRefPMF)(const QStringRef &, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; typedef QRegularExpressionMatch (QRegularExpression::*QREMatchStringViewPMF)(QStringView, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const;
typedef QRegularExpressionMatchIterator (QRegularExpression::*QREGlobalMatchStringPMF)(const QString &, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; typedef QRegularExpressionMatchIterator (QRegularExpression::*QREGlobalMatchStringPMF)(const QString &, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const;
typedef QRegularExpressionMatchIterator (QRegularExpression::*QREGlobalMatchStringRefPMF)(const QStringRef &, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const; typedef QRegularExpressionMatchIterator (QRegularExpression::*QREGlobalMatchStringViewPMF)(QStringView, int, QRegularExpression::MatchType, QRegularExpression::MatchOptions) const;
void tst_QRegularExpression::provideRegularExpressions() void tst_QRegularExpression::provideRegularExpressions()
{ {
@ -866,7 +863,7 @@ void tst_QRegularExpression::normalMatch()
testMatch<QRegularExpressionMatch>(regexp, testMatch<QRegularExpressionMatch>(regexp,
static_cast<QREMatchStringPMF>(&QRegularExpression::match), static_cast<QREMatchStringPMF>(&QRegularExpression::match),
static_cast<QREMatchStringRefPMF>(&QRegularExpression::match), static_cast<QREMatchStringViewPMF>(&QRegularExpression::match),
subject, subject,
offset, offset,
QRegularExpression::NormalMatch, QRegularExpression::NormalMatch,
@ -1138,7 +1135,7 @@ void tst_QRegularExpression::partialMatch()
testMatch<QRegularExpressionMatch>(regexp, testMatch<QRegularExpressionMatch>(regexp,
static_cast<QREMatchStringPMF>(&QRegularExpression::match), static_cast<QREMatchStringPMF>(&QRegularExpression::match),
static_cast<QREMatchStringRefPMF>(&QRegularExpression::match), static_cast<QREMatchStringViewPMF>(&QRegularExpression::match),
subject, subject,
offset, offset,
matchType, matchType,
@ -1415,7 +1412,7 @@ void tst_QRegularExpression::globalMatch()
testMatch<QRegularExpressionMatchIterator>(regexp, testMatch<QRegularExpressionMatchIterator>(regexp,
static_cast<QREGlobalMatchStringPMF>(&QRegularExpression::globalMatch), static_cast<QREGlobalMatchStringPMF>(&QRegularExpression::globalMatch),
static_cast<QREGlobalMatchStringRefPMF>(&QRegularExpression::globalMatch), static_cast<QREGlobalMatchStringViewPMF>(&QRegularExpression::globalMatch),
subject, subject,
offset, offset,
matchType, matchType,