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
59 template<class N, N *N::*nextMember>
60 class QForwardFieldList
61 {
62 public:
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);
84 private:
85     QFlagPointer<N> _first;
86 };
87 
88 // QFieldList is a simple linked list, that can append and prepend and also
89 // maintains a count
90 template<class N, N *N::*nextMember>
91 class QFieldList
92 {
93 public:
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);
120 private:
121     N *_first;
122     N *_last;
123     quint32 _flag:1;
124     quint32 _count:31;
125 };
126 
127 template<class N, N *N::*nextMember>
QForwardFieldList()128 QForwardFieldList<N, nextMember>::QForwardFieldList()
129 {
130 }
131 
132 template<class N, N *N::*nextMember>
first()133 N *QForwardFieldList<N, nextMember>::first() const
134 {
135     return *_first;
136 }
137 
138 template<class N, N *N::*nextMember>
takeFirst()139 N *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 
149 template<class N, N *N::*nextMember>
prepend(N * v)150 void QForwardFieldList<N, nextMember>::prepend(N *v)
151 {
152     Q_ASSERT(v->*nextMember == nullptr);
153     v->*nextMember = *_first;
154     _first = v;
155 }
156 
157 template<class N, N *N::*nextMember>
isEmpty()158 bool QForwardFieldList<N, nextMember>::isEmpty() const
159 {
160     return _first.isNull();
161 }
162 
163 template<class N, N *N::*nextMember>
isOne()164 bool QForwardFieldList<N, nextMember>::isOne() const
165 {
166     return *_first && _first->*nextMember == 0;
167 }
168 
169 template<class N, N *N::*nextMember>
isMany()170 bool QForwardFieldList<N, nextMember>::isMany() const
171 {
172     return *_first && _first->*nextMember != 0;
173 }
174 
175 template<class N, N *N::*nextMember>
next(N * v)176 N *QForwardFieldList<N, nextMember>::next(N *v)
177 {
178     Q_ASSERT(v);
179     return v->*nextMember;
180 }
181 
182 template<class N, N *N::*nextMember>
flag()183 bool QForwardFieldList<N, nextMember>::flag() const
184 {
185     return _first.flag();
186 }
187 
188 template<class N, N *N::*nextMember>
setFlag()189 void QForwardFieldList<N, nextMember>::setFlag()
190 {
191     _first.setFlag();
192 }
193 
194 template<class N, N *N::*nextMember>
clearFlag()195 void QForwardFieldList<N, nextMember>::clearFlag()
196 {
197     _first.clearFlag();
198 }
199 
200 template<class N, N *N::*nextMember>
setFlagValue(bool v)201 void QForwardFieldList<N, nextMember>::setFlagValue(bool v)
202 {
203     _first.setFlagValue(v);
204 }
205 
206 template<class N, N *N::*nextMember>
flag2()207 bool QForwardFieldList<N, nextMember>::flag2() const
208 {
209     return _first.flag2();
210 }
211 
212 template<class N, N *N::*nextMember>
setFlag2()213 void QForwardFieldList<N, nextMember>::setFlag2()
214 {
215     _first.setFlag2();
216 }
217 
218 template<class N, N *N::*nextMember>
clearFlag2()219 void QForwardFieldList<N, nextMember>::clearFlag2()
220 {
221     _first.clearFlag2();
222 }
223 
224 template<class N, N *N::*nextMember>
setFlag2Value(bool v)225 void QForwardFieldList<N, nextMember>::setFlag2Value(bool v)
226 {
227     _first.setFlag2Value(v);
228 }
229 
230 template<class N, N *N::*nextMember>
QFieldList()231 QFieldList<N, nextMember>::QFieldList()
232 : _first(nullptr), _last(nullptr), _flag(0), _count(0)
233 {
234 }
235 
236 template<class N, N *N::*nextMember>
first()237 N *QFieldList<N, nextMember>::first() const
238 {
239     return _first;
240 }
241 
242 template<class N, N *N::*nextMember>
takeFirst()243 N *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 
258 template<class N, N *N::*nextMember>
append(N * v)259 void 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 
272 template<class N, N *N::*nextMember>
prepend(N * v)273 void 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 
286 template<class N, N *N::*nextMember>
isEmpty()287 bool QFieldList<N, nextMember>::isEmpty() const
288 {
289     return _count == 0;
290 }
291 
292 template<class N, N *N::*nextMember>
isOne()293 bool QFieldList<N, nextMember>::isOne() const
294 {
295     return _count == 1;
296 }
297 
298 template<class N, N *N::*nextMember>
isMany()299 bool QFieldList<N, nextMember>::isMany() const
300 {
301     return _count > 1;
302 }
303 
304 template<class N, N *N::*nextMember>
count()305 int QFieldList<N, nextMember>::count() const
306 {
307     return _count;
308 }
309 
310 template<class N, N *N::*nextMember>
next(N * v)311 N *QFieldList<N, nextMember>::next(N *v)
312 {
313     Q_ASSERT(v);
314     return v->*nextMember;
315 }
316 
317 template<class N, N *N::*nextMember>
append(QFieldList<N,nextMember> & o)318 void 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 
334 template<class N, N *N::*nextMember>
prepend(QFieldList<N,nextMember> & o)335 void 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 
351 template<class N, N *N::*nextMember>
insertAfter(N * after,QFieldList<N,nextMember> & o)352 void 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 
372 template<class N, N *N::*nextMember>
copyAndClear(QFieldList<N,nextMember> & o)373 void 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 
382 template<class N, N *N::*nextMember>
copyAndClearAppend(QForwardFieldList<N,nextMember> & o)383 void 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 
391 template<class N, N *N::*nextMember>
copyAndClearPrepend(QForwardFieldList<N,nextMember> & o)392 void 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 
400 template<class N, N *N::*nextMember>
flag()401 bool QFieldList<N, nextMember>::flag() const
402 {
403     return _flag;
404 }
405 
406 template<class N, N *N::*nextMember>
setFlag()407 void QFieldList<N, nextMember>::setFlag()
408 {
409     _flag = true;
410 }
411 
412 template<class N, N *N::*nextMember>
clearFlag()413 void QFieldList<N, nextMember>::clearFlag()
414 {
415     _flag = false;
416 }
417 
418 template<class N, N *N::*nextMember>
setFlagValue(bool v)419 void QFieldList<N, nextMember>::setFlagValue(bool v)
420 {
421     _flag = v;
422 }
423 
424 #endif // QFIELDLIST_P_H
425