summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qregularexpression.cpp51
-rw-r--r--src/corelib/tools/qregularexpression.h5
-rw-r--r--tests/auto/corelib/tools/qregularexpression/.gitignore1
-rw-r--r--tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro8
-rw-r--r--tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp52
-rw-r--r--tests/auto/corelib/tools/qregularexpression/qregularexpression.pro2
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp71
7 files changed, 183 insertions, 7 deletions
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index daa6765dcc..26988a4420 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -699,6 +699,12 @@ 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
+ The regular expression will be optimized (and possibly
+ JIT-compiled) on its first usage, instead of after a certain (undefined)
+ number of usages. See also \l{QRegularExpression::}{optimize()}.
+ This enum value has been introduced in Qt 5.4.
*/
/*!
@@ -802,7 +808,13 @@ struct QRegularExpressionPrivate : QSharedData
void cleanCompiledPattern();
void compilePattern();
void getPatternInfo();
- void optimizePattern();
+
+ enum OptimizePatternOption {
+ LazyOptimizeOption,
+ ImmediateOptimizeOption
+ };
+
+ void optimizePattern(OptimizePatternOption option);
QRegularExpressionMatchPrivate *doMatch(const QString &subject,
int offset,
@@ -1107,13 +1119,16 @@ static bool isJitEnabled()
(localStudyData) before using storeRelease on studyData. In doMatch there's
the corresponding loadAcquire.
*/
-void QRegularExpressionPrivate::optimizePattern()
+void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
{
Q_ASSERT(compiledPattern);
QMutexLocker lock(&mutex);
- if (studyData.load() || (++usedCount != qt_qregularexpression_optimize_after_use_count))
+ if (studyData.load()) // already optimized
+ return;
+
+ if ((option == LazyOptimizeOption) && (++usedCount != qt_qregularexpression_optimize_after_use_count))
return;
static const bool enableJit = isJitEnabled();
@@ -1233,8 +1248,13 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
matchType, matchOptions,
capturingCount + 1);
+ const OptimizePatternOption optimizePatternOption =
+ (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
+ ? ImmediateOptimizeOption
+ : LazyOptimizeOption;
+
// this is mutex protected
- const_cast<QRegularExpressionPrivate *>(this)->optimizePattern();
+ const_cast<QRegularExpressionPrivate *>(this)->optimizePattern(optimizePatternOption);
// work with a local copy of the study data, as we are running pcre_exec
// potentially more than once, and we don't want to run call it
@@ -1667,6 +1687,27 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
}
/*!
+ \since 5.4
+
+ Forces an immediate optimization of the pattern, including
+ JIT-compiling it (if the JIT compiler is enabled).
+
+ Patterns are normally optimized only after a certain number of usages.
+ If you can predict that this QRegularExpression object is going to be
+ used for several matches, it may be convenient to optimize it in
+ advance by calling this function.
+
+ \sa QRegularExpression::OptimizeOnFirstUsageOption
+*/
+void QRegularExpression::optimize()
+{
+ if (!isValid()) // will compile the pattern
+ return;
+
+ d->optimizePattern(QRegularExpressionPrivate::ImmediateOptimizeOption);
+}
+
+/*!
Returns \c true if the regular expression is equal to \a re, or false
otherwise. Two QRegularExpression objects are equal if they have
the same pattern string and the same pattern options.
@@ -2327,6 +2368,8 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.append("DontCaptureOption|");
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
flags.append("UseUnicodePropertiesOption|");
+ if (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
+ flags.append("OptimizeOnFirstUsageOption|");
flags.chop(1);
}
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index 5059ea6431..6154ea7c51 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -69,7 +69,8 @@ public:
ExtendedPatternSyntaxOption = 0x0008,
InvertedGreedinessOption = 0x0010,
DontCaptureOption = 0x0020,
- UseUnicodePropertiesOption = 0x0040
+ UseUnicodePropertiesOption = 0x0040,
+ OptimizeOnFirstUsageOption = 0x0080
};
Q_DECLARE_FLAGS(PatternOptions, PatternOption)
@@ -122,6 +123,8 @@ public:
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+ void optimize();
+
static QString escape(const QString &str);
bool operator==(const QRegularExpression &re) const;
diff --git a/tests/auto/corelib/tools/qregularexpression/.gitignore b/tests/auto/corelib/tools/qregularexpression/.gitignore
index c9249e090e..4650b4454e 100644
--- a/tests/auto/corelib/tools/qregularexpression/.gitignore
+++ b/tests/auto/corelib/tools/qregularexpression/.gitignore
@@ -1,2 +1,3 @@
tst_qregularexpression_alwaysoptimize
tst_qregularexpression_defaultoptimize
+tst_qregularexpression_forceoptimize
diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro b/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro
new file mode 100644
index 0000000000..d34bc9b93d
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qregularexpression_forceoptimize
+QT = core testlib
+HEADERS = ../tst_qregularexpression.h
+SOURCES = \
+ tst_qregularexpression_forceoptimize.cpp \
+ ../tst_qregularexpression.cpp
+DEFINES += forceOptimize=true
diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp
new file mode 100644
index 0000000000..6244aacedf
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include "../tst_qregularexpression.h"
+
+class tst_QRegularExpression_ForceOptimize : public tst_QRegularExpression
+{
+ Q_OBJECT
+};
+
+QTEST_APPLESS_MAIN(tst_QRegularExpression_ForceOptimize)
+
+#include "tst_qregularexpression_forceoptimize.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
index 0cae10112f..c030f04a27 100644
--- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
+++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = defaultoptimize
+SUBDIRS = defaultoptimize forceoptimize
contains(QT_CONFIG,private_tests):SUBDIRS += alwaysoptimize
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
index 909725f4b8..5fad1bb738 100644
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
+++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
@@ -48,6 +48,10 @@
#include "tst_qregularexpression.h"
+#ifndef forceOptimize
+#define forceOptimize false
+#endif
+
struct Match
{
Match()
@@ -329,22 +333,30 @@ void tst_QRegularExpression::gettersSetters()
{
QRegularExpression re;
re.setPattern(pattern);
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
}
{
QRegularExpression re;
re.setPatternOptions(patternOptions);
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.pattern(), QString());
QCOMPARE(re.patternOptions(), patternOptions);
}
{
QRegularExpression re(pattern);
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
}
{
QRegularExpression re(pattern, patternOptions);
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), patternOptions);
}
@@ -385,6 +397,8 @@ void tst_QRegularExpression::escape()
QFETCH(QString, escaped);
QCOMPARE(QRegularExpression::escape(string), escaped);
QRegularExpression re(escaped);
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.isValid(), true);
}
@@ -415,6 +429,8 @@ void tst_QRegularExpression::validity()
QFETCH(QString, pattern);
QFETCH(bool, validity);
QRegularExpression re(pattern);
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.isValid(), validity);
if (!validity)
QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
@@ -501,6 +517,9 @@ void tst_QRegularExpression::patternOptions()
QFETCH(QString, subject);
QFETCH(Match, match);
+ if (forceOptimize)
+ regexp.optimize();
+
QRegularExpressionMatch m = regexp.match(subject);
consistencyCheck(m);
QVERIFY(m == match);
@@ -717,6 +736,9 @@ void tst_QRegularExpression::normalMatch()
QFETCH(QRegularExpression::MatchOptions, matchOptions);
QFETCH(Match, match);
+ if (forceOptimize)
+ regexp.optimize();
+
{
QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NormalMatch, matchOptions);
consistencyCheck(m);
@@ -995,6 +1017,9 @@ void tst_QRegularExpression::partialMatch()
QFETCH(QRegularExpression::MatchOptions, matchOptions);
QFETCH(Match, match);
+ if (forceOptimize)
+ regexp.optimize();
+
{
QRegularExpressionMatch m = regexp.match(subject, offset, matchType, matchOptions);
consistencyCheck(m);
@@ -1286,6 +1311,10 @@ void tst_QRegularExpression::globalMatch()
QFETCH(QRegularExpression::MatchType, matchType);
QFETCH(QRegularExpression::MatchOptions, matchOptions);
QFETCH(QList<Match>, matchList);
+
+ if (forceOptimize)
+ regexp.optimize();
+
{
QRegularExpressionMatchIterator iterator = regexp.globalMatch(subject, offset, matchType, matchOptions);
consistencyCheck(iterator);
@@ -1320,6 +1349,10 @@ void tst_QRegularExpression::serialize()
QFETCH(QString, pattern);
QFETCH(QRegularExpression::PatternOptions, patternOptions);
QRegularExpression outRe(pattern, patternOptions);
+
+ if (forceOptimize)
+ outRe.optimize();
+
QByteArray buffer;
{
QDataStream out(&buffer, QIODevice::WriteOnly);
@@ -1376,16 +1409,34 @@ void tst_QRegularExpression::operatoreq()
{
QRegularExpression re1(pattern);
QRegularExpression re2(pattern);
+
+ if (forceOptimize)
+ re1.optimize();
+ if (forceOptimize)
+ re2.optimize();
+
verifyEquality(re1, re2);
}
{
QRegularExpression re1(QString(), patternOptions);
QRegularExpression re2(QString(), patternOptions);
+
+ if (forceOptimize)
+ re1.optimize();
+ if (forceOptimize)
+ re2.optimize();
+
verifyEquality(re1, re2);
}
{
QRegularExpression re1(pattern, patternOptions);
QRegularExpression re2(pattern, patternOptions);
+
+ if (forceOptimize)
+ re1.optimize();
+ if (forceOptimize)
+ re2.optimize();
+
verifyEquality(re1, re2);
}
}
@@ -1414,6 +1465,10 @@ void tst_QRegularExpression::captureCount()
{
QFETCH(QString, pattern);
QRegularExpression re(pattern);
+
+ if (forceOptimize)
+ re.optimize();
+
QTEST(re.captureCount(), "captureCount");
if (!re.isValid())
QCOMPARE(re.captureCount(), -1);
@@ -1480,7 +1535,11 @@ void tst_QRegularExpression::captureNames()
QFETCH(QString, pattern);
QFETCH(StringToIntMap, namedCapturesIndexMap);
- const QRegularExpression re(pattern);
+ QRegularExpression re(pattern);
+
+ if (forceOptimize)
+ re.optimize();
+
QStringList namedCaptureGroups = re.namedCaptureGroups();
int namedCaptureGroupsCount = namedCaptureGroups.size();
@@ -1515,6 +1574,10 @@ void tst_QRegularExpression::pcreJitStackUsage()
QFETCH(QString, subject);
QRegularExpression re(pattern);
+
+ if (forceOptimize)
+ re.optimize();
+
QVERIFY(re.isValid());
QRegularExpressionMatch match = re.match(subject);
consistencyCheck(match);
@@ -1541,6 +1604,10 @@ void tst_QRegularExpression::regularExpressionMatch()
QFETCH(QString, subject);
QRegularExpression re(pattern);
+
+ if (forceOptimize)
+ re.optimize();
+
QVERIFY(re.isValid());
QRegularExpressionMatch match = re.match(subject);
consistencyCheck(match);
@@ -1580,5 +1647,7 @@ void tst_QRegularExpression::JOptionUsage()
QRegularExpression re(pattern);
if (isValid && JOptionUsed)
QTest::ignoreMessage(QtWarningMsg, qPrintable(warningMessage.arg(pattern)));
+ if (forceOptimize)
+ re.optimize();
QCOMPARE(re.isValid(), isValid);
}