1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QFIELDLIST_P_H
41#define QFIELDLIST_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtCore/qglobal.h>
55
56#include <private/qflagpointer_p.h>
57
58// QForwardFieldList is a super simple linked list that can only prepend
59template<class N, N *N::*nextMember>
60class QForwardFieldList
61{
62public:
63 inline QForwardFieldList();
64 inline N *first() const;
65 inline N *takeFirst();
66
67 inline void prepend(N *);
68
69 inline bool isEmpty() const;
70 inline bool isOne() const;
71 inline bool isMany() const;
72
73 static inline N *next(N *v);
74
75 inline bool flag() const;
76 inline void setFlag();
77 inline void clearFlag();
78 inline void setFlagValue(bool);
79
80 inline bool flag2() const;
81 inline void setFlag2();
82 inline void clearFlag2();
83 inline void setFlag2Value(bool);
84private:
85 QFlagPointer<N> _first;
86};
87
88// QFieldList is a simple linked list, that can append and prepend and also
89// maintains a count
90template<class N, N *N::*nextMember>
91class QFieldList
92{
93public:
94 inline QFieldList();
95 inline N *first() const;
96 inline N *takeFirst();
97
98 inline void append(N *);
99 inline void prepend(N *);
100
101 inline bool isEmpty() const;
102 inline bool isOne() const;
103 inline bool isMany() const;
104 inline int count() const;
105
106 inline void append(QFieldList<N, nextMember> &);
107 inline void prepend(QFieldList<N, nextMember> &);
108 inline void insertAfter(N *, QFieldList<N, nextMember> &);
109
110 inline void copyAndClear(QFieldList<N, nextMember> &);
111 inline void copyAndClearAppend(QForwardFieldList<N, nextMember> &);
112 inline void copyAndClearPrepend(QForwardFieldList<N, nextMember> &);
113
114 static inline N *next(N *v);
115
116 inline bool flag() const;
117 inline void setFlag();
118 inline void clearFlag();
119 inline void setFlagValue(bool);
120private:
121 N *_first;
122 N *_last;
123 quint32 _flag:1;
124 quint32 _count:31;
125};
126
127template<class N, N *N::*nextMember>
128QForwardFieldList<N, nextMember>::QForwardFieldList()
129{
130}
131
132template<class N, N *N::*nextMember>
133N *QForwardFieldList<N, nextMember>::first() const
134{
135 return *_first;
136}
137
138template<class N, N *N::*nextMember>
139N *QForwardFieldList<N, nextMember>::takeFirst()
140{
141 N *value = *_first;
142 if (value) {
143 _first = next(value);
144 value->*nextMember = nullptr;
145 }
146 return value;
147}
148
149template<class N, N *N::*nextMember>
150void QForwardFieldList<N, nextMember>::prepend(N *v)
151{
152 Q_ASSERT(v->*nextMember == nullptr);
153 v->*nextMember = *_first;
154 _first = v;
155}
156
157template<class N, N *N::*nextMember>
158bool QForwardFieldList<N, nextMember>::isEmpty() const
159{
160 return _first.isNull();
161}
162
163template<class N, N *N::*nextMember>
164bool QForwardFieldList<N, nextMember>::isOne() const
165{
166 return *_first && _first->*nextMember == 0;
167}
168
169template<class N, N *N::*nextMember>
170bool QForwardFieldList<N, nextMember>::isMany() const
171{
172 return *_first && _first->*nextMember != 0;
173}
174
175template<class N, N *N::*nextMember>
176N *QForwardFieldList<N, nextMember>::next(N *v)
177{
178 Q_ASSERT(v);
179 return v->*nextMember;
180}
181
182template<class N, N *N::*nextMember>
183bool QForwardFieldList<N, nextMember>::flag() const
184{
185 return _first.flag();
186}
187
188template<class N, N *N::*nextMember>
189void QForwardFieldList<N, nextMember>::setFlag()
190{
191 _first.setFlag();
192}
193
194template<class N, N *N::*nextMember>
195void QForwardFieldList<N, nextMember>::clearFlag()
196{
197 _first.clearFlag();
198}
199
200template<class N, N *N::*nextMember>
201void QForwardFieldList<N, nextMember>::setFlagValue(bool v)
202{
203 _first.setFlagValue(v);
204}
205
206template<class N, N *N::*nextMember>
207bool QForwardFieldList<N, nextMember>::flag2() const
208{
209 return _first.flag2();
210}
211
212template<class N, N *N::*nextMember>
213void QForwardFieldList<N, nextMember>::setFlag2()
214{
215 _first.setFlag2();
216}
217
218template<class N, N *N::*nextMember>
219void QForwardFieldList<N, nextMember>::clearFlag2()
220{
221 _first.clearFlag2();
222}
223
224template<class N, N *N::*nextMember>
225void QForwardFieldList<N, nextMember>::setFlag2Value(bool v)
226{
227 _first.setFlag2Value(v);
228}
229
230template<class N, N *N::*nextMember>
231QFieldList<N, nextMember>::QFieldList()
232: _first(nullptr), _last(nullptr), _flag(0), _count(0)
233{
234}
235
236template<class N, N *N::*nextMember>
237N *QFieldList<N, nextMember>::first() const
238{
239 return _first;
240}
241
242template<class N, N *N::*nextMember>
243N *QFieldList<N, nextMember>::takeFirst()
244{
245 N *value = _first;
246 if (value) {
247 _first = next(value);
248 if (_last == value) {
249 Q_ASSERT(_first == nullptr);
250 _last = nullptr;
251 }
252 value->*nextMember = nullptr;
253 --_count;
254 }
255 return value;
256}
257
258template<class N, N *N::*nextMember>
259void QFieldList<N, nextMember>::append(N *v)
260{
261 Q_ASSERT(v->*nextMember == nullptr);
262 if (isEmpty()) {
263 _first = v;
264 _last = v;
265 } else {
266 _last->*nextMember = v;
267 _last = v;
268 }
269 ++_count;
270}
271
272template<class N, N *N::*nextMember>
273void QFieldList<N, nextMember>::prepend(N *v)
274{
275 Q_ASSERT(v->*nextMember == nullptr);
276 if (isEmpty()) {
277 _first = v;
278 _last = v;
279 } else {
280 v->*nextMember = _first;
281 _first = v;
282 }
283 ++_count;
284}
285
286template<class N, N *N::*nextMember>
287bool QFieldList<N, nextMember>::isEmpty() const
288{
289 return _count == 0;
290}
291
292template<class N, N *N::*nextMember>
293bool QFieldList<N, nextMember>::isOne() const
294{
295 return _count == 1;
296}
297
298template<class N, N *N::*nextMember>
299bool QFieldList<N, nextMember>::isMany() const
300{
301 return _count > 1;
302}
303
304template<class N, N *N::*nextMember>
305int QFieldList<N, nextMember>::count() const
306{
307 return _count;
308}
309
310template<class N, N *N::*nextMember>
311N *QFieldList<N, nextMember>::next(N *v)
312{
313 Q_ASSERT(v);
314 return v->*nextMember;
315}
316
317template<class N, N *N::*nextMember>
318void QFieldList<N, nextMember>::append(QFieldList<N, nextMember> &o)
319{
320 if (!o.isEmpty()) {
321 if (isEmpty()) {
322 _first = o._first;
323 _last = o._last;
324 _count = o._count;
325 } else {
326 _last->*nextMember = o._first;
327 _last = o._last;
328 _count += o._count;
329 }
330 o._first = o._last = 0; o._count = 0;
331 }
332}
333
334template<class N, N *N::*nextMember>
335void QFieldList<N, nextMember>::prepend(QFieldList<N, nextMember> &o)
336{
337 if (!o.isEmpty()) {
338 if (isEmpty()) {
339 _first = o._first;
340 _last = o._last;
341 _count = o._count;
342 } else {
343 o._last->*nextMember = _first;
344 _first = o._first;
345 _count += o._count;
346 }
347 o._first = o._last = 0; o._count = 0;
348 }
349}
350
351template<class N, N *N::*nextMember>
352void QFieldList<N, nextMember>::insertAfter(N *after, QFieldList<N, nextMember> &o)
353{
354 if (after == 0) {
355 prepend(o);
356 } else if (after == _last) {
357 append(o);
358 } else if (!o.isEmpty()) {
359 if (isEmpty()) {
360 _first = o._first;
361 _last = o._last;
362 _count = o._count;
363 } else {
364 o._last->*nextMember = after->*nextMember;
365 after->*nextMember = o._first;
366 _count += o._count;
367 }
368 o._first = o._last = 0; o._count = 0;
369 }
370}
371
372template<class N, N *N::*nextMember>
373void QFieldList<N, nextMember>::copyAndClear(QFieldList<N, nextMember> &o)
374{
375 _first = o._first;
376 _last = o._last;
377 _count = o._count;
378 o._first = o._last = nullptr;
379 o._count = 0;
380}
381
382template<class N, N *N::*nextMember>
383void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember> &o)
384{
385 _first = 0;
386 _last = 0;
387 _count = 0;
388 while (N *n = o.takeFirst()) append(n);
389}
390
391template<class N, N *N::*nextMember>
392void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember> &o)
393{
394 _first = nullptr;
395 _last = nullptr;
396 _count = 0;
397 while (N *n = o.takeFirst()) prepend(n);
398}
399
400template<class N, N *N::*nextMember>
401bool QFieldList<N, nextMember>::flag() const
402{
403 return _flag;
404}
405
406template<class N, N *N::*nextMember>
407void QFieldList<N, nextMember>::setFlag()
408{
409 _flag = true;
410}
411
412template<class N, N *N::*nextMember>
413void QFieldList<N, nextMember>::clearFlag()
414{
415 _flag = false;
416}
417
418template<class N, N *N::*nextMember>
419void QFieldList<N, nextMember>::setFlagValue(bool v)
420{
421 _flag = v;
422}
423
424#endif // QFIELDLIST_P_H
425