Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qssginvasivelinkedlist_p.h
Go to the documentation of this file.
1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#ifndef QSSGINVASIVELINKEDLIST_H
6#define QSSGINVASIVELINKEDLIST_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 <QtQuick3DUtils/private/qtquick3dutilsglobal_p.h>
20
22
23#ifdef QT_DEBUG
24#define QSSG_VERIFY_NODE(X) if (!(X)) qCritical("Node links are not null!");
25#else
26#define QSSG_VERIFY_NODE(X) Q_UNUSED((X));
27#endif
28
29// Used for singly linked list where
30// items have either no head or tail ptr.
31template<typename T>
33{
34 static void set(T &, T *) {}
35 static T *get(const T &) { return nullptr; }
36};
37
38template <typename T, T *T::*n>
40{
41 static inline T *get(T &o) { return o.*n; }
42 static inline const T *get(const T &o) { return o.*n; }
43 static inline void set(T &o, T *next) { o.*n = next; }
44};
45
46template <typename T, T *T::*p>
48{
49 static inline T *get(T &o) { return o.*p; }
50 static inline const T *get(const T &o) { return o.*p; }
51 static inline void set(T &o, T *prev) { o.*p = prev; }
52};
53
54// Base linked list without an included head or tail member.
55template<typename T, typename HeadOp, typename TailOp>
57{
58 inline T *tail(T *inObj) { return inObj ? TailOp::get(inObj) : nullptr; }
59 inline T *head(T *inObj) { return inObj ? HeadOp::get(inObj) : nullptr; }
60 inline const T *tail(const T *inObj) { return inObj ? TailOp::get(inObj) : nullptr; }
61 inline const T *head(const T *inObj) { return inObj ? HeadOp::get(inObj) : nullptr; }
62
63 void remove(T &inObj)
64 {
65 T *theHead = HeadOp::get(inObj);
66 T *theTail = TailOp::get(inObj);
67 if (theHead)
68 TailOp::set(*theHead, theTail);
69 if (theTail)
70 HeadOp::set(*theTail, theHead);
71 HeadOp::set(inObj, nullptr);
72 TailOp::set(inObj, nullptr);
73 }
74
75 void insert_after(T &inPosition, T &inObj)
76 {
77 T *theHead = &inPosition;
78 T *theTail = TailOp::get(inPosition);
79 insert_unsafe(theHead, theTail, inObj);
80 }
81
82 void insert_before(T &inPosition, T &inObj)
83 {
84 T *theHead = HeadOp::get(inPosition);
85 T *theTail = &inPosition;
86 insert_unsafe(theHead, theTail, inObj);
87 }
88
89 // The name here is intentionally named "unsafe" to discourage use
90 // with out knowing what it implies to call this function.
91 // In most cases this will be used to insert before and after a neighboring pair
92 // (see: insert_before()/_after), but it can also be convenient if you want to split
93 // up a list and retain the chain for the removed section.
94 void insert_unsafe(T *inHead, T *inTail, T &inObj)
95 {
96 if (inHead)
97 TailOp::set(*inHead, &inObj);
98 if (inTail)
99 HeadOp::set(*inTail, &inObj);
100 HeadOp::set(inObj, inHead);
101 TailOp::set(inObj, inTail);
102 }
103};
104
105template<typename T, typename TailOp>
107{
108 using Iterator = QSSGLinkedListIterator<T, TailOp>;
110 explicit QSSGLinkedListIterator(T *inObj = nullptr) : m_obj(inObj) {}
111
112 inline bool operator!=(const Iterator &inIter) const { return m_obj != inIter.m_obj; }
113 inline bool operator==(const Iterator &inIter) const { return m_obj == inIter.m_obj; }
114
116 {
117 if (m_obj)
118 m_obj = TailOp::get(*m_obj);
119 return *this;
120 }
121
123 {
124 Iterator retval(*this);
125 ++(*this);
126 return retval;
127 }
128
129 T &operator*() { return *m_obj; }
130 T *operator->() { return m_obj; }
131};
132
133template<typename T, T *T::*Next>
134struct QSSGInvasiveSingleLinkedList : public QSSGInvasiveLinkListBase<T, QSSGNullOp<T>, QSSGListAccessorNext<T, Next>>
135{
136 using TailOp = QSSGListAccessorNext<T, Next>;
137 using List = QSSGInvasiveSingleLinkedList<T, Next>;
138 using BaseList = QSSGInvasiveLinkListBase<T, QSSGNullOp<T>, TailOp>;
139 using iterator = QSSGLinkedListIterator<T, TailOp>;
141 T *m_head = nullptr;
142
143 inline T &front() const { return *m_head; }
144
145 void push_front(T &inObj)
146 {
147 if (m_head != nullptr)
148 BaseList::insert_before(*m_head, inObj);
149 m_head = &inObj;
150 }
151
152 void push_back(T &inObj)
153 {
154 // The next pointer of the tail must be null.
155 // We assert because if the inObj actually points somewhere then it's
156 // likely that we: Crash at some later point, we loop, or we broke the links
157 // in another list.
158 QSSG_VERIFY_NODE(TailOp::get(inObj) == nullptr);
159
160 if (m_head == nullptr) {
161 m_head = &inObj;
162 } else {
163 T *lastObj = nullptr;
164 for (iterator iter = begin(), endIter = end(); iter != endIter; ++iter)
165 lastObj = &(*iter);
166
167 Q_ASSERT(lastObj);
168 if (lastObj)
169 TailOp::set(*lastObj, &inObj);
170 }
171 TailOp::set(inObj, nullptr);
172 }
173
174 void remove(T &inObj)
175 {
176 if (m_head == &inObj) {
177 m_head = TailOp::get(inObj);
178 BaseList::remove(inObj);
179 } else if (m_head) {
180 // We need to find the node pointing to inObj
181 T *head = m_head;
182 T *tail = TailOp::get(*head);
183 while (head && tail != &inObj) {
184 head = TailOp::get(*head);
185 tail = head ? TailOp::get(*head) : nullptr;
186 }
187
188 if (head && tail == &inObj) {
189 T *oldTail = TailOp::get(inObj);
190 TailOp::set(inObj, nullptr); // deteach from the list
191 TailOp::set(*head, oldTail); // insert old tail to head of inObj
192 }
193 }
194 }
195
200 {
201 for (auto it = begin(), e = end(); it != e;)
202 remove(*(it++));
203 }
204
209 void clear()
210 {
211 m_head = nullptr;
212 }
213
214 inline bool isEmpty() const { return m_head == nullptr; }
215
216 inline iterator begin() { return iterator(m_head); }
217 inline iterator end() { return iterator(nullptr); }
218 inline const_iterator begin() const { return iterator(m_head); }
219 inline const_iterator end() const { return iterator(nullptr); }
220};
221
222template<typename T, T *T::*Previous, T *T::*Next>
223struct QSSGInvasiveLinkedList : public QSSGInvasiveLinkListBase<T, QSSGListAccessorPrevious<T, Previous>, QSSGListAccessorNext<T, Next>>
224{
225 using HeadOp = QSSGListAccessorPrevious<T, Previous>;
226 using TailOp = QSSGListAccessorNext<T, Next>;
227 using List = QSSGInvasiveLinkedList<T, Previous, Next>;
228 using BaseList = QSSGInvasiveLinkListBase<T, HeadOp, TailOp>;
229 using iterator = QSSGLinkedListIterator<T, TailOp>;
231 using reverse_iterator = QSSGLinkedListIterator<T, HeadOp>;
233
234 T *m_head = nullptr;
235 T *m_tail = nullptr;
236
237 inline T &front() const
238 {
240 return *m_head;
241 }
242 inline T &back() const
243 {
245 return *m_tail;
246 }
247
248 inline T *front_ptr() const { return m_head; }
249 inline T *back_ptr() const { return m_tail; }
250
251 void push_front(T &inObj)
252 {
253 // The prev pointer of the head must be null.
254 // If the inObj actually points somewhere then it's likely that we're going to:
255 // Crash at some later point, loop, or that the we just broke the another list.
256 QSSG_VERIFY_NODE(HeadOp::get(inObj) == nullptr);
257
258 if (m_head != nullptr)
259 BaseList::insert_before(*m_head, inObj);
260 else
261 HeadOp::set(inObj, nullptr);
262
263 m_head = &inObj;
264
265 if (m_tail == nullptr)
266 m_tail = &inObj;
267 }
268
269 void push_back(T &inObj)
270 {
271 // The next pointer of the tail must be null.
272 // We assert because if the inObj actually points somewhere then it's
273 // likely that we: Crash at some later point, we loop, or we broke the links
274 // in another list.
275 QSSG_VERIFY_NODE(TailOp::get(inObj) == nullptr);
276
277 if (m_tail != nullptr)
278 BaseList::insert_after(*m_tail, inObj);
279 else
280 TailOp::set(inObj, nullptr);
281
282 m_tail = &inObj;
283
284 if (m_head == nullptr)
285 m_head = &inObj;
286 }
287
288 void remove(T &inObj)
289 {
290 if (m_head == &inObj)
291 m_head = TailOp::get(inObj);
292 if (m_tail == &inObj)
293 m_tail = HeadOp::get(inObj);
294
295 BaseList::remove(inObj);
296 }
297
302 {
303 for (auto it = begin(), e = end(); it != e;)
304 remove(*(it++));
305 }
306
311 void clear()
312 {
313 m_head = m_tail = nullptr;
314 }
315
316 inline bool isEmpty() const { return m_head == nullptr; }
317
318 inline iterator begin() { return iterator(m_head); }
319 inline iterator end() { return iterator(nullptr); }
320
321 inline const_iterator begin() const { return iterator(m_head); }
322 inline const_iterator end() const { return iterator(nullptr); }
323
325 inline reverse_iterator rend() { return reverse_iterator(nullptr); }
326
328 inline const_reverse_iterator rend() const { return reverse_iterator(nullptr); }
329};
330
332
333#endif // QSSGINVASIVELINKEDLIST_H
QSet< QString >::iterator it
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
GLfloat n
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QSSG_VERIFY_NODE(X)
void insert_before(T &inPosition, T &inObj)
const T * head(const T *inObj)
const T * tail(const T *inObj)
void insert_after(T &inPosition, T &inObj)
void insert_unsafe(T *inHead, T *inTail, T &inObj)
QSSGLinkedListIterator< T, HeadOp > reverse_iterator
const_reverse_iterator rbegin() const
QSSGListAccessorNext< T, Next > TailOp
void clear()
clear will set the head and tail of the list to null.
void removeAll()
removeAll removes all nodes and re-sets their head and tail to null.
QSSGInvasiveLinkListBase< T, HeadOp, TailOp > BaseList
QSSGListAccessorPrevious< T, Previous > HeadOp
QSSGInvasiveLinkedList< T, Previous, Next > List
const_reverse_iterator rend() const
QSSGLinkedListIterator< T, TailOp > iterator
void clear()
clear will set the head of the list to null.
QSSGLinkedListIterator< T, TailOp > iterator
QSSGListAccessorNext< T, Next > TailOp
QSSGInvasiveLinkListBase< T, QSSGNullOp< T >, TailOp > BaseList
void removeAll()
removeAll removes all nodes and re-sets their tail to null.
QSSGInvasiveSingleLinkedList< T, Next > List
bool operator==(const Iterator &inIter) const
QSSGLinkedListIterator(T *inObj=nullptr)
bool operator!=(const Iterator &inIter) const
QSSGLinkedListIterator< T, TailOp > Iterator
static void set(T &o, T *next)
static const T * get(const T &o)
static const T * get(const T &o)
static void set(T &o, T *prev)
static void set(T &, T *)
static T * get(const T &)