diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-04-02 09:28:23 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-04-03 21:01:45 +0200 |
commit | e1bc9db85149b89feb73f1690fd218de498b8b27 (patch) | |
tree | 1aa369e8fa0461e1629a177923b0433cb681e90b /src/qml/jsruntime | |
parent | 3156fd64cccbc49588fbd71621a8e83b95b25eba (diff) |
Improve conversion between JS RegExp and QRegularExpression
Add support for InvertedGreedinessOption and MultilineOption.
Change-Id: I19dce6e356a7ec406640bb8858885cd576b4aa2f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 97 |
1 files changed, 54 insertions, 43 deletions
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index a8a37cda37..f763237ea3 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -84,6 +84,42 @@ void Heap::RegExpObject::init(QV4::RegExp *value) o->initProperties(); } +static QString minimalPattern(const QString &pattern) +{ + QString ecmaPattern; + int len = pattern.length(); + ecmaPattern.reserve(len); + int i = 0; + const QChar *wc = pattern.unicode(); + bool inBracket = false; + while (i < len) { + QChar c = wc[i++]; + ecmaPattern += c; + switch (c.unicode()) { + case '?': + case '+': + case '*': + case '}': + if (!inBracket) + ecmaPattern += QLatin1Char('?'); + break; + case '\\': + if (i < len) + ecmaPattern += wc[i++]; + break; + case '[': + inBracket = true; + break; + case ']': + inBracket = false; + break; + default: + break; + } + } + return ecmaPattern; +} + // Converts a QRegExp to a JS RegExp. // The conversion is not 100% exact since ECMA regexp and QRegExp // have different semantics/flags, but we try to do our best. @@ -93,40 +129,8 @@ void Heap::RegExpObject::init(const QRegExp &re) // Convert the pattern to a ECMAScript pattern. QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax()); - if (re.isMinimal()) { - QString ecmaPattern; - int len = pattern.length(); - ecmaPattern.reserve(len); - int i = 0; - const QChar *wc = pattern.unicode(); - bool inBracket = false; - while (i < len) { - QChar c = wc[i++]; - ecmaPattern += c; - switch (c.unicode()) { - case '?': - case '+': - case '*': - case '}': - if (!inBracket) - ecmaPattern += QLatin1Char('?'); - break; - case '\\': - if (i < len) - ecmaPattern += wc[i++]; - break; - case '[': - inBracket = true; - break; - case ']': - inBracket = false; - break; - default: - break; - } - } - pattern = ecmaPattern; - } + if (re.isMinimal()) + pattern = minimalPattern(pattern); Scope scope(internalClass->engine); Scoped<QV4::RegExpObject> o(scope, this); @@ -148,10 +152,16 @@ void Heap::RegExpObject::init(const QRegularExpression &re) Scope scope(internalClass->engine); Scoped<QV4::RegExpObject> o(scope, this); - const uint flags = (re.patternOptions() & QRegularExpression::CaseInsensitiveOption) - ? CompiledData::RegExp::RegExp_IgnoreCase - : CompiledData::RegExp::RegExp_NoFlags; - o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, re.pattern(), flags)); + QRegularExpression::PatternOptions options = re.patternOptions(); + uint flags = (options & QRegularExpression::CaseInsensitiveOption) + ? CompiledData::RegExp::RegExp_IgnoreCase + : CompiledData::RegExp::RegExp_NoFlags; + if (options & QRegularExpression::MultilineOption) + flags |= CompiledData::RegExp::RegExp_Multiline; + QString pattern = re.pattern(); + if (options & QRegularExpression::InvertedGreedinessOption) + pattern = minimalPattern(pattern); + o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, pattern, flags)); o->initProperties(); } #endif @@ -178,11 +188,12 @@ QRegExp RegExpObject::toQRegExp() const // have different semantics/flags, but we try to do our best. QRegularExpression RegExpObject::toQRegularExpression() const { - QRegularExpression::PatternOptions caseSensitivity - = (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase) - ? QRegularExpression::CaseInsensitiveOption - : QRegularExpression::NoPatternOption; - return QRegularExpression(*value()->pattern, caseSensitivity); + QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption; + if (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase) + options |= QRegularExpression::CaseInsensitiveOption; + if (value()->flags & CompiledData::RegExp::RegExp_Multiline) + options |= QRegularExpression::MultilineOption; + return QRegularExpression(*value()->pattern, options); } #endif |