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
qdoubleendedlist_p.h
Go to the documentation of this file.
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// Qt-Security score:significant
4
5#ifndef QDOUBLEENDEDLIST_P_H
6#define QDOUBLEENDEDLIST_P_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 <QtCore/private/qglobal_p.h>
20
21QT_BEGIN_NAMESPACE
22
23class QInheritedListNode
24{
25public:
26 ~QInheritedListNode() { remove(); }
27 bool isInList() const
28 {
29 Q_ASSERT((m_prev && m_next) || (!m_prev && !m_next));
30 return m_prev != nullptr;
31 }
32
33private:
34 template<class N>
35 friend class QDoubleEndedList;
36
37 void remove()
38 {
39 Q_ASSERT((m_prev && m_next) || (!m_prev && !m_next));
40 if (!m_prev)
41 return;
42
43 m_prev->m_next = m_next;
44 m_next->m_prev = m_prev;
45 m_prev = nullptr;
46 m_next = nullptr;
47 }
48
49 QInheritedListNode *m_next = nullptr;
50 QInheritedListNode *m_prev = nullptr;
51};
52
53template<class N>
55{
56public:
58 {
59 m_head.m_next = &m_head;
60 m_head.m_prev = &m_head;
61 assertHeadConsistent();
62 }
63
65 {
66 assertHeadConsistent();
67 while (!isEmpty())
68 m_head.m_next->remove();
69 assertHeadConsistent();
70 }
71
72 bool isEmpty() const
73 {
74 assertHeadConsistent();
75 return m_head.m_next == &m_head;
76 }
77
78 void prepend(N *n)
79 {
80 assertHeadConsistent();
81 QInheritedListNode *nnode = n;
82 nnode->remove();
83
84 nnode->m_next = m_head.m_next ? m_head.m_next : &m_head;
85 nnode->m_next->m_prev = nnode;
86
87 m_head.m_next = nnode;
88 nnode->m_prev = &m_head;
89 assertHeadConsistent();
90 }
91
92 void append(N *n)
93 {
94 assertHeadConsistent();
95 QInheritedListNode *nnode = n;
96 nnode->remove();
97
98 nnode->m_prev = m_head.m_prev ? m_head.m_prev : &m_head;
99 nnode->m_prev->m_next = nnode;
100
101 m_head.m_prev = nnode;
102 nnode->m_next = &m_head;
103 assertHeadConsistent();
104 }
105
106 void remove(N *n) {
107 Q_ASSERT(contains(n));
108 QInheritedListNode *nnode = n;
109 nnode->remove();
110 assertHeadConsistent();
111 }
112
113 bool contains(const N *n) const
114 {
115 assertHeadConsistent();
116 for (const QInheritedListNode *nnode = m_head.m_next;
117 nnode != &m_head; nnode = nnode->m_next) {
118 if (nnode == n)
119 return true;
120 }
121
122 return false;
123 }
124
125 template<typename T, typename Node>
127 public:
128 T *operator*() const { return QDoubleEndedList<N>::nodeToN(m_node); }
129 T *operator->() const { return QDoubleEndedList<N>::nodeToN(m_node); }
130
131 bool operator==(const base_iterator &other) const { return other.m_node == m_node; }
132 bool operator!=(const base_iterator &other) const { return other.m_node != m_node; }
133
135 {
136 m_node = m_node->m_next;
137 return *this;
138 }
139
141 {
142 const base_iterator self(m_node);
143 m_node = m_node->m_next;
144 return self;
145 }
146
147 private:
148 friend class QDoubleEndedList<N>;
149
150 base_iterator(Node *node) : m_node(node)
151 {
152 Q_ASSERT(m_node != nullptr);
153 }
154
155 Node *m_node = nullptr;
156 };
157
158 using iterator = base_iterator<N, QInheritedListNode>;
159 using const_iterator = base_iterator<const N, const QInheritedListNode>;
160
161 const N *first() const { return checkedNodeToN(m_head.m_next); }
162 N *first() { return checkedNodeToN(m_head.m_next); }
163
164 const N *last() const { return checkedNodeToN(m_head.m_prev); }
165 N *last() { return checkedNodeToN(m_head.m_prev); }
166
167 const N *next(const N *current) const
168 {
169 Q_ASSERT(contains(current));
170 const QInheritedListNode *nnode = current;
171 return checkedNodeToN(nnode->m_next);
172 }
173
174 N *next(N *current)
175 {
176 Q_ASSERT(contains(current));
177 const QInheritedListNode *nnode = current;
178 return checkedNodeToN(nnode->m_next);
179 }
180
181 const N *prev(const N *current) const
182 {
183 Q_ASSERT(contains(current));
184 const QInheritedListNode *nnode = current;
185 return checkedNodeToN(nnode->m_prev);
186 }
187
188 N *prev(N *current)
189 {
190 Q_ASSERT(contains(current));
191 const QInheritedListNode *nnode = current;
192 return checkedNodeToN(nnode->m_prev);
193 }
194
196 {
197 assertHeadConsistent();
198 return iterator(m_head.m_next);
199 }
200
202 {
203 assertHeadConsistent();
204 return iterator(&m_head);
205 }
206
208 {
209 assertHeadConsistent();
210 return const_iterator(m_head.m_next);
211 }
212
214 {
215 assertHeadConsistent();
216 return const_iterator(&m_head);
217 }
218
220 {
221 assertHeadConsistent();
222 qsizetype result = 0;
223 for (const auto *node = m_head.m_next; node != &m_head; node = node->m_next)
224 ++result;
225 return result;
226 }
227
228private:
229 static N *nodeToN(QInheritedListNode *node)
230 {
231 return static_cast<N *>(node);
232 }
233
234 static const N *nodeToN(const QInheritedListNode *node)
235 {
236 return static_cast<const N *>(node);
237 }
238
239 N *checkedNodeToN(QInheritedListNode *node) const
240 {
241 assertHeadConsistent();
242 return (!node || node == &m_head) ? nullptr : nodeToN(node);
243 }
244
245 void assertHeadConsistent() const
246 {
247 Q_ASSERT(m_head.m_next != nullptr);
248 Q_ASSERT(m_head.m_prev != nullptr);
249 Q_ASSERT(m_head.m_next != &m_head || m_head.m_prev == &m_head);
250 }
251
252 QInheritedListNode m_head;
253};
254
255QT_END_NAMESPACE
256
257#endif // QDOUBLEENDEDLIST_P_H
bool operator!=(const base_iterator &other) const
bool operator==(const base_iterator &other) const
const N * last() const
qsizetype count() const
const N * next(const N *current) const
const_iterator end() const
base_iterator< N, QInheritedListNode > iterator
bool contains(const N *n) const
N * next(N *current)
N * prev(N *current)
base_iterator< const N, const QInheritedListNode > const_iterator
const N * prev(const N *current) const
const N * first() const
const_iterator begin() const