1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlpreviewblacklist.h"
5
6QT_BEGIN_NAMESPACE
7
8void QQmlPreviewBlacklist::blacklist(const QString &path)
9{
10 if (!path.isEmpty())
11 m_root.insert(path, offset: 0);
12}
13
14void QQmlPreviewBlacklist::whitelist(const QString &path)
15{
16 if (!path.isEmpty())
17 m_root.remove(path, offset: 0);
18}
19
20bool QQmlPreviewBlacklist::isBlacklisted(const QString &path) const
21{
22 return path.isEmpty() ? true : m_root.containedPrefixLeaf(path, offset: 0) > 0;
23}
24
25void QQmlPreviewBlacklist::clear()
26{
27 m_root = Node();
28}
29
30QQmlPreviewBlacklist::Node::Node()
31{
32}
33
34QQmlPreviewBlacklist::Node::Node(const QQmlPreviewBlacklist::Node &other) :
35 m_mine(other.m_mine), m_isLeaf(other.m_isLeaf)
36{
37 for (auto it = other.m_next.begin(), end = other.m_next.end(); it != end; ++it)
38 m_next.insert(key: it.key(), value: new Node(**it));
39}
40
41QQmlPreviewBlacklist::Node::Node(QQmlPreviewBlacklist::Node &&other) noexcept
42{
43 m_mine.swap(other&: other.m_mine);
44 m_next.swap(other&: other.m_next);
45 m_isLeaf = other.m_isLeaf;
46}
47
48QQmlPreviewBlacklist::Node::~Node()
49{
50 qDeleteAll(c: m_next);
51}
52
53QQmlPreviewBlacklist::Node &QQmlPreviewBlacklist::Node::operator=(
54 const QQmlPreviewBlacklist::Node &other)
55{
56 if (&other != this) {
57 m_mine = other.m_mine;
58 for (auto it = other.m_next.begin(), end = other.m_next.end(); it != end; ++it)
59 m_next.insert(key: it.key(), value: new Node(**it));
60 m_isLeaf = other.m_isLeaf;
61 }
62 return *this;
63}
64
65QQmlPreviewBlacklist::Node &QQmlPreviewBlacklist::Node::operator=(
66 QQmlPreviewBlacklist::Node &&other) noexcept
67{
68 if (&other != this) {
69 m_mine.swap(other&: other.m_mine);
70 m_next.swap(other&: other.m_next);
71 m_isLeaf = other.m_isLeaf;
72 }
73 return *this;
74}
75
76void QQmlPreviewBlacklist::Node::split(QString::iterator it, QString::iterator end)
77{
78 QString existing;
79 existing.resize(size: end - it - 1);
80 std::copy(first: it + 1, last: end, result: existing.begin());
81
82 Node *node = new Node(existing, m_next, m_isLeaf);
83 m_next.clear();
84 m_next.insert(key: *it, value: node);
85 m_mine.resize(size: it - m_mine.begin());
86 m_isLeaf = false;
87}
88
89void QQmlPreviewBlacklist::Node::insert(const QString &path, int offset)
90{
91 for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
92 if (offset == path.size()) {
93 split(it, end);
94 m_isLeaf = true;
95 return;
96 }
97
98 if (path.at(i: offset) != *it) {
99 split(it, end);
100
101 QString inserted;
102 inserted.resize(size: path.size() - offset - 1);
103 std::copy(first: path.begin() + offset + 1, last: path.end(), result: inserted.begin());
104 m_next.insert(key: path.at(i: offset), value: new Node(inserted));
105 return;
106 }
107
108 ++offset;
109 }
110
111 if (offset == path.size()) {
112 m_isLeaf = true;
113 return;
114 }
115
116 Node *&node = m_next[path.at(i: offset++)];
117 if (node == nullptr) {
118 QString inserted;
119 inserted.resize(size: path.size() - offset);
120 std::copy(first: path.begin() + offset, last: path.end(), result: inserted.begin());
121 node = new Node(inserted);
122 } else {
123 node->insert(path, offset);
124 }
125}
126
127void QQmlPreviewBlacklist::Node::remove(const QString &path, int offset)
128{
129 for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
130 if (offset == path.size() || path.at(i: offset) != *it) {
131 split(it, end);
132 return;
133 }
134 ++offset;
135 }
136
137 m_isLeaf = false;
138 if (offset == path.size())
139 return;
140
141 auto it = m_next.find(key: path.at(i: offset));
142 if (it != m_next.end())
143 (*it)->remove(path, offset: ++offset);
144}
145
146int QQmlPreviewBlacklist::Node::containedPrefixLeaf(const QString &path, int offset) const
147{
148 if (offset == path.size())
149 return (m_mine.isEmpty() && m_isLeaf) ? offset : -1;
150
151 for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
152 if (path.at(i: offset) != *it)
153 return -1;
154
155 if (++offset == path.size())
156 return (++it == end && m_isLeaf) ? offset : -1;
157 }
158
159 const QChar c = path.at(i: offset);
160 if (m_isLeaf && c == '/')
161 return offset;
162
163 auto it = m_next.find(key: c);
164 if (it == m_next.end())
165 return -1;
166
167 return (*it)->containedPrefixLeaf(path, offset: ++offset);
168}
169
170QQmlPreviewBlacklist::Node::Node(const QString &mine,
171 const QHash<QChar, QQmlPreviewBlacklist::Node *> &next,
172 bool isLeaf)
173 : m_mine(mine), m_next(next), m_isLeaf(isLeaf)
174{
175}
176
177QT_END_NAMESPACE
178

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.cpp