1// Copyright (C) 2019 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#ifndef QQMLPROPERTYCACHEVECTOR_P_H
5#define QQMLPROPERTYCACHEVECTOR_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qqmlpropertycache_p.h>
19#include <private/qbipointer_p.h>
20
21#include <QtCore/qtaggedpointer.h>
22
23QT_BEGIN_NAMESPACE
24
25class QQmlPropertyCacheVector
26{
27public:
28 QQmlPropertyCacheVector() = default;
29 QQmlPropertyCacheVector(QQmlPropertyCacheVector &&) = default;
30 QQmlPropertyCacheVector &operator=(QQmlPropertyCacheVector &&) = default;
31
32 ~QQmlPropertyCacheVector() { clear(); }
33 void resize(int size)
34 {
35 Q_ASSERT(size >= data.size());
36 return data.resize(size);
37 }
38
39 int count() const {
40 // the property cache vector will never contain more thant INT_MAX many elements
41 return int(data.size());
42 }
43 void clear()
44 {
45 for (int i = 0; i < data.size(); ++i)
46 releaseElement(i);
47 data.clear();
48 }
49
50 void resetAndResize(int size)
51 {
52 for (int i = 0; i < data.size(); ++i) {
53 releaseElement(i);
54 data[i] = BiPointer();
55 }
56 data.resize(size);
57 }
58
59 void append(const QQmlPropertyCache::ConstPtr &cache) {
60 cache->addref();
61 data.append(t: BiPointer(cache.data()));
62 Q_ASSERT(data.last().isT1());
63 Q_ASSERT(data.size() <= std::numeric_limits<int>::max());
64 }
65
66 void appendOwn(const QQmlPropertyCache::Ptr &cache) {
67 cache->addref();
68 data.append(t: BiPointer(cache.data()));
69 Q_ASSERT(data.last().isT2());
70 Q_ASSERT(data.size() <= std::numeric_limits<int>::max());
71 }
72
73 QQmlPropertyCache::ConstPtr at(int index) const
74 {
75 const auto entry = data.at(i: index);
76 if (entry.isT2())
77 return entry.asT2();
78 return entry.asT1();
79 }
80
81 QQmlPropertyCache::Ptr ownAt(int index) const
82 {
83 const auto entry = data.at(i: index);
84 if (entry.isT2())
85 return entry.asT2();
86 return QQmlPropertyCache::Ptr();
87 }
88
89 void set(int index, const QQmlPropertyCache::ConstPtr &replacement) {
90 if (QQmlPropertyCache::ConstPtr oldCache = at(index)) {
91 // If it is our own, we keep it our own
92 if (replacement.data() == oldCache.data())
93 return;
94 oldCache->release();
95 }
96 data[index] = replacement.data();
97 replacement->addref();
98 Q_ASSERT(data[index].isT1());
99 }
100
101 void setOwn(int index, const QQmlPropertyCache::Ptr &replacement) {
102 if (QQmlPropertyCache::ConstPtr oldCache = at(index)) {
103 if (replacement.data() != oldCache.data()) {
104 oldCache->release();
105 replacement->addref();
106 }
107 } else {
108 replacement->addref();
109 }
110 data[index] = replacement.data();
111 Q_ASSERT(data[index].isT2());
112 }
113
114 void setNeedsVMEMetaObject(int index) { data[index].setFlag(); }
115 bool needsVMEMetaObject(int index) const { return data.at(i: index).flag(); }
116
117 void seal()
118 {
119 for (auto &entry: data) {
120 if (entry.isT2())
121 entry = static_cast<const QQmlPropertyCache *>(entry.asT2());
122 Q_ASSERT(entry.isT1());
123 }
124 }
125
126private:
127 void releaseElement(int i)
128 {
129 const auto &cache = data.at(i);
130 if (cache.isT2()) {
131 if (QQmlPropertyCache *data = cache.asT2())
132 data->release();
133 } else if (const QQmlPropertyCache *data = cache.asT1()) {
134 data->release();
135 }
136 }
137
138 Q_DISABLE_COPY(QQmlPropertyCacheVector)
139 using BiPointer = QBiPointer<const QQmlPropertyCache, QQmlPropertyCache>;
140 QVector<BiPointer> data;
141};
142
143QT_END_NAMESPACE
144
145#endif // QQMLPROPERTYCACHEVECTOR_P_H
146

source code of qtdeclarative/src/qml/qml/qqmlpropertycachevector_p.h