summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qregularexpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qregularexpression.cpp')
-rw-r--r--src/corelib/text/qregularexpression.cpp671
1 files changed, 431 insertions, 240 deletions
diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp
index db0f6907bb..95fd0e3d9a 100644
--- a/src/corelib/text/qregularexpression.cpp
+++ b/src/corelib/text/qregularexpression.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qregularexpression.h"
@@ -47,17 +11,22 @@
#include <QtCore/qmutex.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qthreadstorage.h>
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qdatastream.h>
+#if defined(Q_OS_MACOS)
+#include <QtCore/private/qcore_mac_p.h>
+#endif
+
#define PCRE2_CODE_UNIT_WIDTH 16
#include <pcre2.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QRegularExpression
\inmodule QtCore
@@ -105,9 +74,9 @@ QT_BEGIN_NAMESPACE
\list
\li \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F.
Friedl, ISBN 0-596-52812-4;
- \li the \l{http://pcre.org/pcre.txt} {pcrepattern(3)} man page, describing
- the pattern syntax supported by PCRE (the reference implementation of
- Perl-compatible regular expressions);
+ \li the \l{https://pcre.org/original/doc/html/pcrepattern.html}
+ {pcrepattern(3)} man page, describing the pattern syntax supported by PCRE
+ (the reference implementation of Perl-compatible regular expressions);
\li the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression
documentation} and the \l{http://perldoc.perl.org/perlretut.html} {Perl's
regular expression tutorial}.
@@ -140,6 +109,14 @@ QT_BEGIN_NAMESPACE
\snippet code/src_corelib_text_qregularexpression.cpp 2
+ Alternatively, you can use a
+ \l {https://en.cppreference.com/w/cpp/language/string_literal} {raw string literal},
+ in which case you don't need to escape backslashes in the pattern, all characters
+ between \c {R"(...)"} are considered raw characters. As you can see in the following
+ example, this simplifies writing patterns:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 35
+
The pattern() function returns the pattern that is currently set for a
QRegularExpression object:
@@ -260,6 +237,12 @@ QT_BEGIN_NAMESPACE
You can also use \l{QRegularExpressionMatchIterator::}{peekNext()} to get
the next result without advancing the iterator.
+ It is also possible to simply use the result of
+ QRegularExpression::globalMatch in a range-based for loop, for instance
+ like this:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 34
+
It is possible to pass a starting offset and one or more match options to
the globalMatch() function, exactly like normal matching with match().
@@ -535,6 +518,12 @@ QT_BEGIN_NAMESPACE
Moreover, QRegularExpressionMatchIterator offers a peekNext() function
to get the next result \e{without} advancing the iterator.
+ Starting with Qt 6.0, it is also possible to simply use the result of
+ QRegularExpression::globalMatch in a range-based for loop, for instance
+ like this:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 34
+
You can retrieve the QRegularExpression object the subject string was
matched against by calling the regularExpression() function; the
match type and the match options are available as well by calling
@@ -608,16 +597,6 @@ QT_BEGIN_NAMESPACE
\c{\w} to match any character with either the Unicode L (letter) or N
(digit) property, plus underscore, and so on. This option corresponds
to the \c{/u} modifier in Perl regular expressions.
-
- \value OptimizeOnFirstUsageOption
- This option is ignored. A regular expression is automatically optimized
- (including JIT compiling) the first time it is used. This enum value
- was introduced in Qt 5.4.
-
- \value DontAutomaticallyOptimizeOption
- This option is ignored. A regular expression is automatically optimized
- (including JIT compiling) the first time it is used. This enum value
- was introduced in Qt 5.4.
*/
/*!
@@ -738,7 +717,7 @@ struct QRegularExpressionPrivate : QSharedData
};
void doMatch(QRegularExpressionMatchPrivate *priv,
- int offset,
+ qsizetype offset,
CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
const QRegularExpressionMatchPrivate *previous = nullptr) const;
@@ -758,7 +737,7 @@ struct QRegularExpressionPrivate : QSharedData
// it is set to nullptr
pcre2_code_16 *compiledPattern;
int errorCode;
- int errorOffset;
+ qsizetype errorOffset;
int capturingCount;
bool usingCrLfNewlines;
bool isDirty;
@@ -787,7 +766,7 @@ struct QRegularExpressionMatchPrivate : QSharedData
// the capturedOffsets vector contains pairs of (start, end) positions
// for each captured substring
- QList<int> capturedOffsets;
+ QList<qsizetype> capturedOffsets;
int capturedCount = 0;
@@ -812,6 +791,24 @@ struct QRegularExpressionMatchIteratorPrivate : QSharedData
/*!
\internal
+
+ Used to centralize the warning about using an invalid QRegularExpression.
+ In case the pattern is an illegal UTF-16 string, we can't pass print it
+ (pass it to qUtf16Printable, etc.), so we need to check for that.
+*/
+Q_DECL_COLD_FUNCTION
+void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *where)
+{
+ if (pattern.isValidUtf16()) {
+ qWarning("%s(): called on an invalid QRegularExpression object "
+ "(pattern is '%ls')", where, qUtf16Printable(pattern));
+ } else {
+ qWarning("%s(): called on an invalid QRegularExpression object", where);
+ }
+}
+
+/*!
+ \internal
*/
QRegularExpression::QRegularExpression(QRegularExpressionPrivate &dd)
: d(&dd)
@@ -896,15 +893,15 @@ void QRegularExpressionPrivate::compilePattern()
options |= PCRE2_UTF;
PCRE2_SIZE patternErrorOffset;
- compiledPattern = pcre2_compile_16(reinterpret_cast<PCRE2_SPTR16>(pattern.utf16()),
- pattern.length(),
+ compiledPattern = pcre2_compile_16(reinterpret_cast<PCRE2_SPTR16>(pattern.constData()),
+ pattern.size(),
options,
&errorCode,
&patternErrorOffset,
nullptr);
if (!compiledPattern) {
- errorOffset = static_cast<int>(patternErrorOffset);
+ errorOffset = qsizetype(patternErrorOffset);
return;
} else {
// ignore whatever PCRE2 wrote into errorCode -- leave it to 0 to mean "no error"
@@ -948,43 +945,24 @@ void QRegularExpressionPrivate::getPatternInfo()
Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with
QThreadStorage.
*/
-class QPcreJitStackPointer
+namespace {
+struct PcreJitStackFree
{
- Q_DISABLE_COPY(QPcreJitStackPointer)
-
-public:
- /*!
- \internal
- */
- QPcreJitStackPointer()
- {
- // The default JIT stack size in PCRE is 32K,
- // we allocate from 32K up to 512K.
- stack = pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, nullptr);
- }
- /*!
- \internal
- */
- ~QPcreJitStackPointer()
+ void operator()(pcre2_jit_stack_16 *stack)
{
if (stack)
pcre2_jit_stack_free_16(stack);
}
-
- pcre2_jit_stack_16 *stack;
};
-
-Q_GLOBAL_STATIC(QThreadStorage<QPcreJitStackPointer *>, jitStacks)
+Q_CONSTINIT static thread_local std::unique_ptr<pcre2_jit_stack_16, PcreJitStackFree> jitStacks;
+}
/*!
\internal
*/
static pcre2_jit_stack_16 *qtPcreCallback(void *)
{
- if (jitStacks()->hasLocalData())
- return jitStacks()->localData()->stack;
-
- return nullptr;
+ return jitStacks.get();
}
/*!
@@ -1001,6 +979,8 @@ static bool isJitEnabled()
#ifdef QT_DEBUG
return false;
+#elif defined(Q_OS_MACOS)
+ return !qt_mac_runningUnderRosetta();
#else
return true;
#endif
@@ -1040,9 +1020,24 @@ int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
if (!compiledPattern)
return -1;
- int index = pcre2_substring_number_from_name_16(compiledPattern, reinterpret_cast<PCRE2_SPTR16>(name.utf16()));
- if (index >= 0)
- return index;
+ // See the other usages of pcre2_pattern_info_16 for more details about this
+ PCRE2_SPTR16 *namedCapturingTable;
+ unsigned int namedCapturingTableEntryCount;
+ unsigned int namedCapturingTableEntrySize;
+
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMETABLE, &namedCapturingTable);
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
+
+ for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
+ const auto currentNamedCapturingTableRow =
+ reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
+
+ if (name == (currentNamedCapturingTableRow + 1)) {
+ const int index = *currentNamedCapturingTableRow;
+ return index;
+ }
+ }
return -1;
}
@@ -1055,17 +1050,18 @@ int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
and re-run pcre2_match_16.
*/
static int safe_pcre2_match_16(const pcre2_code_16 *code,
- PCRE2_SPTR16 subject, int length,
- int startOffset, int options,
+ PCRE2_SPTR16 subject, qsizetype length,
+ qsizetype startOffset, int options,
pcre2_match_data_16 *matchData,
pcre2_match_context_16 *matchContext)
{
int result = pcre2_match_16(code, subject, length,
startOffset, options, matchData, matchContext);
- if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks()->hasLocalData()) {
- QPcreJitStackPointer *p = new QPcreJitStackPointer;
- jitStacks()->setLocalData(p);
+ if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks) {
+ // The default JIT stack size in PCRE is 32K,
+ // we allocate from 32K up to 512K.
+ jitStacks.reset(pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, NULL));
result = pcre2_match_16(code, subject, length,
startOffset, options, matchData, matchContext);
@@ -1103,14 +1099,14 @@ static int safe_pcre2_match_16(const pcre2_code_16 *code,
must advance over it.
*/
void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
- int offset,
+ qsizetype offset,
CheckSubjectStringOption checkSubjectStringOption,
const QRegularExpressionMatchPrivate *previous) const
{
Q_ASSERT(priv);
- Q_ASSUME(priv != previous);
+ Q_ASSERT(priv != previous);
- const int subjectLength = priv->subject.length();
+ const qsizetype subjectLength = priv->subject.size();
if (offset < 0)
offset += subjectLength;
@@ -1119,7 +1115,7 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
return;
if (Q_UNLIKELY(!compiledPattern)) {
- qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
+ qtWarnAboutInvalidRegularExpression(pattern, "QRegularExpressionPrivate::doMatch");
return;
}
@@ -1149,7 +1145,19 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
pcre2_jit_stack_assign_16(matchContext, &qtPcreCallback, nullptr);
pcre2_match_data_16 *matchData = pcre2_match_data_create_from_pattern_16(compiledPattern, nullptr);
- const char16_t * const subjectUtf16 = priv->subject.utf16();
+ // PCRE does not accept a null pointer as subject string, even if
+ // its length is zero. We however allow it in input: a QStringView
+ // subject may have data == nullptr. In this case, to keep PCRE
+ // happy, pass a pointer to a dummy character.
+ const char16_t dummySubject = 0;
+ const char16_t * const subjectUtf16 = [&]()
+ {
+ const auto subjectUtf16 = priv->subject.utf16();
+ if (subjectUtf16)
+ return subjectUtf16;
+ Q_ASSERT(subjectLength == 0);
+ return &dummySubject;
+ }();
int result;
@@ -1169,8 +1177,8 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
if (usingCrLfNewlines
&& offset < subjectLength
- && subjectUtf16[offset - 1] == QLatin1Char('\r')
- && subjectUtf16[offset] == QLatin1Char('\n')) {
+ && subjectUtf16[offset - 1] == u'\r'
+ && subjectUtf16[offset] == u'\n') {
++offset;
} else if (offset < subjectLength
&& QChar::isLowSurrogate(subjectUtf16[offset])) {
@@ -1220,10 +1228,16 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
// copy the captured substrings offsets, if any
if (priv->capturedCount) {
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(matchData);
- int * const capturedOffsets = priv->capturedOffsets.data();
+ qsizetype *const capturedOffsets = priv->capturedOffsets.data();
+
+ // We rely on the fact that capturing groups that did not
+ // capture anything have offset -1, but PCRE technically
+ // returns "PCRE2_UNSET". Test that out, better safe than
+ // sorry...
+ static_assert(qsizetype(PCRE2_UNSET) == qsizetype(-1), "Internal error: PCRE2 changed its API");
for (int i = 0; i < priv->capturedCount * 2; ++i)
- capturedOffsets[i] = static_cast<int>(ovector[i]);
+ capturedOffsets[i] = qsizetype(ovector[i]);
// For partial matches, PCRE2 and PCRE1 differ in behavior when lookbehinds
// are involved. PCRE2 reports the real begin of the match and the maximum
@@ -1340,10 +1354,21 @@ QRegularExpression::QRegularExpression(const QString &pattern, PatternOptions op
\sa operator=()
*/
-QRegularExpression::QRegularExpression(const QRegularExpression &re)
- : d(re.d)
-{
-}
+QRegularExpression::QRegularExpression(const QRegularExpression &re) noexcept = default;
+
+/*!
+ \fn QRegularExpression::QRegularExpression(QRegularExpression &&re)
+
+ \since 6.1
+
+ Constructs a QRegularExpression object by moving from \a re.
+
+ Note that a moved-from QRegularExpression can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
+
+ \sa operator=()
+*/
/*!
Destroys the QRegularExpression object.
@@ -1352,15 +1377,13 @@ QRegularExpression::~QRegularExpression()
{
}
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionPrivate)
+
/*!
Assigns the regular expression \a re to this object, and returns a reference
to the copy. Both the pattern and the pattern options are copied.
*/
-QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re)
-{
- d = re.d;
- return *this;
-}
+QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re) noexcept = default;
/*!
\fn void QRegularExpression::swap(QRegularExpression &other)
@@ -1387,6 +1410,8 @@ QString QRegularExpression::pattern() const
*/
void QRegularExpression::setPattern(const QString &pattern)
{
+ if (d->pattern == pattern)
+ return;
d.detach();
d->isDirty = true;
d->pattern = pattern;
@@ -1410,6 +1435,8 @@ QRegularExpression::PatternOptions QRegularExpression::patternOptions() const
*/
void QRegularExpression::setPatternOptions(PatternOptions options)
{
+ if (d->patternOptions == options)
+ return;
d.detach();
d->isDirty = true;
d->patternOptions = options;
@@ -1473,19 +1500,15 @@ QStringList QRegularExpression::namedCaptureGroups() const
pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
- QStringList result;
-
- // no QList::resize nor fill is available. The +1 is for the implicit group #0
- result.reserve(d->capturingCount + 1);
- for (int i = 0; i < d->capturingCount + 1; ++i)
- result.append(QString());
+ // The +1 is for the implicit group #0
+ QStringList result(d->capturingCount + 1);
for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
const auto currentNamedCapturingTableRow =
reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
const int index = *currentNamedCapturingTableRow;
- result[index] = QString::fromUtf16(currentNamedCapturingTableRow + 1);
+ result[index] = QStringView(currentNamedCapturingTableRow + 1).toString();
}
return result;
@@ -1517,10 +1540,10 @@ QString QRegularExpression::errorString() const
QString errorString;
int errorStringLength;
do {
- errorString.resize(errorString.length() + 64);
+ errorString.resize(errorString.size() + 64);
errorStringLength = pcre2_get_error_message_16(d->errorCode,
reinterpret_cast<ushort *>(errorString.data()),
- errorString.length());
+ errorString.size());
} while (errorStringLength < 0);
errorString.resize(errorStringLength);
@@ -1531,7 +1554,7 @@ QString QRegularExpression::errorString() const
#endif
}
#ifdef QT_NO_TRANSLATION
- return QLatin1String("no error");
+ return u"no error"_s;
#else
return QCoreApplication::translate("QRegularExpression", "no error");
#endif
@@ -1544,7 +1567,7 @@ QString QRegularExpression::errorString() const
\sa pattern(), isValid(), errorString()
*/
-int QRegularExpression::patternErrorOffset() const
+qsizetype QRegularExpression::patternErrorOffset() const
{
d.data()->compilePattern();
return d->errorOffset;
@@ -1561,23 +1584,40 @@ int QRegularExpression::patternErrorOffset() const
\sa QRegularExpressionMatch, {normal matching}
*/
QRegularExpressionMatch QRegularExpression::match(const QString &subject,
- int offset,
+ qsizetype offset,
MatchType matchType,
MatchOptions matchOptions) const
{
d.data()->compilePattern();
auto priv = new QRegularExpressionMatchPrivate(*this,
subject,
- qToStringViewIgnoringNull(subject),
+ QStringView(subject),
matchType,
matchOptions);
d->doMatch(priv, offset);
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
@@ -1591,10 +1631,10 @@ QRegularExpressionMatch QRegularExpression::match(const QString &subject,
\sa QRegularExpressionMatch, {normal matching}
*/
-QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
- int 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,
@@ -1618,7 +1658,7 @@ QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
\sa QRegularExpressionMatchIterator, {global matching}
*/
QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &subject,
- int offset,
+ qsizetype offset,
MatchType matchType,
MatchOptions matchOptions) const
{
@@ -1631,9 +1671,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
@@ -1649,16 +1706,16 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
\sa QRegularExpressionMatchIterator, {global matching}
*/
-QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView,
- int 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);
}
@@ -1692,8 +1749,12 @@ bool QRegularExpression::operator==(const QRegularExpression &re) const
/*!
\fn QRegularExpression & QRegularExpression::operator=(QRegularExpression && re)
- Move-assigns the regular expression \a re to this object, and returns a reference
- to the copy. Both the pattern and the pattern options are copied.
+ Move-assigns the regular expression \a re to this object, and returns a
+ reference to the result. Both the pattern and the pattern options are copied.
+
+ Note that a moved-from QRegularExpression can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
*/
/*!
@@ -1717,12 +1778,10 @@ size_t qHash(const QRegularExpression &key, size_t seed) noexcept
return qHashMulti(seed, key.d->pattern, key.d->patternOptions);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QString QRegularExpression::escape(const QString &str)
\overload
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.15
@@ -1747,26 +1806,25 @@ size_t qHash(const QRegularExpression &key, size_t seed) noexcept
QString QRegularExpression::escape(QStringView str)
{
QString result;
- const int count = str.size();
+ const qsizetype count = str.size();
result.reserve(count * 2);
// everything but [a-zA-Z0-9_] gets escaped,
// cf. perldoc -f quotemeta
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
const QChar current = str.at(i);
if (current == QChar::Null) {
// unlike Perl, a literal NUL must be escaped with
// "\\0" (backslash + 0) and not "\\\0" (backslash + NUL),
// because pcre16_compile uses a NUL-terminated string
- result.append(QLatin1Char('\\'));
- result.append(QLatin1Char('0'));
- } else if ( (current < QLatin1Char('a') || current > QLatin1Char('z')) &&
- (current < QLatin1Char('A') || current > QLatin1Char('Z')) &&
- (current < QLatin1Char('0') || current > QLatin1Char('9')) &&
- current != QLatin1Char('_') )
- {
- result.append(QLatin1Char('\\'));
+ result.append(u'\\');
+ result.append(u'0');
+ } else if ((current < u'a' || current > u'z') &&
+ (current < u'A' || current > u'Z') &&
+ (current < u'0' || current > u'9') &&
+ current != u'_') {
+ result.append(u'\\');
result.append(current);
if (current.isHighSurrogate() && i < (count - 1))
result.append(str.at(++i));
@@ -1779,13 +1837,11 @@ QString QRegularExpression::escape(QStringView str)
return result;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.12
- \fn QString QRegularExpression::wildcardToRegularExpression(const QString &pattern, WildcardConversionType type)
+ \fn QString QRegularExpression::wildcardToRegularExpression(const QString &pattern, WildcardConversionOptions options)
\overload
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 6.0
@@ -1800,22 +1856,30 @@ QString QRegularExpression::escape(QStringView str)
\value UnanchoredWildcardConversion
The conversion will not anchor the pattern. This allows for partial string matches of
wildcard expressions.
+
+ \value [since 6.6] NonPathWildcardConversion
+ The conversion will \e{not} interpret the pattern as filepath globbing.
+
+ \sa QRegularExpression::wildcardToRegularExpression
*/
/*!
\since 5.15
Returns a regular expression representation of the given glob \a pattern.
- The transformation is targeting file path globbing, which means in particular
- that path separators receive special treatment. This implies that it is not
- just a basic translation from "*" to ".*".
+
+ There are two transformations possible, one that targets file path
+ globbing, and another one which is more generic.
+
+ By default, the transformation is targeting file path globbing,
+ which means in particular that path separators receive special
+ treatment. This implies that it is not just a basic translation
+ from "*" to ".*" and similar.
\snippet code/src_corelib_text_qregularexpression.cpp 31
- By default, the returned regular expression is fully anchored. In other
- words, there is no need of calling anchoredPattern() again on the
- result. To get an a regular expression that is not anchored, pass
- UnanchoredWildcardConversion as the conversion \a option.
+ The more generic globbing transformation is available by passing
+ \c NonPathWildcardConversion in the conversion \a options.
This implementation follows closely the definition
of wildcard for glob patterns:
@@ -1824,10 +1888,12 @@ QString QRegularExpression::escape(QStringView str)
\li Any character represents itself apart from those mentioned
below. Thus \b{c} matches the character \e c.
\row \li \b{?}
- \li Matches any single character. It is the same as
- \b{.} in full regexps.
+ \li Matches any single character, except for a path separator
+ (in case file path globbing has been selected). It is the
+ same as b{.} in full regexps.
\row \li \b{*}
- \li Matches zero or more of any characters. It is the
+ \li Matches zero or more of any characters, except for path
+ separators (in case file path globbing has been selected). It is the
same as \b{.*} in full regexps.
\row \li \b{[abc]}
\li Matches one character given in the bracket.
@@ -1841,9 +1907,10 @@ QString QRegularExpression::escape(QStringView str)
bracket. It is the same as \b{[^a-c]} in full regexp.
\endtable
- \note The backslash (\\) character is \e not an escape char in this context.
- In order to match one of the special characters, place it in square brackets
- (for example, \c{[?]}).
+ \note For historical reasons, a backslash (\\) character is \e not
+ an escape char in this context. In order to match one of the
+ special characters, place it in square brackets (for example,
+ \c{[?]}).
More information about the implementation can be found in:
\list
@@ -1851,39 +1918,66 @@ QString QRegularExpression::escape(QStringView str)
\li \c {man 7 glob}
\endlist
+ By default, the returned regular expression is fully anchored. In other
+ words, there is no need of calling anchoredPattern() again on the
+ result. To get a regular expression that is not anchored, pass
+ UnanchoredWildcardConversion in the conversion \a options.
+
\sa escape()
*/
QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, WildcardConversionOptions options)
{
- const int wclen = pattern.length();
+ const qsizetype wclen = pattern.size();
QString rx;
rx.reserve(wclen + wclen / 16);
- int i = 0;
+ qsizetype i = 0;
const QChar *wc = pattern.data();
+ struct GlobSettings {
+ char16_t nativePathSeparator;
+ QStringView starEscape;
+ QStringView questionMarkEscape;
+ };
+
+ const GlobSettings settings = [options]() {
+ if (options.testFlag(NonPathWildcardConversion)) {
+ // using [\d\D] to mean "match everything";
+ // dot doesn't match newlines, unless in /s mode
+ return GlobSettings{ u'\0', u"[\\d\\D]*", u"[\\d\\D]" };
+ } else {
#ifdef Q_OS_WIN
- const QLatin1Char nativePathSeparator('\\');
- const QLatin1String starEscape("[^/\\\\]*");
- const QLatin1String questionMarkEscape("[^/\\\\]");
+ return GlobSettings{ u'\\', u"[^/\\\\]*", u"[^/\\\\]" };
#else
- const QLatin1Char nativePathSeparator('/');
- const QLatin1String starEscape("[^/]*");
- const QLatin1String questionMarkEscape("[^/]");
+ return GlobSettings{ u'/', u"[^/]*", u"[^/]" };
#endif
+ }
+ }();
while (i < wclen) {
const QChar c = wc[i++];
switch (c.unicode()) {
case '*':
- rx += starEscape;
+ rx += settings.starEscape;
break;
case '?':
- rx += questionMarkEscape;
+ rx += settings.questionMarkEscape;
break;
+ // When not using filepath globbing: \ is escaped, / is itself
+ // When using filepath globbing:
+ // * Unix: \ gets escaped. / is itself
+ // * Windows: \ and / can match each other -- they become [/\\] in regexp
case '\\':
#ifdef Q_OS_WIN
+ if (options.testFlag(NonPathWildcardConversion))
+ rx += u"\\\\";
+ else
+ rx += u"[/\\\\]";
+ break;
case '/':
- rx += QLatin1String("[/\\\\]");
+ if (options.testFlag(NonPathWildcardConversion))
+ rx += u'/';
+ else
+ rx += u"[/\\\\]";
break;
#endif
case '$':
@@ -1895,29 +1989,31 @@ QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, Wil
case '{':
case '|':
case '}':
- rx += QLatin1Char('\\');
+ rx += u'\\';
rx += c;
break;
case '[':
rx += c;
// Support for the [!abc] or [!a-c] syntax
if (i < wclen) {
- if (wc[i] == QLatin1Char('!')) {
- rx += QLatin1Char('^');
+ if (wc[i] == u'!') {
+ rx += u'^';
++i;
}
- if (i < wclen && wc[i] == QLatin1Char(']'))
+ if (i < wclen && wc[i] == u']')
rx += wc[i++];
- while (i < wclen && wc[i] != QLatin1Char(']')) {
- // The '/' appearing in a character class invalidates the
- // regular expression parsing. It also concerns '\\' on
- // Windows OS types.
- if (wc[i] == QLatin1Char('/') || wc[i] == nativePathSeparator)
- return rx;
- if (wc[i] == QLatin1Char('\\'))
- rx += QLatin1Char('\\');
+ while (i < wclen && wc[i] != u']') {
+ if (!options.testFlag(NonPathWildcardConversion)) {
+ // The '/' appearing in a character class invalidates the
+ // regular expression parsing. It also concerns '\\' on
+ // Windows OS types.
+ if (wc[i] == u'/' || wc[i] == settings.nativePathSeparator)
+ return rx;
+ }
+ if (wc[i] == u'\\')
+ rx += u'\\';
rx += wc[i++];
}
}
@@ -1936,7 +2032,9 @@ QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, Wil
/*!
\since 6.0
- Returns a regular expression of the glob pattern \a pattern.
+ Returns a regular expression of the glob pattern \a pattern. The regular expression
+ will be case sensitive if \a cs is \l{Qt::CaseSensitive}, and converted according to
+ \a options.
Equivalent to
\code
@@ -1945,21 +2043,19 @@ QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, Wil
return QRegularExpression(wildcardToRegularExpression(str, options), reOptions);
\endcode
*/
-QRegularExpression QRegularExpression::fromWildcard(QStringView str, Qt::CaseSensitivity cs,
+QRegularExpression QRegularExpression::fromWildcard(QStringView pattern, Qt::CaseSensitivity cs,
WildcardConversionOptions options)
{
auto reOptions = cs == Qt::CaseSensitive ? QRegularExpression::NoPatternOption :
QRegularExpression::CaseInsensitiveOption;
- return QRegularExpression(wildcardToRegularExpression(str, options), reOptions);
+ return QRegularExpression(wildcardToRegularExpression(pattern, options), reOptions);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QRegularExpression::anchoredPattern(const QString &expression)
\since 5.12
\overload
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.15
@@ -1970,9 +2066,9 @@ QRegularExpression QRegularExpression::fromWildcard(QStringView str, Qt::CaseSen
QString QRegularExpression::anchoredPattern(QStringView expression)
{
return QString()
- + QLatin1String("\\A(?:")
+ + "\\A(?:"_L1
+ expression
- + QLatin1String(")\\z");
+ + ")\\z"_L1;
}
/*!
@@ -2003,6 +2099,8 @@ QRegularExpressionMatch::~QRegularExpressionMatch()
{
}
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionMatchPrivate)
+
/*!
Constructs a match result by copying the result of the given \a match.
@@ -2014,6 +2112,20 @@ QRegularExpressionMatch::QRegularExpressionMatch(const QRegularExpressionMatch &
}
/*!
+ \fn QRegularExpressionMatch::QRegularExpressionMatch(QRegularExpressionMatch &&match)
+
+ \since 6.1
+
+ Constructs a match result by moving the result from the given \a match.
+
+ Note that a moved-from QRegularExpressionMatch can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
+
+ \sa operator=()
+*/
+
+/*!
Assigns the match result \a match to this object, and returns a reference
to the copy.
*/
@@ -2026,8 +2138,12 @@ QRegularExpressionMatch &QRegularExpressionMatch::operator=(const QRegularExpres
/*!
\fn QRegularExpressionMatch &QRegularExpressionMatch::operator=(QRegularExpressionMatch &&match)
- Move-assigns the match result \a match to this object, and returns a reference
- to the copy.
+ Move-assigns the match result \a match to this object, and returns a
+ reference to the result.
+
+ Note that a moved-from QRegularExpressionMatch can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
*/
/*!
@@ -2093,7 +2209,7 @@ QRegularExpression::MatchOptions QRegularExpressionMatch::matchOptions() const
If the regular expression did not match, this function returns -1.
- \sa captured(), capturedStart(), capturedEnd(), capturedLength()
+ \sa hasCaptured(), captured(), capturedStart(), capturedEnd(), capturedLength()
*/
int QRegularExpressionMatch::lastCapturedIndex() const
{
@@ -2101,6 +2217,63 @@ int QRegularExpressionMatch::lastCapturedIndex() const
}
/*!
+ \fn bool QRegularExpressionMatch::hasCaptured(const QString &name) const
+ \fn bool QRegularExpressionMatch::hasCaptured(QStringView name) const
+ \since 6.3
+
+ Returns true if the capturing group named \a name captured something
+ in the subject string, and false otherwise (or if there is no
+ capturing group called \a name).
+
+ \note Some capturing groups in a regular expression may not have
+ captured anything even if the regular expression matched. This may
+ happen, for instance, if a conditional operator is used in the
+ pattern:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 36
+
+ Similarly, a capturing group may capture a substring of length 0;
+ this function will return \c{true} for such a capturing group.
+
+ \sa captured(), hasMatch()
+*/
+bool QRegularExpressionMatch::hasCaptured(QStringView name) const
+{
+ const int nth = d->regularExpression.d->captureIndexForName(name);
+ return hasCaptured(nth);
+}
+
+/*!
+ \since 6.3
+
+ Returns true if the \a nth capturing group captured something
+ in the subject string, and false otherwise (or if there is no
+ such capturing group).
+
+ \note The implicit capturing group number 0 captures the substring
+ matched by the entire pattern.
+
+ \note Some capturing groups in a regular expression may not have
+ captured anything even if the regular expression matched. This may
+ happen, for instance, if a conditional operator is used in the
+ pattern:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 36
+
+ Similarly, a capturing group may capture a substring of length 0;
+ this function will return \c{true} for such a capturing group.
+
+ \sa captured(), lastCapturedIndex(), hasMatch()
+*/
+bool QRegularExpressionMatch::hasCaptured(int nth) const
+{
+ if (nth < 0 || nth > lastCapturedIndex())
+ return false;
+
+ return d->capturedOffsets.at(nth * 2) != -1;
+}
+
+/*!
Returns 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
@@ -2133,10 +2306,10 @@ QString QRegularExpressionMatch::captured(int nth) const
*/
QStringView QRegularExpressionMatch::capturedView(int nth) const
{
- if (nth < 0 || nth > lastCapturedIndex())
+ if (!hasCaptured(nth))
return QStringView();
- int start = capturedStart(nth);
+ qsizetype start = capturedStart(nth);
if (start == -1) // didn't capture
return QStringView();
@@ -2144,8 +2317,8 @@ QStringView QRegularExpressionMatch::capturedView(int nth) const
return d->subject.mid(start, capturedLength(nth));
}
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
+/*! \fn QString QRegularExpressionMatch::captured(const QString &name) const
+
Returns the substring captured by the capturing group named \a name.
If the named capturing group \a name did not capture a string, or if
@@ -2154,11 +2327,6 @@ QStringView QRegularExpressionMatch::capturedView(int nth) const
\sa capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QString::isNull()
*/
-QString QRegularExpressionMatch::captured(const QString &name) const
-{
- return captured(qToStringViewIgnoringNull(name));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.10
@@ -2191,7 +2359,7 @@ QString QRegularExpressionMatch::captured(QStringView name) const
there is no capturing group named \a name, returns a null QStringView.
\sa captured(), capturedStart(), capturedEnd(), capturedLength(),
- QStringRef::isNull()
+ QStringView::isNull()
*/
QStringView QRegularExpressionMatch::capturedView(QStringView name) const
{
@@ -2228,9 +2396,9 @@ QStringList QRegularExpressionMatch::capturedTexts() const
\sa capturedEnd(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedStart(int nth) const
+qsizetype QRegularExpressionMatch::capturedStart(int nth) const
{
- if (nth < 0 || nth > lastCapturedIndex())
+ if (!hasCaptured(nth))
return -1;
return d->capturedOffsets.at(nth * 2);
@@ -2244,7 +2412,7 @@ int QRegularExpressionMatch::capturedStart(int nth) const
\sa capturedStart(), capturedEnd(), captured()
*/
-int QRegularExpressionMatch::capturedLength(int nth) const
+qsizetype QRegularExpressionMatch::capturedLength(int nth) const
{
// bound checking performed by these two functions
return capturedEnd(nth) - capturedStart(nth);
@@ -2257,16 +2425,16 @@ int QRegularExpressionMatch::capturedLength(int nth) const
\sa capturedStart(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedEnd(int nth) const
+qsizetype QRegularExpressionMatch::capturedEnd(int nth) const
{
- if (nth < 0 || nth > lastCapturedIndex())
+ if (!hasCaptured(nth))
return -1;
return d->capturedOffsets.at(nth * 2 + 1);
}
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
+/*! \fn qsizetype QRegularExpressionMatch::capturedStart(const QString &name) const
+
Returns the offset inside the subject string corresponding to the starting
position of the substring captured by the capturing group named \a name.
If the capturing group named \a name did not capture a string or doesn't
@@ -2274,12 +2442,9 @@ int QRegularExpressionMatch::capturedEnd(int nth) const
\sa capturedEnd(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedStart(const QString &name) const
-{
- return capturedStart(qToStringViewIgnoringNull(name));
-}
-/*!
+/*! \fn qsizetype QRegularExpressionMatch::capturedLength(const QString &name) const
+
Returns the length of the substring captured by the capturing group named
\a name.
@@ -2288,12 +2453,9 @@ int QRegularExpressionMatch::capturedStart(const QString &name) const
\sa capturedStart(), capturedEnd(), captured()
*/
-int QRegularExpressionMatch::capturedLength(const QString &name) const
-{
- return capturedLength(qToStringViewIgnoringNull(name));
-}
-/*!
+/*! \fn qsizetype QRegularExpressionMatch::capturedEnd(const QString &name) const
+
Returns the offset inside the subject string immediately after the ending
position of the substring captured by the capturing group named \a name. If
the capturing group named \a name did not capture a string or doesn't
@@ -2301,11 +2463,6 @@ int QRegularExpressionMatch::capturedLength(const QString &name) const
\sa capturedStart(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedEnd(const QString &name) const
-{
- return capturedEnd(qToStringViewIgnoringNull(name));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.10
@@ -2317,7 +2474,7 @@ int QRegularExpressionMatch::capturedEnd(const QString &name) const
\sa capturedEnd(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedStart(QStringView name) const
+qsizetype QRegularExpressionMatch::capturedStart(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedStart: empty capturing group name passed");
@@ -2340,7 +2497,7 @@ int QRegularExpressionMatch::capturedStart(QStringView name) const
\sa capturedStart(), capturedEnd(), captured()
*/
-int QRegularExpressionMatch::capturedLength(QStringView name) const
+qsizetype QRegularExpressionMatch::capturedLength(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedLength: empty capturing group name passed");
@@ -2362,7 +2519,7 @@ int QRegularExpressionMatch::capturedLength(QStringView name) const
\sa capturedStart(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedEnd(QStringView name) const
+qsizetype QRegularExpressionMatch::capturedEnd(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedEnd: empty capturing group name passed");
@@ -2447,6 +2604,8 @@ QRegularExpressionMatchIterator::~QRegularExpressionMatchIterator()
{
}
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionMatchIteratorPrivate)
+
/*!
Constructs a QRegularExpressionMatchIterator object as a copy of \a
iterator.
@@ -2459,6 +2618,20 @@ QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(const QRegularE
}
/*!
+ \fn QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(QRegularExpressionMatchIterator &&iterator)
+
+ \since 6.1
+
+ Constructs a QRegularExpressionMatchIterator object by moving from \a iterator.
+
+ Note that a moved-from QRegularExpressionMatchIterator can only be destroyed
+ or assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
+
+ \sa operator=()
+*/
+
+/*!
Assigns the iterator \a iterator to this object, and returns a reference to
the copy.
*/
@@ -2471,7 +2644,12 @@ QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(cons
/*!
\fn QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(QRegularExpressionMatchIterator &&iterator)
- Move-assigns the \a iterator to this object.
+ Move-assigns the \a iterator to this object, and returns a reference to the
+ result.
+
+ Note that a moved-from QRegularExpressionMatchIterator can only be destroyed
+ or assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
*/
/*!
@@ -2529,12 +2707,11 @@ QRegularExpressionMatch QRegularExpressionMatchIterator::next()
{
if (!hasNext()) {
qWarning("QRegularExpressionMatchIterator::next() called on an iterator already at end");
- return d->next;
+ return d.constData()->next;
}
- QRegularExpressionMatch current = d->next;
- d->next = d->next.d.constData()->nextMatch();
- return current;
+ d.detach();
+ return std::exchange(d->next, d->next.d.constData()->nextMatch());
}
/*!
@@ -2572,6 +2749,19 @@ QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions()
return d->matchOptions;
}
+/*!
+ \internal
+*/
+QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
+{
+ return QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator(iterator);
+}
+
+/*!
+ \fn QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &)
+ \internal
+*/
+
#ifndef QT_NO_DATASTREAM
/*!
\relates QRegularExpression
@@ -2582,7 +2772,7 @@ QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions()
*/
QDataStream &operator<<(QDataStream &out, const QRegularExpression &re)
{
- out << re.pattern() << quint32(re.patternOptions());
+ out << re.pattern() << quint32(re.patternOptions().toInt());
return out;
}
@@ -2599,7 +2789,7 @@ QDataStream &operator>>(QDataStream &in, QRegularExpression &re)
quint32 patternOptions;
in >> pattern >> patternOptions;
re.setPattern(pattern);
- re.setPatternOptions(QRegularExpression::PatternOptions(patternOptions));
+ re.setPatternOptions(QRegularExpression::PatternOptions::fromInt(patternOptions));
return in;
}
#endif
@@ -2910,7 +3100,8 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "heap limit exceeded"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid syntax"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error - duplicate substitution match"),
- QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching")
+ QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "INTERNAL ERROR: invalid substring offset")
};
#endif // #if 0