aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldom/qqmldompath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldom/qqmldompath.cpp')
-rw-r--r--src/qmldom/qqmldompath.cpp485
1 files changed, 270 insertions, 215 deletions
diff --git a/src/qmldom/qqmldompath.cpp b/src/qmldom/qqmldompath.cpp
index 60086ced10..d2b4582bc0 100644
--- a/src/qmldom/qqmldompath.cpp
+++ b/src/qmldom/qqmldompath.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml 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$
-**/
-#include "qqmldompath_p.h"
+// Copyright (C) 2020 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 "qqmldomitem_p.h"
#include "qqmldomerrormessage_p.h"
#include <QtCore/QDebug>
@@ -101,8 +65,6 @@ The current contexts are:
\li \l{@module} The current module instantiation.
\li \l{@ids} The ids in the current component.
\li \l{@types} All the types in the current component (reachable through imports, respecting renames)
-\li \l{@instantiation} The current instantiation, either component instantiation or module
- instantiation
\li \l{@lookupStrict} The strict lookup inside the current object: localJS, ids, properties, proto
properties, component, its properties, global context, oterwise error
\li \l{@lookupDynamic} The default lookup inside the current object: localJS, ids, properties, proto
@@ -112,15 +74,16 @@ The current contexts are:
\endlist
*/
-void Base::dump(Sink sink) const {
- if (hasSquareBrackets())
+void Base::dump(const Sink &sink, const QString &name, bool hasSquareBrackets) const {
+ if (hasSquareBrackets)
sink(u"[");
- sink(name());
- if (hasSquareBrackets())
+ sink(name);
+ if (hasSquareBrackets)
sink(u"]");
}
-Filter::Filter(function<bool(DomItem)> f, QStringView filterDescription): filterFunction(f), filterDescription(filterDescription) {}
+Filter::Filter(const function<bool(const DomItem &)> &f, QStringView filterDescription)
+ : filterFunction(f), filterDescription(filterDescription) {}
QString Filter::name() const {
return QLatin1String("?(%1)").arg(filterDescription); }
@@ -128,7 +91,7 @@ QString Filter::name() const {
bool Filter::checkName(QStringView s) const
{
return s.startsWith(u"?(")
- && s.mid(2, s.length()-3) == filterDescription
+ && s.mid(2, s.size()-3) == filterDescription
&& s.endsWith(u")");
}
@@ -138,13 +101,6 @@ enum class ParserState{
End
};
-} // namespace PathEls
-
-using namespace PathEls;
-
-PathComponent::~PathComponent(){
-}
-
int PathComponent::cmp(const PathComponent &p1, const PathComponent &p2)
{
int k1 = static_cast<int>(p1.kind());
@@ -157,37 +113,46 @@ int PathComponent::cmp(const PathComponent &p1, const PathComponent &p2)
case Kind::Empty:
return 0;
case Kind::Field:
- return p1.data.field.fieldName.compare(p2.data.field.fieldName);
+ return std::get<Field>(p1.m_data).fieldName.compare(std::get<Field>(p2.m_data).fieldName);
case Kind::Index:
- if (p1.data.index.indexValue < p2.data.index.indexValue)
+ if (std::get<Index>(p1.m_data).indexValue < std::get<Index>(p2.m_data).indexValue)
return -1;
- if (p1.data.index.indexValue > p2.data.index.indexValue)
+ if (std::get<Index>(p1.m_data).indexValue > std::get<Index>(p2.m_data).indexValue)
return 1;
return 0;
case Kind::Key:
- return p1.data.key.keyValue.compare(p2.data.key.keyValue);
+ return std::get<Key>(p1.m_data).keyValue.compare(std::get<Key>(p2.m_data).keyValue);
case Kind::Root:
{
- int c = int(p1.data.root.contextKind) - int(p2.data.root.contextKind);
+ PathRoot k1 = std::get<Root>(p1.m_data).contextKind;
+ PathRoot k2 = std::get<Root>(p2.m_data).contextKind;
+ if (k1 == PathRoot::Env || k1 == PathRoot::Universe)
+ k1 = PathRoot::Top;
+ if (k2 == PathRoot::Env || k2 == PathRoot::Universe)
+ k2 = PathRoot::Top;
+ int c = int(k1) - int(k2);
if (c != 0)
return c;
- return p1.data.root.contextName.compare(p2.data.root.contextName);
+ return std::get<Root>(p1.m_data).contextName.compare(std::get<Root>(p2.m_data).contextName);
}
case Kind::Current:
{
- int c = int(p1.data.current.contextKind) - int(p2.data.current.contextKind);
+ int c = int(std::get<Current>(p1.m_data).contextKind)
+ - int(std::get<Current>(p2.m_data).contextKind);
if (c != 0)
return c;
- return p1.data.current.contextName.compare(p2.data.current.contextName);
+ return std::get<Current>(p1.m_data).contextName
+ .compare(std::get<Current>(p2.m_data).contextName);
}
case Kind::Any:
return 0;
case Kind::Filter:
{
- int c = p1.data.filter.filterDescription.compare(p2.data.filter.filterDescription);
+ int c = std::get<Filter>(p1.m_data).filterDescription
+ .compare(std::get<Filter>(p2.m_data).filterDescription);
if (c != 0)
return c;
- if (p1.data.filter.filterDescription.startsWith(u"<")) {
+ if (std::get<Filter>(p1.m_data).filterDescription.startsWith(u"<")) {
// assuming non comparable native code (target comparison is not portable)
auto pp1 = &p1;
auto pp2 = &p2;
@@ -203,24 +168,27 @@ int PathComponent::cmp(const PathComponent &p1, const PathComponent &p2)
return 0;
}
-PathComponent Path::component(int i) const
+} // namespace PathEls
+
+const PathEls::PathComponent &Path::component(int i) const
{
+ static Component emptyComponent;
if (i < 0)
i += m_length;
if (i >= m_length || i < 0) {
Q_ASSERT(false && "index out of bounds");
- return Component();
+ return emptyComponent;
}
i = i - m_length - m_endOffset;
auto data = m_data.get();
while (data) {
- i += data->components.length();
+ i += data->components.size();
if (i >= 0)
- return data->components.at(i);
+ return std::as_const(data)->components[i];
data = data->parent.get();
}
Q_ASSERT(false && "Invalid data reached while resolving a seemengly valid index in Path (inconsisten Path object)");
- return Component();
+ return emptyComponent;
}
Path Path::operator[](int i) const
@@ -233,10 +201,20 @@ QQmlJS::Dom::Path::operator bool() const
return length() != 0;
}
+PathIterator Path::begin() const
+{
+ return PathIterator{*this};
+}
+
+PathIterator Path::end() const
+{
+ return PathIterator();
+}
+
PathRoot Path::headRoot() const
{
- auto comp = component(0);
- if (Root const * r = comp.base()->asRoot())
+ auto &comp = component(0);
+ if (PathEls::Root const * r = comp.asRoot())
return r->contextKind;
return PathRoot::Other;
}
@@ -244,13 +222,15 @@ PathRoot Path::headRoot() const
PathCurrent Path::headCurrent() const
{
auto comp = component(0);
- if (Current const * c = comp.base()->asCurrent())
+ if (PathEls::Current const * c = comp.asCurrent())
return c->contextKind;
return PathCurrent::Other;
}
Path::Kind Path::headKind() const
{
+ if (m_length == 0)
+ return Path::Kind::Empty;
return component(0).kind();
}
@@ -269,10 +249,10 @@ index_type Path::headIndex(index_type defaultValue) const
return component(0).index(defaultValue);
}
-function<bool (DomItem)> Path::headFilter() const
+function<bool(const DomItem &)> Path::headFilter() const
{
- auto comp = component(0);
- if (Filter const * f = comp.base()->asFilter()) {
+ auto &comp = component(0);
+ if (PathEls::Filter const * f = comp.asFilter()) {
return f->filterFunction;
}
return {};
@@ -300,7 +280,7 @@ Source Path::split() const
return Source{Path(), *this};
}
-bool inQString(QStringView el, QString base)
+bool inQString(QStringView el, const QString &base)
{
if (quintptr(base.constData()) > quintptr(el.begin())
|| quintptr(base.constData() + base.size()) < quintptr(el.begin()))
@@ -309,7 +289,7 @@ bool inQString(QStringView el, QString base)
return diff >= 0 && diff < base.size();
}
-bool inQString(QString el, QString base)
+bool inQString(const QString &el, const QString &base)
{
if (quintptr(base.constData()) > quintptr(el.constData())
|| quintptr(base.constData() + base.size()) < quintptr(el.constData()))
@@ -318,7 +298,7 @@ bool inQString(QString el, QString base)
return diff >= 0 && diff < base.size() && diff + el.size() < base.size();
}
-Path Path::fromString(QStringView s, ErrorHandler errorHandler)
+Path Path::fromString(QStringView s, const ErrorHandler &errorHandler)
{
if (s.isEmpty())
return Path();
@@ -332,51 +312,51 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
const QChar backslash = QChar::fromLatin1('\\');
const QChar underscore = QChar::fromLatin1('_');
const QChar tilda = QChar::fromLatin1('~');
- for (int i=0; i < s.length(); ++i)
+ for (int i=0; i < s.size(); ++i)
if (s.at(i) == lsBrace || s.at(i) == dot)
++len;
QVector<Component> components;
components.reserve(len);
int i = 0;
int i0 = 0;
- ParserState state = ParserState::Start;
+ PathEls::ParserState state = PathEls::ParserState::Start;
QStringList strVals;
- while (i < s.length()) {
+ while (i < s.size()) {
// skip space
- while (i < s.length() && s.at(i).isSpace())
+ while (i < s.size() && s.at(i).isSpace())
++i;
- if (i >= s.length())
+ if (i >= s.size())
break;
QChar c = s.at(i++);
switch (state) {
- case ParserState::Start:
+ case PathEls::ParserState::Start:
if (c == dollar) {
i0 = i;
- while (i < s.length() && s.at(i).isLetterOrNumber()){
+ while (i < s.size() && s.at(i).isLetterOrNumber()){
++i;
}
- components.append(Component(Root(s.mid(i0,i-i0))));
- state = ParserState::End;
+ components.append(Component(PathEls::Root(s.mid(i0,i-i0))));
+ state = PathEls::ParserState::End;
} else if (c == at) {
i0 = i;
- while (i < s.length() && s.at(i).isLetterOrNumber()){
+ while (i < s.size() && s.at(i).isLetterOrNumber()){
++i;
}
- components.append(Component(Current(s.mid(i0,i-i0))));
- state = ParserState::End;
+ components.append(Component(PathEls::Current(s.mid(i0,i-i0))));
+ state = PathEls::ParserState::End;
} else if (c.isLetter()) {
myErrors().warning(tr("Field expressions should start with a dot, even when at the start of the path %1.")
.arg(s)).handle(errorHandler);
return Path();
} else {
--i;
- state = ParserState::End;
+ state = PathEls::ParserState::End;
}
break;
- case ParserState::IndexOrKey:
+ case PathEls::ParserState::IndexOrKey:
if (c.isDigit()) {
i0 = i-1;
- while (i < s.length() && s.at(i).isDigit())
+ while (i < s.size() && s.at(i).isDigit())
++i;
bool ok;
components.append(Component(static_cast<index_type>(s.mid(i0,i-i0).toString()
@@ -388,22 +368,19 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
}
} else if (c.isLetter() || c == tilda || c == underscore) {
i0 = i-1;
- while (i < s.length() && (s.at(i).isLetterOrNumber() || s.at(i) == underscore || s.at(i) == tilda))
+ while (i < s.size() && (s.at(i).isLetterOrNumber() || s.at(i) == underscore || s.at(i) == tilda))
++i;
- components.append(Component(Key(s.mid(i0, i-i0))));
+ components.append(Component(PathEls::Key(s.mid(i0, i - i0).toString())));
} else if (c == quote) {
i0 = i;
QString strVal;
- QStringView key;
- bool needsConversion = false;
bool properEnd = false;
- while (i < s.length()) {
+ while (i < s.size()) {
c = s.at(i);
if (c == quote) {
properEnd = true;
break;
} else if (c == backslash) {
- needsConversion = true;
strVal.append(s.mid(i0, i - i0).toString());
c = s.at(++i);
i0 = i + 1;
@@ -419,33 +396,27 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
++i;
}
if (properEnd) {
- if (needsConversion) {
- strVal.append(s.mid(i0, i - i0).toString());
- strVals.append(strVal);
- key=strVal;
- } else {
- key = s.mid(i0, i - i0);
- }
+ strVal.append(s.mid(i0, i - i0).toString());
++i;
} else {
myErrors().error(tr("Unclosed quoted string at char %1.")
.arg(QString::number(i - 1))).handle(errorHandler);
return Path();
}
- components.append(Key(key));
+ components.append(PathEls::Key(strVal));
} else if (c == QChar::fromLatin1('*')) {
- components.append(Component(Any()));
+ components.append(Component(PathEls::Any()));
} else if (c == QChar::fromLatin1('?')) {
- while (i < s.length() && s.at(i).isSpace())
+ while (i < s.size() && s.at(i).isSpace())
++i;
- if (i >= s.length() || s.at(i) != QChar::fromLatin1('(')) {
+ if (i >= s.size() || s.at(i) != QChar::fromLatin1('(')) {
myErrors().error(tr("Expected a brace in filter after the question mark (at char %1).")
.arg(QString::number(i))).handle(errorHandler);
return Path();
}
i0 = ++i;
- while (i < s.length() && s.at(i) != QChar::fromLatin1(')')) ++i; // check matching braces when skipping??
- if (i >= s.length() || s.at(i) != QChar::fromLatin1(')')) {
+ while (i < s.size() && s.at(i) != QChar::fromLatin1(')')) ++i; // check matching braces when skipping??
+ if (i >= s.size() || s.at(i) != QChar::fromLatin1(')')) {
myErrors().error(tr("Expected a closing brace in filter after the question mark (at char %1).")
.arg(QString::number(i))).handle(errorHandler);
return Path();
@@ -459,32 +430,32 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
.arg(c).arg(i-1)).handle(errorHandler);
return Path();
}
- while (i < s.length() && s.at(i).isSpace()) ++i;
- if (i >= s.length() || s.at(i) != rsBrace) {
+ while (i < s.size() && s.at(i).isSpace()) ++i;
+ if (i >= s.size() || s.at(i) != rsBrace) {
myErrors().error(tr("square braces misses closing brace at char %1.")
.arg(QString::number(i))).handle(errorHandler);
return Path();
} else {
++i;
}
- state = ParserState::End;
+ state = PathEls::ParserState::End;
break;
- case ParserState::End:
+ case PathEls::ParserState::End:
if (c == dot) {
- while (i < s.length() && s.at(i).isSpace()) ++i;
- if (i == s.length()) {
+ while (i < s.size() && s.at(i).isSpace()) ++i;
+ if (i == s.size()) {
components.append(Component());
- state = ParserState::End;
+ state = PathEls::ParserState::End;
} else if (s.at(i).isLetter() || s.at(i) == underscore || s.at(i) == tilda) {
i0 = i;
- while (i < s.length() && (s.at(i).isLetterOrNumber() || s.at(i) == underscore || s.at(i) == tilda)) {
+ while (i < s.size() && (s.at(i).isLetterOrNumber() || s.at(i) == underscore || s.at(i) == tilda)) {
++i;
}
- components.append(Component(Field(s.mid(i0,i-i0))));
- state = ParserState::End;
+ components.append(Component(PathEls::Field(s.mid(i0,i-i0))));
+ state = PathEls::ParserState::End;
} else if (s.at(i).isDigit()) {
i0 = i;
- while (i < s.length() && s.at(i).isDigit()){
+ while (i < s.size() && s.at(i).isDigit()){
++i;
}
bool ok;
@@ -495,27 +466,27 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
.arg(QString::number(i0))).handle(errorHandler);
return Path();
} else {
- myErrors().hint(tr("Index should use square brackets and not a dot (at char %1).")
+ myErrors().info(tr("Index should use square brackets and not a dot (at char %1).")
.arg(QString::number(i0))).handle(errorHandler);
}
- state = ParserState::End;
+ state = PathEls::ParserState::End;
} else if (s.at(i) == dot || s.at(i) == lsBrace) {
components.append(Component());
- state = ParserState::End;
+ state = PathEls::ParserState::End;
} else if (s.at(i) == at) {
i0 = ++i;
- while (i < s.length() && s.at(i).isLetterOrNumber()){
+ while (i < s.size() && s.at(i).isLetterOrNumber()){
++i;
}
- components.append(Component(Current(s.mid(i0,i-i0))));
- state = ParserState::End;
+ components.append(Component(PathEls::Current(s.mid(i0,i-i0))));
+ state = PathEls::ParserState::End;
} else if (s.at(i) == dollar) {
i0 = ++i;
- while (i < s.length() && s.at(i).isLetterOrNumber()){
+ while (i < s.size() && s.at(i).isLetterOrNumber()){
++i;
}
- components.append(Component(Root(s.mid(i0,i-i0))));
- state = ParserState::End;
+ components.append(Component(PathEls::Root(s.mid(i0,i-i0))));
+ state = PathEls::ParserState::End;
} else {
c=s.at(i);
myErrors().error(tr("Unexpected character '%1' after dot (at char %2).")
@@ -524,7 +495,7 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
return Path();
}
} else if (c == lsBrace) {
- state = ParserState::IndexOrKey;
+ state = PathEls::ParserState::IndexOrKey;
} else {
myErrors().error(tr("Unexpected character '%1' after end of component (char %2).")
.arg(QStringView(&c,1))
@@ -535,163 +506,184 @@ Path Path::fromString(QStringView s, ErrorHandler errorHandler)
}
}
switch (state) {
- case ParserState::Start:
+ case PathEls::ParserState::Start:
return Path();
- case ParserState::IndexOrKey:
+ case PathEls::ParserState::IndexOrKey:
errorHandler(myErrors().error(tr("unclosed square brace at end.")));
return Path();
- case ParserState::End:
- return Path(0, components.length(), std::make_shared<PathData>(strVals, components));
+ case PathEls::ParserState::End:
+ return Path(0, components.size(), std::make_shared<PathEls::PathData>(
+ strVals, components));
}
Q_ASSERT(false && "Unexpected state in Path::fromString");
return Path();
}
-Path Path::root(PathRoot s)
+Path Path::Root(PathRoot s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Root(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Root(s)))));
}
-Path Path::root(QString s)
+Path Path::Root(const QString &s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(s), QVector<Component>(1,Component(Root(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(s), QVector<Component>(1,Component(PathEls::Root(s)))));
}
-Path Path::index(index_type i)
+Path Path::Index(index_type i)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Index(i)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Index(i)))));
}
-Path Path::root(QStringView s)
+Path Path::Root(QStringView s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Root(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Root(s)))));
}
-Path Path::field(QStringView s)
+Path Path::Field(QStringView s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Field(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Field(s)))));
}
-Path Path::field(QString s)
+Path Path::Field(const QString &s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(s), QVector<Component>(1,Component(Field(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(s), QVector<Component>(1,Component(PathEls::Field(s)))));
}
-Path Path::key(QStringView s)
+Path Path::Key(QStringView s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Key(s)))));
+ return Path(
+ 0, 1,
+ std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1, Component(PathEls::Key(s.toString())))));
}
-Path Path::key(QString s)
+Path Path::Key(const QString &s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(s), QVector<Component>(1,Component(Key(s)))));
+ return Path(0, 1,
+ std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1, Component(PathEls::Key(s)))));
}
-Path Path::current(PathCurrent s)
+Path Path::Current(PathCurrent s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Current(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Current(s)))));
}
-Path Path::current(QString s)
+Path Path::Current(const QString &s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(s), QVector<Component>(1,Component(Current(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(s), QVector<Component>(1,Component(PathEls::Current(s)))));
}
-Path Path::current(QStringView s)
+Path Path::Current(QStringView s)
{
- return Path(0,1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Current(s)))));
+ return Path(0,1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Current(s)))));
}
-Path Path::empty()
+Path Path::Empty()
{
return Path();
}
-Path Path::subEmpty() const
+Path Path::empty() const
{
if (m_endOffset != 0)
- return noEndOffset().subEmpty();
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component()), m_data));
+ return noEndOffset().empty();
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component()), m_data));
}
-Path Path::subField(QString name) const
+Path Path::field(const QString &name) const
{
- auto res = subField(QStringView(name));
+ auto res = field(QStringView(name));
res.m_data->strData.append(name);
return res;
}
-Path Path::subField(QStringView name) const
+Path Path::field(QStringView name) const
{
if (m_endOffset != 0)
- return noEndOffset().subField(name);
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Field(name))), m_data));
+ return noEndOffset().field(name);
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Field(name))), m_data));
}
-Path Path::subKey(QString name) const
+Path Path::key(const QString &name) const
{
- auto res = subKey(QStringView(name));
- res.m_data->strData.append(name);
- return res;
+ if (m_endOffset != 0)
+ return noEndOffset().key(name);
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Key(name))), m_data));
}
-Path Path::subKey(QStringView name) const
+Path Path::key(QStringView name) const
{
- if (m_endOffset != 0)
- return noEndOffset().subKey(name);
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Key(name))), m_data));
+ return key(name.toString());
}
-Path Path::subIndex(index_type i) const
+Path Path::index(index_type i) const
{
if (m_endOffset != 0)
- return noEndOffset().subIndex(i);
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(i)), m_data));
+ return noEndOffset().index(i);
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(i)), m_data));
}
-Path Path::subAny() const
+Path Path::any() const
{
if (m_endOffset != 0)
- return noEndOffset().subAny();
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Any())), m_data));
+ return noEndOffset().any();
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Any())), m_data));
}
-Path Path::subFilter(function<bool (DomItem)> filter, QString desc) const
+Path Path::filter(const function<bool(const DomItem &)> &filterF, const QString &desc) const
{
- auto res = subFilter(filter, QStringView(desc));
+ auto res = filter(filterF, QStringView(desc));
res.m_data->strData.append(desc);
return res;
}
-Path Path::subFilter(function<bool (DomItem)> filter, QStringView desc) const
+Path Path::filter(const function<bool(const DomItem &)> &filter, QStringView desc) const
{
if (m_endOffset != 0)
- return noEndOffset().subFilter(filter, desc);
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Filter(filter, desc))), m_data));
+ return noEndOffset().filter(filter, desc);
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Filter(filter, desc))), m_data));
}
-Path Path::subCurrent(PathCurrent s) const
+Path Path::current(PathCurrent s) const
{
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Current(s))), m_data));
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Current(s))), m_data));
}
-Path Path::subCurrent(QString s) const
+Path Path::current(const QString &s) const
{
- auto res = subCurrent(QStringView(s));
+ auto res = current(QStringView(s));
res.m_data->strData.append(s);
return res;
}
-Path Path::subCurrent(QStringView s) const
+Path Path::current(QStringView s) const
{
if (m_endOffset != 0)
- return noEndOffset().subCurrent(s);
- return Path(0,m_length+1,std::make_shared<PathData>(QStringList(), QVector<Component>(1,Component(Current(s))), m_data));
+ return noEndOffset().current(s);
+ return Path(0,m_length+1,std::make_shared<PathEls::PathData>(
+ QStringList(), QVector<Component>(1,Component(PathEls::Current(s))), m_data));
}
-Path Path::subPath(Path toAdd, bool avoidToAddAsBase) const
+Path Path::path(const Path &toAdd, bool avoidToAddAsBase) const
{
if (toAdd.length() == 0)
return *this;
@@ -705,7 +697,7 @@ Path Path::subPath(Path toAdd, bool avoidToAddAsBase) const
if (resLength == thisExtended.length())
return thisExtended;
else
- return thisExtended.subPath(toAdd.mid(added.length(), resLength - thisExtended.length()));
+ return thisExtended.path(toAdd.mid(added.length(), resLength - thisExtended.length()));
}
}
if (!avoidToAddAsBase) {
@@ -737,9 +729,9 @@ Path Path::subPath(Path toAdd, bool avoidToAddAsBase) const
}
data = toAdd.m_data.get();
while (data) {
- for (int ij = 0; ij < data->strData.length(); ++ij) {
+ for (int ij = 0; ij < data->strData.size(); ++ij) {
bool hasAlready = false;
- for (int ii = 0; ii < myStrs.length() && !hasAlready; ++ii)
+ for (int ii = 0; ii < myStrs.size() && !hasAlready; ++ii)
hasAlready = inQString(data->strData[ij], myStrs[ii]);
if (!hasAlready)
addedStrs.append(data->strData[ij]);
@@ -752,7 +744,7 @@ Path Path::subPath(Path toAdd, bool avoidToAddAsBase) const
components.append(toAdd.component(i));
QStringView compStrView = toAdd.component(i).stringView();
if (!compStrView.isEmpty()) {
- for (int j = 0; j < addedStrs.length(); ++j) {
+ for (int j = 0; j < addedStrs.size(); ++j) {
if (inQString(compStrView, addedStrs[j])) {
toAddStrs.append(addedStrs[j]);
addedStrs.removeAt(j);
@@ -761,8 +753,8 @@ Path Path::subPath(Path toAdd, bool avoidToAddAsBase) const
}
}
}
- return Path(0, m_length + toAdd.length(),
- std::make_shared<PathData>(toAddStrs, components, ((m_endOffset == 0) ? m_data : noEndOffset().m_data)));
+ return Path(0, m_length + toAdd.length(), std::make_shared<PathEls::PathData>(
+ toAddStrs, components, ((m_endOffset == 0) ? m_data : noEndOffset().m_data)));
}
Path Path::expandFront() const
@@ -770,7 +762,7 @@ Path Path::expandFront() const
int newLen = 0;
auto data = m_data.get();
while (data) {
- newLen += data->components.length();
+ newLen += data->components.size();
data = data->parent.get();
}
newLen -= m_endOffset;
@@ -817,7 +809,7 @@ int Path::cmp(const Path &p1, const Path &p2)
return 0;
}
-Path::Path(quint16 endOffset, quint16 length, std::shared_ptr<PathData> data)
+Path::Path(quint16 endOffset, quint16 length, const std::shared_ptr<PathEls::PathData> &data)
:m_endOffset(endOffset), m_length(length), m_data(data)
{
}
@@ -830,29 +822,90 @@ Path Path::noEndOffset() const
return *this;
// peel back
qint16 endOffset = m_endOffset;
- std::shared_ptr<PathData> lastData = m_data;
- while (lastData && endOffset >= lastData->components.length()) {
- endOffset -= lastData->components.length();
+ std::shared_ptr<PathEls::PathData> lastData = m_data;
+ while (lastData && endOffset >= lastData->components.size()) {
+ endOffset -= lastData->components.size();
lastData = lastData->parent;
}
if (endOffset > 0) {
Q_ASSERT(lastData && "Internal problem, reference to non existing PathData");
- return Path(0, m_length, std::make_shared<PathData>(lastData->strData, lastData->components.mid(0, lastData->components.length() - endOffset), lastData->parent));
+ return Path(0, m_length, std::make_shared<PathEls::PathData>(
+ lastData->strData, lastData->components.mid(0, lastData->components.size() - endOffset), lastData->parent));
}
return Path(0, m_length, lastData);
}
+Path Path::appendComponent(const PathEls::PathComponent &c)
+{
+ if (m_endOffset != 0) {
+ Path newP = noEndOffset();
+ return newP.appendComponent(c);
+ }
+ if (m_data && m_data.use_count() != 1) {
+ // create a new path (otherwise paths linking to this will change)
+ Path newP(c);
+ newP.m_data->parent = m_data;
+ newP.m_length = static_cast<quint16>(m_length + 1);
+ return newP;
+ }
+ auto my_data =
+ (m_data ? m_data
+ : std::make_shared<PathEls::PathData>(QStringList(),
+ QVector<PathEls::PathComponent>()));
+ switch (c.kind()) {
+ case PathEls::Kind::Any:
+ case PathEls::Kind::Empty:
+ case PathEls::Kind::Index:
+ // no string
+ case PathEls::Kind::Field:
+ // string assumed to stay valid (Fields::...)
+ my_data->components.append(c);
+ break;
+ case PathEls::Kind::Current:
+ if (c.asCurrent()->contextKind == PathCurrent::Other) {
+ my_data->strData.append(c.asCurrent()->contextName.toString());
+ my_data->components.append(PathEls::Current(my_data->strData.last()));
+ } else {
+ my_data->components.append(c);
+ }
+ break;
+ case PathEls::Kind::Filter:
+ if (!c.asFilter()->filterDescription.isEmpty()) {
+ my_data->strData.append(c.asFilter()->filterDescription.toString());
+ my_data->components.append(
+ PathEls::Filter(c.asFilter()->filterFunction, my_data->strData.last()));
+ } else {
+ my_data->components.append(c);
+ }
+ break;
+ case PathEls::Kind::Key:
+ my_data->components.append(c);
+ break;
+ case PathEls::Kind::Root:
+ if (c.asRoot()->contextKind == PathRoot::Other) {
+ my_data->strData.append(c.asRoot()->contextName.toString());
+ my_data->components.append(PathEls::Root(my_data->strData.last()));
+ } else {
+ my_data->components.append(c);
+ }
+ break;
+ }
+ if (m_data)
+ m_endOffset = 1;
+ return Path { 0, static_cast<quint16>(m_length + 1), my_data };
+}
+
ErrorGroups Path::myErrors()
{
static ErrorGroups res = {{NewErrorGroup("PathParsing")}};
return res;
}
-void Path::dump(Sink sink) const
+void Path::dump(const Sink &sink) const
{
bool first = true;
for (int i = 0; i < m_length; ++i) {
- auto c = component(i);
+ auto &c = component(i);
if (!c.hasSquareBrackets()) {
if (!first || (c.kind() != Kind::Root && c.kind() != Kind::Current))
sink(u".");
@@ -871,17 +924,17 @@ QString Path::toString() const
return res;
}
-Path Path::dropFront() const
+Path Path::dropFront(int n) const
{
- if (m_length > 0)
- return Path(m_endOffset, m_length - 1, m_data);
+ if (m_length > n && n >= 0)
+ return Path(m_endOffset, m_length - n, m_data);
return Path();
}
-Path Path::dropTail() const
+Path Path::dropTail(int n) const
{
- if (m_length > 0)
- return Path(m_endOffset + 1, m_length - 1, m_data);
+ if (m_length > n && n >= 0)
+ return Path(m_endOffset + n, m_length - n, m_data);
return Path();
}
@@ -899,7 +952,7 @@ Path Path::mid(int offset) const
return mid(offset, m_length - offset);
}
-Path Path::fromString(QString s, ErrorHandler errorHandler)
+Path Path::fromString(const QString &s, const ErrorHandler &errorHandler)
{
Path res = fromString(QStringView(s), errorHandler);
if (res.m_data)
@@ -910,3 +963,5 @@ Path Path::fromString(QString s, ErrorHandler errorHandler)
} // end namespace Dom
} // end namespace QQmlJS
QT_END_NAMESPACE
+
+#include "moc_qqmldompath_p.cpp"