Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
inlinecomponentutils_p.h
Go to the documentation of this file.
1// Copyright (C) 2020 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#ifndef INLINECOMPONENTUTILS_P_H
4#define INLINECOMPONENTUTILS_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <private/qqmlmetatype_p.h>
18#include <private/qv4compileddata_p.h>
19#include <private/qv4resolvedtypereference_p.h>
20
22
23namespace icutils {
24struct Node {
25private:
26 using IndexType = std::vector<QV4::CompiledData::InlineComponent>::size_type;
27 using IndexField = quint32_le_bitfield_member<0, 30, IndexType>;
28 using TemporaryMarkField = quint32_le_bitfield_member<30, 1>;
29 using PermanentMarkField = quint32_le_bitfield_member<31, 1>;
30 quint32_le_bitfield_union<IndexField, TemporaryMarkField, PermanentMarkField> m_data;
31
32public:
33 Node() = default;
34 Node(const Node &) = default;
35 Node(Node &&) = default;
36 Node& operator=(Node const &) = default;
37 Node& operator=(Node &&) = default;
38 bool operator==(Node const &other) const {return m_data.data() == other.m_data.data(); }
39
40 Node(IndexType s) : m_data(QSpecialIntegerBitfieldZero) { m_data.set<IndexField>(s); }
41
42 bool hasPermanentMark() const { return m_data.get<PermanentMarkField>(); }
43 bool hasTemporaryMark() const { return m_data.get<TemporaryMarkField>(); }
44
46 {
47 m_data.set<TemporaryMarkField>(0);
48 m_data.set<PermanentMarkField>(1);
49 }
50
52 {
53 m_data.set<TemporaryMarkField>(1);
54 }
55
56 IndexType index() const { return m_data.get<IndexField>(); }
57};
58
59using NodeList = std::vector<Node>;
60using AdjacencyList = std::vector<std::vector<Node*>>;
61
62inline bool containedInSameType(const QQmlType &a, const QQmlType &b)
63{
64 return QQmlMetaType::equalBaseUrls(a.sourceUrl(), b.sourceUrl());
65}
66
67template<typename ObjectContainer, typename InlineComponent>
68void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer,
69 AdjacencyList &adjacencyList, NodeList &nodes,
70 const std::vector<InlineComponent> &allICs)
71{
72 using CompiledObject = typename ObjectContainer::CompiledObject;
73 // add an edge from A to B if A and B are inline components with the same containing type
74 // and A inherits from B (ignore indirect chains through external types for now)
75 // or if A instantiates B
76 for (typename std::vector<InlineComponent>::size_type i = 0; i < allICs.size(); ++i) {
77 const auto& ic = allICs[i];
78 const CompiledObject *obj = objectContainer->objectAt(ic.objectIndex);
79 QV4::ResolvedTypeReference *currentICTypeRef = objectContainer->resolvedType(ic.nameIndex);
80 auto createEdgeFromTypeRef = [&](QV4::ResolvedTypeReference *targetTypeRef) {
81 if (targetTypeRef) {
82 const auto targetType = targetTypeRef->type();
83 if (targetType.isInlineComponentType()
84 && containedInSameType(targetType, currentICTypeRef->type())) {
85 auto icIt = std::find_if(allICs.cbegin(), allICs.cend(), [&](const QV4::CompiledData::InlineComponent &icSearched){
86 return objectContainer->stringAt(icSearched.nameIndex)
87 == targetType.elementName();
88 });
89 Q_ASSERT(icIt != allICs.cend());
90 Node& target = nodes[i];
91 adjacencyList[std::distance(allICs.cbegin(), icIt)].push_back(&target);
92 }
93 }
94 };
95 if (obj->inheritedTypeNameIndex != 0) {
96 QV4::ResolvedTypeReference *parentTypeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
97 createEdgeFromTypeRef(parentTypeRef);
98
99 }
100 auto referencedInICObjectIndex = ic.objectIndex + 1;
101 while (int(referencedInICObjectIndex) < objectContainer->objectCount()) {
102 auto potentiallyReferencedInICObject = objectContainer->objectAt(referencedInICObjectIndex);
103 bool stillInIC
104 = !potentiallyReferencedInICObject->hasFlag(
106 && potentiallyReferencedInICObject->hasFlag(
108 if (!stillInIC)
109 break;
110 createEdgeFromTypeRef(objectContainer->resolvedType(potentiallyReferencedInICObject->inheritedTypeNameIndex));
111 ++referencedInICObjectIndex;
112 }
113 }
114};
115
116inline void topoVisit(Node *node, AdjacencyList &adjacencyList, bool &hasCycle,
117 NodeList &nodesSorted)
118{
119 if (node->hasPermanentMark())
120 return;
121 if (node->hasTemporaryMark()) {
122 hasCycle = true;
123 return;
124 }
125 node->setTemporaryMark();
126
127 auto const &edges = adjacencyList[node->index()];
128 for (auto edgeTarget =edges.begin(); edgeTarget != edges.end(); ++edgeTarget) {
129 topoVisit(*edgeTarget, adjacencyList, hasCycle, nodesSorted);
130 }
131
132 node->setPermanentMark();
133 nodesSorted.push_back(*node);
134};
135
136// Use DFS based topological sorting (https://en.wikipedia.org/wiki/Topological_sorting)
137inline NodeList topoSort(NodeList &nodes, AdjacencyList &adjacencyList, bool &hasCycle)
138{
139 NodeList nodesSorted;
140 nodesSorted.reserve(nodes.size());
141
142 hasCycle = false;
143 auto currentNodeIt = std::find_if(nodes.begin(), nodes.end(), [](const Node& node) {
144 return !node.hasPermanentMark();
145 });
146 // Do a topological sort of all inline components
147 // afterwards, nodesSorted contains the nodes for the inline components in reverse topological order
148 while (currentNodeIt != nodes.end() && !hasCycle) {
149 Node& currentNode = *currentNodeIt;
150 topoVisit(&currentNode, adjacencyList, hasCycle, nodesSorted);
151 currentNodeIt = std::find_if(nodes.begin(), nodes.end(), [](const Node& node) {
152 return !node.hasPermanentMark();
153 });
154 }
155 return nodesSorted;
156}
157}
158
160
161#endif // INLINECOMPONENTUTILS_P_H
NSData * m_data
static bool equalBaseUrls(const QUrl &aUrl, const QUrl &bUrl)
Combined button and popup list for selecting options.
NodeList topoSort(NodeList &nodes, AdjacencyList &adjacencyList, bool &hasCycle)
std::vector< Node > NodeList
void topoVisit(Node *node, AdjacencyList &adjacencyList, bool &hasCycle, NodeList &nodesSorted)
void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, AdjacencyList &adjacencyList, NodeList &nodes, const std::vector< InlineComponent > &allICs)
std::vector< std::vector< Node * > > AdjacencyList
bool containedInSameType(const QQmlType &a, const QQmlType &b)
constexpr QSpecialIntegerBitfieldInitializer QSpecialIntegerBitfieldZero
Definition qendian_p.h:24
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum target
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QSharedPointer< T > other(t)
[5]
Node(Node &&)=default
Node(const Node &)=default
Node & operator=(Node const &)=default
Node()=default
IndexType index() const
bool hasTemporaryMark() const
bool operator==(Node const &other) const
bool hasPermanentMark() const
Node & operator=(Node &&)=default