1// Copyright (C) 2021 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 QFIELDLIST_P_H
5#define QFIELDLIST_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 <QtCore/private/qglobal_p.h>
19#include <QtCore/qtaggedpointer.h>
20
21
22// QForwardFieldList is a super simple linked list that can only prepend
23template<class N, N *N::*nextMember, typename Tag = QtPrivate::TagInfo<N>>
24class QForwardFieldList
25{
26public:
27 inline QForwardFieldList();
28 inline N *first() const;
29 inline N *takeFirst();
30
31 inline void prepend(N *);
32 template <typename OtherTag>
33 inline void copyAndClearPrepend(QForwardFieldList<N, nextMember, OtherTag> &);
34
35 inline bool isEmpty() const;
36 inline bool isOne() const;
37 inline bool isMany() const;
38
39 static inline N *next(N *v);
40
41 inline Tag tag() const;
42 inline void setTag(Tag t);
43private:
44 QTaggedPointer<N, Tag> _first;
45};
46
47// QFieldList is a simple linked list, that can append and prepend and also
48// maintains a count
49template<class N, N *N::*nextMember>
50class QFieldList
51{
52public:
53 inline QFieldList();
54 inline N *first() const;
55 inline N *takeFirst();
56
57 inline void append(N *);
58 inline void prepend(N *);
59
60 inline bool isEmpty() const;
61 inline bool isOne() const;
62 inline bool isMany() const;
63 inline int count() const;
64
65 inline void append(QFieldList<N, nextMember> &);
66 inline void prepend(QFieldList<N, nextMember> &);
67 inline void insertAfter(N *, QFieldList<N, nextMember> &);
68
69 inline void copyAndClear(QFieldList<N, nextMember> &);
70 template <typename Tag>
71 inline void copyAndClearAppend(QForwardFieldList<N, nextMember, Tag> &);
72 template <typename Tag>
73 inline void copyAndClearPrepend(QForwardFieldList<N, nextMember, Tag> &);
74
75 static inline N *next(N *v);
76
77 inline bool flag() const;
78 inline void setFlag();
79 inline void clearFlag();
80 inline void setFlagValue(bool);
81private:
82 N *_first;
83 N *_last;
84 quint32 _flag:1;
85 quint32 _count:31;
86};
87
88template<class N, N *N::*nextMember, typename Tag>
89QForwardFieldList<N, nextMember, Tag>::QForwardFieldList()
90{
91}
92
93template<class N, N *N::*nextMember, typename Tag>
94N *QForwardFieldList<N, nextMember, Tag>::first() const
95{
96 return _first.data();
97}
98
99template<class N, N *N::*nextMember, typename Tag>
100N *QForwardFieldList<N, nextMember, Tag>::takeFirst()
101{
102 N *value = _first.data();
103 if (value) {
104 _first = next(v: value);
105 value->*nextMember = nullptr;
106 }
107 return value;
108}
109
110template<class N, N *N::*nextMember, typename Tag>
111void QForwardFieldList<N, nextMember, Tag>::prepend(N *v)
112{
113 Q_ASSERT(v->*nextMember == nullptr);
114 v->*nextMember = _first.data();
115 _first = v;
116}
117
118template<class N, N *N::*nextMember, typename Tag>
119template <typename OtherTag>
120void QForwardFieldList<N, nextMember, Tag>::copyAndClearPrepend(QForwardFieldList<N, nextMember, OtherTag> &o)
121{
122 _first = nullptr;
123 while (N *n = o.takeFirst()) prepend(v: n);
124}
125
126template<class N, N *N::*nextMember, typename Tag>
127bool QForwardFieldList<N, nextMember, Tag>::isEmpty() const
128{
129 return _first.isNull();
130}
131
132template<class N, N *N::*nextMember, typename Tag>
133bool QForwardFieldList<N, nextMember, Tag>::isOne() const
134{
135 return _first.data() && _first->*nextMember == 0;
136}
137
138template<class N, N *N::*nextMember, typename Tag>
139bool QForwardFieldList<N, nextMember, Tag>::isMany() const
140{
141 return _first.data() && _first->*nextMember != 0;
142}
143
144template<class N, N *N::*nextMember, typename Tag>
145N *QForwardFieldList<N, nextMember, Tag>::next(N *v)
146{
147 Q_ASSERT(v);
148 return v->*nextMember;
149}
150
151template<class N, N *N::*nextMember, typename Tag>
152Tag QForwardFieldList<N, nextMember, Tag>::tag() const
153{
154 return _first.tag();
155}
156
157template<class N, N *N::*nextMember, typename Tag>
158void QForwardFieldList<N, nextMember, Tag>::setTag(Tag t)
159{
160 _first.setTag(t);
161}
162
163template<class N, N *N::*nextMember>
164QFieldList<N, nextMember>::QFieldList()
165: _first(nullptr), _last(nullptr), _flag(0), _count(0)
166{
167}
168
169template<class N, N *N::*nextMember>
170N *QFieldList<N, nextMember>::first() const
171{
172 return _first;
173}
174
175template<class N, N *N::*nextMember>
176N *QFieldList<N, nextMember>::takeFirst()
177{
178 N *value = _first;
179 if (value) {
180 _first = next(v: value);
181 if (_last == value) {
182 Q_ASSERT(_first == nullptr);
183 _last = nullptr;
184 }
185 value->*nextMember = nullptr;
186 --_count;
187 }
188 return value;
189}
190
191template<class N, N *N::*nextMember>
192void QFieldList<N, nextMember>::append(N *v)
193{
194 Q_ASSERT(v->*nextMember == nullptr);
195 if (isEmpty()) {
196 _first = v;
197 _last = v;
198 } else {
199 _last->*nextMember = v;
200 _last = v;
201 }
202 ++_count;
203}
204
205template<class N, N *N::*nextMember>
206void QFieldList<N, nextMember>::prepend(N *v)
207{
208 Q_ASSERT(v->*nextMember == nullptr);
209 if (isEmpty()) {
210 _first = v;
211 _last = v;
212 } else {
213 v->*nextMember = _first;
214 _first = v;
215 }
216 ++_count;
217}
218
219template<class N, N *N::*nextMember>
220bool QFieldList<N, nextMember>::isEmpty() const
221{
222 return _count == 0;
223}
224
225template<class N, N *N::*nextMember>
226bool QFieldList<N, nextMember>::isOne() const
227{
228 return _count == 1;
229}
230
231template<class N, N *N::*nextMember>
232bool QFieldList<N, nextMember>::isMany() const
233{
234 return _count > 1;
235}
236
237template<class N, N *N::*nextMember>
238int QFieldList<N, nextMember>::count() const
239{
240 return _count;
241}
242
243template<class N, N *N::*nextMember>
244N *QFieldList<N, nextMember>::next(N *v)
245{
246 Q_ASSERT(v);
247 return v->*nextMember;
248}
249
250template<class N, N *N::*nextMember>
251void QFieldList<N, nextMember>::append(QFieldList<N, nextMember> &o)
252{
253 if (!o.isEmpty()) {
254 if (isEmpty()) {
255 _first = o._first;
256 _last = o._last;
257 _count = o._count;
258 } else {
259 _last->*nextMember = o._first;
260 _last = o._last;
261 _count += o._count;
262 }
263 o._first = o._last = 0; o._count = 0;
264 }
265}
266
267template<class N, N *N::*nextMember>
268void QFieldList<N, nextMember>::prepend(QFieldList<N, nextMember> &o)
269{
270 if (!o.isEmpty()) {
271 if (isEmpty()) {
272 _first = o._first;
273 _last = o._last;
274 _count = o._count;
275 } else {
276 o._last->*nextMember = _first;
277 _first = o._first;
278 _count += o._count;
279 }
280 o._first = o._last = 0; o._count = 0;
281 }
282}
283
284template<class N, N *N::*nextMember>
285void QFieldList<N, nextMember>::insertAfter(N *after, QFieldList<N, nextMember> &o)
286{
287 if (after == 0) {
288 prepend(o);
289 } else if (after == _last) {
290 append(o);
291 } else if (!o.isEmpty()) {
292 if (isEmpty()) {
293 _first = o._first;
294 _last = o._last;
295 _count = o._count;
296 } else {
297 o._last->*nextMember = after->*nextMember;
298 after->*nextMember = o._first;
299 _count += o._count;
300 }
301 o._first = o._last = 0; o._count = 0;
302 }
303}
304
305template<class N, N *N::*nextMember>
306void QFieldList<N, nextMember>::copyAndClear(QFieldList<N, nextMember> &o)
307{
308 _first = o._first;
309 _last = o._last;
310 _count = o._count;
311 o._first = o._last = nullptr;
312 o._count = 0;
313}
314
315template<class N, N *N::*nextMember>
316template <typename Tag>
317void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember, Tag> &o)
318{
319 _first = 0;
320 _last = 0;
321 _count = 0;
322 while (N *n = o.takeFirst()) append(n);
323}
324
325template<class N, N *N::*nextMember>
326template <typename Tag>
327void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember, Tag> &o)
328{
329 _first = nullptr;
330 _last = nullptr;
331 _count = 0;
332 while (N *n = o.takeFirst()) prepend(n);
333}
334
335template<class N, N *N::*nextMember>
336bool QFieldList<N, nextMember>::flag() const
337{
338 return _flag;
339}
340
341template<class N, N *N::*nextMember>
342void QFieldList<N, nextMember>::setFlag()
343{
344 _flag = true;
345}
346
347template<class N, N *N::*nextMember>
348void QFieldList<N, nextMember>::clearFlag()
349{
350 _flag = false;
351}
352
353template<class N, N *N::*nextMember>
354void QFieldList<N, nextMember>::setFlagValue(bool v)
355{
356 _flag = v;
357}
358
359#endif // QFIELDLIST_P_H
360

source code of qtdeclarative/src/qml/qml/ftw/qfieldlist_p.h