Qt 6.x
The Qt SDK
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/qv4compileddata_p.h>
18#include <private/qv4resolvedtypereference_p.h>
19
21
22namespace icutils {
23struct Node {
24private:
25 using IndexType = std::vector<QV4::CompiledData::InlineComponent>::size_type;
30
31public:
32 Node() = default;
33 Node(const Node &) = default;
34 Node(Node &&) = default;
35 Node& operator=(Node const &) = default;
36 Node& operator=(Node &&) = default;
37 bool operator==(Node const &other) const {return m_data.data() == other.m_data.data(); }
38
40
41 bool hasPermanentMark() const { return m_data.get<PermanentMarkField>(); }
42 bool hasTemporaryMark() const { return m_data.get<TemporaryMarkField>(); }
43
45 {
48 }
49
51 {
53 }
54
55 IndexType index() const { return m_data.get<IndexField>(); }
56};
57
58using NodeList = std::vector<Node>;
59using AdjacencyList = std::vector<std::vector<Node*>>;
60
61inline bool containedInSameType(const QQmlType &a, const QQmlType &b)
62{
63 return QQmlMetaType::equalBaseUrls(a.sourceUrl(), b.sourceUrl());
64}
65
66template<typename ObjectContainer, typename InlineComponent>
67void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer,
68 AdjacencyList &adjacencyList, NodeList &nodes,
69 const std::vector<InlineComponent> &allICs)
70{
71 using CompiledObject = typename ObjectContainer::CompiledObject;
72 // add an edge from A to B if A and B are inline components with the same containing type
73 // and A inherits from B (ignore indirect chains through external types for now)
74 // or if A instantiates B
75 for (typename std::vector<InlineComponent>::size_type i = 0; i < allICs.size(); ++i) {
76 const auto& ic = allICs[i];
77 const CompiledObject *obj = objectContainer->objectAt(ic.objectIndex);
78 QV4::ResolvedTypeReference *currentICTypeRef = objectContainer->resolvedType(ic.nameIndex);
79 auto createEdgeFromTypeRef = [&](QV4::ResolvedTypeReference *targetTypeRef) {
80 if (targetTypeRef) {
81 const auto targetType = targetTypeRef->type();
82 if (targetType.isInlineComponentType()
83 && containedInSameType(targetType, currentICTypeRef->type())) {
84 auto icIt = std::find_if(allICs.cbegin(), allICs.cend(), [&](const QV4::CompiledData::InlineComponent &icSearched){
85 return objectContainer->stringAt(icSearched.nameIndex)
86 == targetType.elementName();
87 });
88 Q_ASSERT(icIt != allICs.cend());
89 Node& target = nodes[i];
90 adjacencyList[std::distance(allICs.cbegin(), icIt)].push_back(&target);
91 }
92 }
93 };
94 if (obj->inheritedTypeNameIndex != 0) {
95 QV4::ResolvedTypeReference *parentTypeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
96 createEdgeFromTypeRef(parentTypeRef);
97
98 }
99 auto referencedInICObjectIndex = ic.objectIndex + 1;
100 while (int(referencedInICObjectIndex) < objectContainer->objectCount()) {
101 auto potentiallyReferencedInICObject = objectContainer->objectAt(referencedInICObjectIndex);
102 bool stillInIC
103 = !potentiallyReferencedInICObject->hasFlag(
105 && potentiallyReferencedInICObject->hasFlag(
107 if (!stillInIC)
108 break;
109 createEdgeFromTypeRef(objectContainer->resolvedType(potentiallyReferencedInICObject->inheritedTypeNameIndex));
110 ++referencedInICObjectIndex;
111 }
112 }
113};
114
115inline void topoVisit(Node *node, AdjacencyList &adjacencyList, bool &hasCycle,
116 NodeList &nodesSorted)
117{
118 if (node->hasPermanentMark())
119 return;
120 if (node->hasTemporaryMark()) {
121 hasCycle = true;
122 return;
123 }
124 node->setTemporaryMark();
125
126 auto const &edges = adjacencyList[node->index()];
127 for (auto edgeTarget =edges.begin(); edgeTarget != edges.end(); ++edgeTarget) {
128 topoVisit(*edgeTarget, adjacencyList, hasCycle, nodesSorted);
129 }
130
131 node->setPermanentMark();
132 nodesSorted.push_back(*node);
133};
134
135// Use DFS based topological sorting (https://en.wikipedia.org/wiki/Topological_sorting)
136inline NodeList topoSort(NodeList &nodes, AdjacencyList &adjacencyList, bool &hasCycle)
137{
138 NodeList nodesSorted;
139 nodesSorted.reserve(nodes.size());
140
141 hasCycle = false;
142 auto currentNodeIt = std::find_if(nodes.begin(), nodes.end(), [](const Node& node) {
143 return !node.hasPermanentMark();
144 });
145 // Do a topological sort of all inline components
146 // afterwards, nodesSorted contains the nodes for the inline components in reverse topological order
147 while (currentNodeIt != nodes.end() && !hasCycle) {
148 Node& currentNode = *currentNodeIt;
149 topoVisit(&currentNode, adjacencyList, hasCycle, nodesSorted);
150 currentNodeIt = std::find_if(nodes.begin(), nodes.end(), [](const Node& node) {
151 return !node.hasPermanentMark();
152 });
153 }
154 return nodesSorted;
155}
156}
157
159
160#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)
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
std::vector< Node > NodeList
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