Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4sparsearray_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant
4
5#ifndef QV4SPARSEARRAY_H
6#define QV4SPARSEARRAY_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "qv4global_p.h"
20#include "qv4value_p.h"
21#include <QtCore/qlist.h>
22
23//#define Q_MAP_DEBUG
24#ifdef Q_MAP_DEBUG
25#include <QtCore/qdebug.h>
26#endif
27
28#include <new>
29
30QT_BEGIN_NAMESPACE
31
32namespace QV4 {
33
34struct SparseArray;
35
37{
42 uint value;
43
44 enum Color { Red = 0, Black = 1 };
45 enum { Mask = 3 }; // reserve the second bit as well
46
47 const SparseArrayNode *nextNode() const;
48 SparseArrayNode *nextNode() { return const_cast<SparseArrayNode *>(const_cast<const SparseArrayNode *>(this)->nextNode()); }
49 const SparseArrayNode *previousNode() const;
50 SparseArrayNode *previousNode() { return const_cast<SparseArrayNode *>(const_cast<const SparseArrayNode *>(this)->previousNode()); }
51
52 Color color() const { return Color(p & 1); }
53 void setColor(Color c) { if (c == Black) p |= Black; else p &= ~Black; }
54 SparseArrayNode *parent() const { return reinterpret_cast<SparseArrayNode *>(p & ~Mask); }
55 void setParent(SparseArrayNode *pp) { p = (p & Mask) | quintptr(pp); }
56
57 uint key() const {
58 uint k = size_left;
59 const SparseArrayNode *n = this;
60 while (SparseArrayNode *p = n->parent()) {
61 if (p && p->right == n)
62 k += p->size_left;
63 n = p;
64 }
65 return k;
66 }
67
68 SparseArrayNode *copy(SparseArray *d) const;
69
70 SparseArrayNode *lowerBound(uint key);
71 SparseArrayNode *upperBound(uint key);
72};
73
74
76{
77 SparseArrayNode *n = this;
78 SparseArrayNode *last = nullptr;
79 while (n) {
80 if (akey <= n->size_left) {
81 last = n;
82 n = n->left;
83 } else {
84 akey -= n->size_left;
85 n = n->right;
86 }
87 }
88 return last;
89}
90
91
93{
94 SparseArrayNode *n = this;
95 SparseArrayNode *last = nullptr;
96 while (n) {
97 if (akey < n->size_left) {
98 last = n;
99 n = n->left;
100 } else {
101 akey -= n->size_left;
102 n = n->right;
103 }
104 }
105 return last;
106}
107
108
109
110struct Q_QML_EXPORT SparseArray
111{
112 SparseArray();
114 if (SparseArrayNode *n = root())
115 freeTree(n, alignof(SparseArrayNode));
116 }
117
119
120 Value freeList;
121private:
123
124 int numEntries;
125 SparseArrayNode header;
126 SparseArrayNode *mostLeftNode;
127
128 void rotateLeft(SparseArrayNode *x);
129 void rotateRight(SparseArrayNode *x);
130 void rebalance(SparseArrayNode *x);
131 void recalcMostLeftNode();
132
133 SparseArrayNode *root() const { return header.left; }
134
135 void deleteNode(SparseArrayNode *z);
136
137
138public:
140 void freeTree(SparseArrayNode *root, int alignment);
141
142 SparseArrayNode *findNode(uint akey) const;
143
144 uint nEntries() const { return numEntries; }
145
146 uint pop_front();
147 void push_front(uint at);
148 uint pop_back(uint len);
149 void push_back(uint at, uint len);
150
151 QList<int> keys() const;
152
153 const SparseArrayNode *end() const { return &header; }
154 SparseArrayNode *end() { return &header; }
155 const SparseArrayNode *begin() const { if (root()) return mostLeftNode; return end(); }
156 SparseArrayNode *begin() { if (root()) return mostLeftNode; return end(); }
157
159
160 SparseArrayNode *lowerBound(uint key);
161 const SparseArrayNode *lowerBound(uint key) const;
162 SparseArrayNode *upperBound(uint key);
163 const SparseArrayNode *upperBound(uint key) const;
164 SparseArrayNode *insert(uint akey);
165
166 // STL compatibility
167 typedef uint key_type;
168 typedef int mapped_type;
170 typedef int size_type;
171
172#ifdef Q_MAP_DEBUG
173 void dump() const;
174#endif
175};
176
177inline SparseArrayNode *SparseArray::findNode(uint akey) const
178{
179 SparseArrayNode *n = root();
180
181 while (n) {
182 if (akey == n->size_left) {
183 return n;
184 } else if (akey < n->size_left) {
185 n = n->left;
186 } else {
187 akey -= n->size_left;
188 n = n->right;
189 }
190 }
191
192 return nullptr;
193}
194
195inline uint SparseArray::pop_front()
196{
197 uint idx = UINT_MAX ;
198
199 SparseArrayNode *n = findNode(0);
200 if (n) {
201 idx = n->value;
202 deleteNode(n);
203 // adjust all size_left indices on the path to leftmost item by 1
204 SparseArrayNode *rootNode = root();
205 while (rootNode) {
206 rootNode->size_left -= 1;
207 rootNode = rootNode->left;
208 }
209 }
210 return idx;
211}
212
213inline void SparseArray::push_front(uint value)
214{
215 // adjust all size_left indices on the path to leftmost item by 1
216 SparseArrayNode *n = root();
217 while (n) {
218 n->size_left += 1;
219 n = n->left;
220 }
221 n = insert(0);
222 n->value = value;
223}
224
225inline uint SparseArray::pop_back(uint len)
226{
227 uint idx = UINT_MAX;
228 if (!len)
229 return idx;
230
231 SparseArrayNode *n = findNode(len - 1);
232 if (n) {
233 idx = n->value;
234 deleteNode(n);
235 }
236 return idx;
237}
238
239inline void SparseArray::push_back(uint index, uint len)
240{
241 SparseArrayNode *n = insert(len);
242 n->value = index;
243}
244
245#ifdef Q_MAP_DEBUG
246inline void SparseArray::dump() const
247{
248 const SparseArrayNode *it = begin();
249 qDebug() << "map dump:";
250 while (it != end()) {
251 const SparseArrayNode *n = it;
252 int depth = 0;
253 while (n && n != root()) {
254 ++depth;
255 n = n->parent();
256 }
257 QByteArray space(4*depth, ' ');
258 qDebug() << space << (it->color() == SparseArrayNode::Red ? "Red " : "Black") << it << it->size_left << it->left << it->right
259 << it->key() << it->value;
260 it = it->nextNode();
261 }
262 qDebug() << "---------";
263}
264#endif
265
266
267inline SparseArrayNode *SparseArray::erase(SparseArrayNode *n)
268{
269 if (n == end())
270 return n;
271
272 SparseArrayNode *next = n->nextNode();
273 deleteNode(n);
274 return next;
275}
276
277inline QList<int> SparseArray::keys() const
278{
279 QList<int> res;
280 res.reserve(numEntries);
281 SparseArrayNode *n = mostLeftNode;
282 while (n != end()) {
283 res.append(n->key());
284 n = n->nextNode();
285 }
286 return res;
287}
288
289inline const SparseArrayNode *SparseArray::lowerBound(uint akey) const
290{
291 if (SparseArrayNode *n = root()) {
292 if (const SparseArrayNode *lb = n->lowerBound(akey))
293 return lb;
294 }
295
296 return end();
297}
298
299
300inline SparseArrayNode *SparseArray::lowerBound(uint akey)
301{
302 if (SparseArrayNode *n = root()) {
303 if (SparseArrayNode *lb = n->lowerBound(akey))
304 return lb;
305 }
306
307 return end();
308}
309
310
311inline const SparseArrayNode *SparseArray::upperBound(uint akey) const
312{
313 if (SparseArrayNode *n = root()) {
314 if (const SparseArrayNode *ub = n->upperBound(akey))
315 return ub;
316 }
317
318 return end();
319}
320
321
322inline SparseArrayNode *SparseArray::upperBound(uint akey)
323{
324 if (SparseArrayNode *n = root()) {
325 if (SparseArrayNode *ub = n->upperBound(akey))
326 return ub;
327 }
328
329 return end();
330}
331
332}
333
334QT_END_NAMESPACE
335
336#endif
ArrayElementLessThan(ExecutionEngine *engine, const Value &comparefn)
bool operator()(Value v1, Value v2) const
ReturnedValue operator*() const
Definition qv4value_p.h:477
OptionalReturnedValue(ReturnedValue v)
Definition qv4value_p.h:470
ReturnedValue operator->() const
Definition qv4value_p.h:476
DECLARE_HEAP_OBJECT(StrictArgumentsObject, Object)
DECLARE_EXPORTED_HEAP_OBJECT(Object, Base)
Definition qv4object_p.h:37
DECLARE_HEAP_OBJECT(ArgumentsObject, Object)
DECLARE_HEAP_OBJECT(MemberData, Base)
DECLARE_HEAP_OBJECT(ArrayData, Base)
Q_STATIC_ASSERT(std::is_trivial_v< ArrayData >)
CallResultDestination
Definition qjsvalue.h:23
Value Primitive
Definition qv4value_p.h:351
Scoped< FunctionObject > ScopedFunctionObject
void sortHelper(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
QVector< StackFrame > StackTrace
int qYouForgotTheQ_MANAGED_Macro(T, T)
Scoped< Object > ScopedObject
ReturnedValue value_convert(ExecutionEngine *e, const Value &v)
Scoped< ArrayObject > ScopedArrayObject
Scoped< String > ScopedString
Scoped< StringOrSymbol > ScopedStringOrSymbol
void qYouForgotTheQ_MANAGED_Macro(T1, T2)
PropertyFlag
@ Attr_Invalid
@ Attr_NotConfigurable
@ Attr_Data
@ Attr_NotEnumerable
@ Attr_ReadOnly
@ Attr_NotWritable
@ Attr_ReadOnly_ButConfigurable
@ Attr_Accessor
Q_STATIC_ASSERT(sizeof(CppStackFrame)==sizeof(JSTypesStackFrame))
Scoped< ExecutionContext > ScopedContext
Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_RELOCATABLE_TYPE)
DEFINE_OBJECT_VTABLE(StrictArgumentsObject)
DEFINE_OBJECT_VTABLE(ArgumentsObject)
#define V4_ARRAYDATA(DataClass)
#define V4_MANAGED(DataClass, superClass)
#define V4_MANAGED_SIZE_TEST
#define V4_NEEDS_DESTROY
#define V4_MANAGED_ITSELF(DataClass, superClass)
#define Q_MANAGED_TYPE(type)
#define V4_INTERNALCLASS(c)
#define Q_MANAGED_CHECK
static qint64 virtualGetLength(const Managed *m)
static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *desc, PropertyAttributes attrs)
Heap::CallContext * context() const
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
static OwnPropertyKeyIterator * virtualOwnPropertyKeys(const Object *m, Value *target)
static bool isNonStrictArgumentsObject(Managed *m)
static bool virtualDeleteProperty(Managed *m, PropertyKey id)
static PropertyAttributes virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
bool isMapped(uint arg) const
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
static qint64 virtualGetLength(const Managed *m)
QStringList toQStringList() const
void(* setAttribute)(Object *o, uint index, PropertyAttributes attrs)
bool(* putArray)(Object *o, uint index, const Value *values, uint n)
bool(* put)(Object *o, uint index, const Value &value)
void(* push_front)(Object *o, const Value *values, uint n)
ReturnedValue(* get)(const Heap::ArrayData *d, uint index)
bool(* del)(Object *o, uint index)
ReturnedValue(* pop_front)(Object *o)
static constexpr size_t offset
Definition qv4value_p.h:408
void set(EngineBase *e, HeapBasePtr b)
Definition qv4value_p.h:418
HeapBasePtr base()
Definition qv4value_p.h:409
void set(EngineBase *e, const Value &newVal)
Definition qv4value_p.h:415
void init(const QStringList &list)
void init(double val)
PropertyAttributes attributes(uint i) const
uint mappedIndex(uint index) const
void setData(EngineBase *e, uint index, Value newVal)
const Value & data(uint index) const
uint mappedIndex(uint index) const
PropertyAttributes attributes(uint i) const
static Heap::MemberData * allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old=nullptr)
const Value * data() const
void set(EngineBase *e, uint index, Value v)
const Value & operator[](uint idx) const
void set(EngineBase *e, uint index, Heap::Base *b)
uint size() const
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
const Value * operator->() const
bool isNull() const
const Value & operator*() const
void set(EngineBase *e, Value newVal)
void setGetter(FunctionObject *g)
Heap::FunctionObject * getter() const
bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
void setSetter(FunctionObject *s)
void fullyPopulated(PropertyAttributes *attrs)
bool isCompatible(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
void copy(const Property *other, PropertyAttributes attrs)
void completed(PropertyAttributes *attrs)
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter)
Heap::FunctionObject * setter() const
void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs)
SparseArrayNode * right
SparseArrayNode * left
SparseArrayNode * copy(SparseArray *d) const
SparseArrayNode * lowerBound(uint key)
const SparseArrayNode * previousNode() const
SparseArrayNode * parent() const
SparseArrayNode * nextNode()
SparseArrayNode * upperBound(uint key)
const SparseArrayNode * nextNode() const
SparseArrayNode * previousNode()
void setParent(SparseArrayNode *pp)
SparseArrayNode * upperBound(uint key)
SparseArrayNode * erase(SparseArrayNode *n)
void push_back(uint at, uint len)
SparseArrayNode * lowerBound(uint key)
const SparseArrayNode * begin() const
SparseArrayNode * insert(uint akey)
void push_front(uint at)
uint pop_back(uint len)
QList< int > keys() const
SparseArrayNode * findNode(uint akey) const
void freeTree(SparseArrayNode *root, int alignment)
const SparseArrayNode * end() const
uint nEntries() const
const Value * data() const
Definition qv4value_p.h:450
Value values[1]
Definition qv4value_p.h:431
void set(EngineBase *e, uint index, Value v)
Definition qv4value_p.h:440
void set(EngineBase *e, uint index, Value::HeapBasePtr b)
Definition qv4value_p.h:443
void mark(MarkStack *markStack)
Definition qv4value_p.h:454
Value::HeapBasePtr base()
Definition qv4value_p.h:433
const Value & operator[](uint index) const
Definition qv4value_p.h:446
static constexpr size_t offset
Definition qv4value_p.h:428