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
qiterable.h
Go to the documentation of this file.
1// Copyright (C) 2020 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 QITERABLE_H
5#define QITERABLE_H
6
7#include <QtCore/qglobal.h>
8#include <QtCore/qtypeinfo.h>
9#include <QtCore/qtaggedpointer.h>
10
11#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
12# include <QtCore/qmetacontainer.h>
13#endif
14
15QT_BEGIN_NAMESPACE
16
17namespace QtPrivate {
18 template<typename Type, typename Storage = Type>
20 {
21 enum Tag : bool { Const, Mutable };
22 QTaggedPointer<Storage, Tag> m_pointer;
23
24 public:
26
28 : m_pointer(reinterpret_cast<Storage *>(const_cast<void *>(pointer)), Const)
29 {
32 }
33
40
41 template<typename InputType>
43 : m_pointer(reinterpret_cast<Storage *>(const_cast<InputType *>(pointer)), Const)
44 {
45 static_assert(alignof(InputType) >= alignof(Storage));
46 }
47
48 template<typename InputType>
50 : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
51 {
52 static_assert(alignof(InputType) >= alignof(Storage));
53 }
54
56
57 const Type *constPointer() const
58 {
59 return reinterpret_cast<const Type *>(m_pointer.data());
60 }
61
62 Type *mutablePointer() const
63 {
64 return m_pointer.tag() == Mutable ? reinterpret_cast<Type *>(m_pointer.data()) : nullptr;
65 }
66 };
67}
68
69template<class Iterator, typename IteratorCategory>
70class QTaggedIterator : public Iterator
71{
72public:
73 using iterator_category = IteratorCategory;
74 QTaggedIterator(Iterator &&it) : Iterator(std::move(it))
75 {
76 const auto metaContainer = this->metaContainer();
77 if constexpr (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory>) {
78 if (!metaContainer.hasRandomAccessIterator()) {
79 qFatal("You cannot use this iterator as a random access iterator");
80 this->clearIterator();
81 }
82 }
83
84 if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory>) {
85 if (!metaContainer.hasBidirectionalIterator()) {
86 qFatal("You cannot use this iterator as a bidirectional iterator");
87 this->clearIterator();
88 }
89 }
90
91 if constexpr (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory>) {
92 if (!metaContainer.hasForwardIterator()) {
93 qFatal("You cannot use this iterator as a forward iterator");
94 this->clearIterator();
95 }
96 }
97
98 if constexpr (std::is_base_of_v<std::input_iterator_tag, IteratorCategory>) {
99 if (!metaContainer.hasInputIterator()) {
100 qFatal("You cannot use this iterator as an input iterator");
101 this->clearIterator();
102 }
103 }
104
105 Q_UNUSED(metaContainer); // in case none of the above apply
106 }
107
108 bool operator==(const QTaggedIterator &o) const { return Iterator::operator==(o); }
109 bool operator!=(const QTaggedIterator &o) const { return Iterator::operator!=(o); }
110 QTaggedIterator &operator++() { Iterator::operator++(); return *this; }
111 QTaggedIterator operator++(int x) { return QTaggedIterator(Iterator::operator++(x)); }
112 QTaggedIterator &operator--() { Iterator::operator--(); return *this; }
113 QTaggedIterator operator--(int x) { return QTaggedIterator(Iterator::operator--(x)); }
114 QTaggedIterator &operator+=(qsizetype j) { Iterator::operator+=(j); return *this; }
115 QTaggedIterator &operator-=(qsizetype j) { Iterator::operator-=(j); return *this; }
116 QTaggedIterator operator+(qsizetype j) const { return QTaggedIterator(Iterator::operator+(j)); }
117 QTaggedIterator operator-(qsizetype j) const { return QTaggedIterator(Iterator::operator-(j)); }
118 qsizetype operator-(const QTaggedIterator &j) const { return Iterator::operator-(j); }
119
120 bool operator<(const QTaggedIterator &j) { return operator-(j) < 0; }
121 bool operator>=(const QTaggedIterator &j) { return !operator<(j); }
122 bool operator>(const QTaggedIterator &j) { return operator-(j) > 0; }
123 bool operator<=(const QTaggedIterator &j) { return !operator>(j); }
124
125 friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; }
126};
127
128template<class Container>
129class QIterable;
130
131template<class Container>
133{
134private:
135 QtPrivate::QConstPreservingPointer<QIterable<Container>> m_iterable;
136 void *m_iterator = nullptr;
137
138protected:
139 QBaseIterator() = default;
140 QBaseIterator(const QIterable<Container> *iterable, void *iterator)
141 : m_iterable(iterable), m_iterator(iterator)
142 {}
143
144 QBaseIterator(QIterable<Container> *iterable, void *iterator)
145 : m_iterable(iterable), m_iterator(iterator)
146 {}
147
150 {
151 other.m_iterator = nullptr;
152 }
153
156 {
157 initIterator(other.m_iterator);
158 }
159
161
163 {
164 if (this != &other) {
166 m_iterable = std::move(other.m_iterable);
167 m_iterator = std::move(other.m_iterator);
168 other.m_iterator = nullptr;
169 }
170 return *this;
171 }
172
174 {
175 if (this != &other) {
177 m_iterable = other.m_iterable;
178 initIterator(other.m_iterator);
179 }
180 return *this;
181 }
182
183 QIterable<Container> *mutableIterable() const
184 {
185 return m_iterable.mutablePointer();
186 }
187
188 const QIterable<Container> *constIterable() const
189 {
190 return m_iterable.constPointer();
191 }
192
193 void initIterator(const void *copy)
194 {
195 if (!copy)
196 return;
197 if (auto *mutableIt = mutableIterable()) {
198 m_iterator = metaContainer().begin(mutableIt->mutableIterable());
199 metaContainer().copyIterator(m_iterator, copy);
200 } else if (auto *constIt = constIterable()) {
201 m_iterator = metaContainer().constBegin(constIt->constIterable());
202 metaContainer().copyConstIterator(m_iterator, copy);
203 }
204 }
205
207 {
208 if (!m_iterator)
209 return;
211 metaContainer().destroyIterator(m_iterator);
212 else
213 metaContainer().destroyConstIterator(m_iterator);
214 }
215
216public:
217 void *mutableIterator() { return m_iterator; }
218 const void *constIterator() const { return m_iterator; }
219 Container metaContainer() const { return constIterable()->m_metaContainer; }
220};
221
222template<class Container>
223struct QIterator : public QBaseIterator<Container>
224{
225public:
227
228 explicit QIterator(QIterable<Container> *iterable, void *iterator)
229 : QBaseIterator<Container>(iterable, iterator)
230 {
231 Q_ASSERT(iterable != nullptr);
232 }
233
234 bool operator==(const QIterator &o) const
235 {
236 return this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
237 }
238
239 bool operator!=(const QIterator &o) const
240 {
241 return !this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
242 }
243
245 {
246 this->metaContainer().advanceIterator(this->mutableIterator(), 1);
247 return *this;
248 }
249
251 {
252 QIterable<Container> *iterable = this->mutableIterable();
253 const Container metaContainer = this->metaContainer();
254 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
255 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
256 metaContainer.advanceIterator(this->mutableIterator(), 1);
257 return result;
258 }
259
261 {
262 this->metaContainer().advanceIterator(this->mutableIterator(), -1);
263 return *this;
264 }
265
267 {
268 QIterable<Container> *iterable = this->mutableIterable();
269 const Container metaContainer = this->metaContainer();
270 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
271 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
272 metaContainer.advanceIterator(this->mutableIterator(), -1);
273 return result;
274 }
275
276 QIterator &operator+=(qsizetype j)
277 {
278 this->metaContainer().advanceIterator(this->mutableIterator(), j);
279 return *this;
280 }
281
282 QIterator &operator-=(qsizetype j)
283 {
284 this->metaContainer().advanceIterator(this->mutableIterator(), -j);
285 return *this;
286 }
287
288 QIterator operator+(qsizetype j) const
289 {
290 QIterable<Container> *iterable = this->mutableIterable();
291 const Container metaContainer = this->metaContainer();
292 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
293 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
294 metaContainer.advanceIterator(result.mutableIterator(), j);
295 return result;
296 }
297
298 QIterator operator-(qsizetype j) const
299 {
300 QIterable<Container> *iterable = this->mutableIterable();
301 const Container metaContainer = this->metaContainer();
302 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
303 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
304 metaContainer.advanceIterator(result.mutableIterator(), -j);
305 return result;
306 }
307
308 qsizetype operator-(const QIterator &j) const
309 {
310 return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
311 }
312
313 friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; }
314};
315
316template<class Container>
317struct QConstIterator : public QBaseIterator<Container>
318{
319public:
321
322 explicit QConstIterator(const QIterable<Container> *iterable, void *iterator)
323 : QBaseIterator<Container>(iterable, iterator)
324 {
325 }
326
327 bool operator==(const QConstIterator &o) const
328 {
329 return this->metaContainer().compareConstIterator(
330 this->constIterator(), o.constIterator());
331 }
332
333 bool operator!=(const QConstIterator &o) const
334 {
335 return !this->metaContainer().compareConstIterator(
336 this->constIterator(), o.constIterator());
337 }
338
340 {
341 this->metaContainer().advanceConstIterator(this->mutableIterator(), 1);
342 return *this;
343 }
344
346 {
347 const Container metaContainer = this->metaContainer();
348 QConstIterator result(this->constIterable(), metaContainer.constBegin(
349 this->constIterable()->constIterable()));
350 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
351 metaContainer.advanceConstIterator(this->mutableIterator(), 1);
352 return result;
353 }
354
356 {
357 this->metaContainer().advanceConstIterator(this->mutableIterator(), -1);
358 return *this;
359 }
360
362 {
363 const Container metaContainer = this->metaContainer();
364 QConstIterator result(this->constIterable(), metaContainer.constBegin(
365 this->constIterable()->constIterable()));
366 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
367 metaContainer.advanceConstIterator(this->mutableIterator(), -1);
368 return result;
369 }
370
371 QConstIterator &operator+=(qsizetype j)
372 {
373 this->metaContainer().advanceConstIterator(this->mutableIterator(), j);
374 return *this;
375 }
376
377 QConstIterator &operator-=(qsizetype j)
378 {
379 this->metaContainer().advanceConstIterator(this->mutableIterator(), -j);
380 return *this;
381 }
382
383 QConstIterator operator+(qsizetype j) const
384 {
385 const Container metaContainer = this->metaContainer();
386 QConstIterator result(
387 this->constIterable(),
388 metaContainer.constBegin(this->constIterable()->constIterable()));
389 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
390 metaContainer.advanceConstIterator(result.mutableIterator(), j);
391 return result;
392 }
393
394 QConstIterator operator-(qsizetype j) const
395 {
396 const Container metaContainer = this->metaContainer();
397 QConstIterator result(this->constIterable(), metaContainer.constBegin(
398 this->constIterable()->constIterable()));
399 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
400 metaContainer.advanceConstIterator(result.mutableIterator(), -j);
401 return result;
402 }
403
405 {
406 return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
407 }
408
409 friend inline QConstIterator operator+(qsizetype j, const QConstIterator &k)
410 {
411 return k + j;
412 }
413};
414
415template<class Container>
417{
418 friend class QBaseIterator<Container>;
419
420protected:
424
425public:
426 template<class T>
427 QIterable(const Container &metaContainer, const T *p)
428 : m_iterable(p), m_metaContainer(metaContainer)
429 {
430 }
431
432 template<class T>
433 QIterable(const Container &metaContainer, T *p)
434 : m_iterable(p), m_metaContainer(metaContainer)
435 {
436 }
437
438 template<typename Pointer>
439 QIterable(const Container &metaContainer, Pointer iterable)
440 : m_iterable(iterable), m_metaContainer(metaContainer)
441 {
442 }
443
444 QIterable(const Container &metaContainer, qsizetype alignment, const void *p)
445 : m_iterable(p, alignment), m_metaContainer(metaContainer)
446 {
447 }
448
449 QIterable(const Container &metaContainer, qsizetype alignment, void *p)
450 : m_iterable(p, alignment), m_metaContainer(metaContainer)
451 {
452 }
453
454 bool canInputIterate() const
455 {
456 return m_metaContainer.hasInputIterator();
457 }
458
459 bool canForwardIterate() const
460 {
461 return m_metaContainer.hasForwardIterator();
462 }
463
464 bool canReverseIterate() const
465 {
466 return m_metaContainer.hasBidirectionalIterator();
467 }
468
470 {
471 return m_metaContainer.hasRandomAccessIterator();
472 }
473
474 const void *constIterable() const { return m_iterable.constPointer(); }
475 void *mutableIterable() { return m_iterable.mutablePointer(); }
476
477 QConstIterator<Container> constBegin() const
478 {
479 return QConstIterator(this, m_metaContainer.constBegin(constIterable()));
480 }
481
482 QConstIterator<Container> constEnd() const
483 {
484 return QConstIterator(this, m_metaContainer.constEnd(constIterable()));
485 }
486
488 {
489 return QIterator(this, m_metaContainer.begin(mutableIterable()));
490 }
491
493 {
495 }
496
498 {
499 const void *container = constIterable();
500 if (m_metaContainer.hasSize())
501 return m_metaContainer.size(container);
502 if (!m_metaContainer.hasConstIterator())
503 return -1;
504
505 const void *begin = m_metaContainer.constBegin(container);
506 const void *end = m_metaContainer.constEnd(container);
507 const qsizetype size = m_metaContainer.diffConstIterator(end, begin);
508 m_metaContainer.destroyConstIterator(begin);
509 m_metaContainer.destroyConstIterator(end);
510 return size;
511 }
512
513 Container metaContainer() const
514 {
515 return m_metaContainer;
516 }
517};
518
519QT_END_NAMESPACE
520
521#endif // QITERABLE_H
\inmodule QtCore QBaseIterator forms the common base class for all iterators operating on subclasses ...
Definition qiterable.h:133
QBaseIterator(QBaseIterator &&other)
Definition qiterable.h:148
QBaseIterator & operator=(QBaseIterator &&other)
Definition qiterable.h:162
QBaseIterator(QIterable< Container > *iterable, void *iterator)
Definition qiterable.h:144
const QIterable< Container > * constIterable() const
Definition qiterable.h:188
const void * constIterator() const
Returns a const pointer to the internal native iterator.
Definition qiterable.h:218
void clearIterator()
Definition qiterable.h:206
Container metaContainer() const
Definition qiterable.h:219
QBaseIterator & operator=(const QBaseIterator &other)
Definition qiterable.h:173
void * mutableIterator()
Returns a non-const pointer to the internal native iterator.
Definition qiterable.h:217
QBaseIterator()=default
QIterable< Container > * mutableIterable() const
Definition qiterable.h:183
QBaseIterator(const QIterable< Container > *iterable, void *iterator)
Definition qiterable.h:140
QBaseIterator(const QBaseIterator &other)
Definition qiterable.h:154
void initIterator(const void *copy)
Definition qiterable.h:193
\inmodule QtCore
Definition qiterable.h:417
bool canForwardIterate() const
Returns whether it is possible to iterate over the container in forward direction.
Definition qiterable.h:459
uint m_revision
Definition qiterable.h:421
QIterable(const Container &metaContainer, Pointer iterable)
Definition qiterable.h:439
QConstIterator< Container > constEnd() const
Returns a Qterable::QConstIterator for the end of the container.
Definition qiterable.h:482
const void * constIterable() const
Definition qiterable.h:474
QIterator< Container > mutableEnd()
Returns a QSequentialIterable::iterator for the end of the container.
Definition qiterable.h:492
QIterable(const Container &metaContainer, qsizetype alignment, const void *p)
Definition qiterable.h:444
Container m_metaContainer
Definition qiterable.h:423
bool canReverseIterate() const
Returns whether it is possible to iterate over the container in reverse.
Definition qiterable.h:464
QIterable(const Container &metaContainer, const T *p)
Definition qiterable.h:427
QConstIterator< Container > constBegin() const
Returns a QConstIterator for the beginning of the container.
Definition qiterable.h:477
bool canInputIterate() const
Returns whether the container has an input iterator.
Definition qiterable.h:454
bool canRandomAccessIterate() const
Returns whether it is possible to efficiently skip over multiple values using and iterator.
Definition qiterable.h:469
void * mutableIterable()
Definition qiterable.h:475
Container metaContainer() const
Definition qiterable.h:513
QtPrivate::QConstPreservingPointer< void, quint16 > m_iterable
Definition qiterable.h:422
QIterable(const Container &metaContainer, T *p)
Definition qiterable.h:433
QIterable(const Container &metaContainer, qsizetype alignment, void *p)
Definition qiterable.h:449
qsizetype size() const
Returns the number of values in the container.
Definition qiterable.h:497
QIterator< Container > mutableBegin()
Returns a QIterator for the beginning of the container.
Definition qiterable.h:487
QTaggedIterator is a template class that wraps an iterator and exposes standard iterator traits.
Definition qiterable.h:71
QTaggedIterator & operator-=(qsizetype j)
Makes the iterator go back by j items.
Definition qiterable.h:115
friend QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k)
Returns an iterator to the item at j positions forward from iterator k.
Definition qiterable.h:125
bool operator<(const QTaggedIterator &j)
Definition qiterable.h:120
QTaggedIterator operator+(qsizetype j) const
Returns an iterator to the item at j positions forward from this iterator.
Definition qiterable.h:116
QTaggedIterator operator--(int x)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:113
bool operator!=(const QTaggedIterator &o) const
Returns true if other points to a different item than this iterator; otherwise returns false.
Definition qiterable.h:109
QTaggedIterator operator++(int x)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:111
bool operator<=(const QTaggedIterator &j)
Definition qiterable.h:123
bool operator==(const QTaggedIterator &o) const
Returns true if other points to the same item as this iterator; otherwise returns false.
Definition qiterable.h:108
QTaggedIterator & operator--()
The prefix {–} operator ({–it}) makes the preceding item current and returns an iterator to the new c...
Definition qiterable.h:112
QTaggedIterator & operator+=(qsizetype j)
Advances the iterator by j items.
Definition qiterable.h:114
QTaggedIterator & operator++()
The prefix {++} operator ({++it}) advances the iterator to the next item in the container and returns...
Definition qiterable.h:110
bool operator>(const QTaggedIterator &j)
Definition qiterable.h:122
QTaggedIterator operator-(qsizetype j) const
Returns an iterator to the item at j positions backward from this iterator.
Definition qiterable.h:117
QTaggedIterator(Iterator &&it)
Constructs a QTaggedIterator from an iterator or QConstIterator it.
Definition qiterable.h:74
IteratorCategory iterator_category
Definition qiterable.h:73
bool operator>=(const QTaggedIterator &j)
Definition qiterable.h:121
qsizetype operator-(const QTaggedIterator &j) const
Definition qiterable.h:118
const Type * constPointer() const
Definition qiterable.h:57
The QConstIterator allows iteration over a container in a QVariant.
Definition qiterable.h:318
bool operator==(const QConstIterator &o) const
Returns true if other points to the same item as this iterator; otherwise returns false.
Definition qiterable.h:327
QConstIterator & operator+=(qsizetype j)
Advances the iterator by j items.
Definition qiterable.h:371
QConstIterator(const QIterable< Container > *iterable, void *iterator)
Creates a QConstIterator to wrap iterator, operating on iterable.
Definition qiterable.h:322
QConstIterator operator++(int)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:345
friend QConstIterator operator+(qsizetype j, const QConstIterator &k)
Definition qiterable.h:409
QConstIterator operator+(qsizetype j) const
Returns an iterator to the item at j positions forward from this iterator.
Definition qiterable.h:383
QConstIterator operator--(int)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:361
bool operator!=(const QConstIterator &o) const
Returns true if other points to a different item than this iterator; otherwise returns false.
Definition qiterable.h:333
qsizetype operator-(const QConstIterator &j) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:404
QConstIterator & operator-=(qsizetype j)
Makes the iterator go back by j items.
Definition qiterable.h:377
QConstIterator & operator--()
The prefix {–} operator ({–it}) makes the preceding item current and returns an iterator to the new c...
Definition qiterable.h:355
QConstIterator & operator++()
The prefix {++} operator ({++it}) advances the iterator to the next item in the container and returns...
Definition qiterable.h:339
QConstIterator operator-(qsizetype j) const
Returns an iterator to the item at j positions backward from this iterator.
Definition qiterable.h:394
The QIterator is a template class that allows iteration over a container in a QVariant.
Definition qiterable.h:224
bool operator==(const QIterator &o) const
Returns true if other points to the same item as this iterator; otherwise returns false.
Definition qiterable.h:234
friend QIterator operator+(qsizetype j, const QIterator &k)
Returns an iterator to the item at j positions forward from iterator k.
Definition qiterable.h:313
QIterator & operator+=(qsizetype j)
Advances the iterator by j items.
Definition qiterable.h:276
bool operator!=(const QIterator &o) const
Returns true if other points to a different item than this iterator; otherwise returns false.
Definition qiterable.h:239
QIterator operator-(qsizetype j) const
Returns an iterator to the item at j positions backward from this iterator.
Definition qiterable.h:298
QIterator & operator--()
The prefix {–} operator ({–it}) makes the preceding item current and returns an iterator to the new c...
Definition qiterable.h:260
qsizetype operator-(const QIterator &j) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:308
QIterator & operator-=(qsizetype j)
Makes the iterator go back by j items.
Definition qiterable.h:282
QIterator(QIterable< Container > *iterable, void *iterator)
Creates an iterator from an iterable and a pointer to a native iterator.
Definition qiterable.h:228
QIterator operator++(int)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:250
QIterator operator+(qsizetype j) const
Returns an iterator to the item at j positions forward from this iterator.
Definition qiterable.h:288
QIterator & operator++()
The prefix {++} operator ({++it}) advances the iterator to the next item in the container and returns...
Definition qiterable.h:244
QIterator operator--(int)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qiterable.h:266