QtBase  v6.3.1
qiterable.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore 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 QITERABLE_H
41 #define QITERABLE_H
42 
43 #include <QtCore/qglobal.h>
44 #include <QtCore/qtypeinfo.h>
45 #include <QtCore/qmetacontainer.h>
46 #include <QtCore/qtaggedpointer.h>
47 
49 
50 namespace QtPrivate {
51  template<typename Type, typename Storage = Type>
53  {
54  enum Tag : bool { Const, Mutable };
56 
57  public:
58  QConstPreservingPointer(std::nullptr_t) : m_pointer(nullptr, Const) {}
59 
61  : m_pointer(reinterpret_cast<Storage *>(const_cast<void *>(pointer)), Const)
62  {
64  Q_ASSERT(alignment > qsizetype(alignof(Storage)));
65  }
66 
68  : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
69  {
71  Q_ASSERT(alignment > qsizetype(alignof(Storage)));
72  }
73 
74  template<typename InputType>
76  : m_pointer(reinterpret_cast<Storage *>(const_cast<InputType *>(pointer)), Const)
77  {
78  static_assert(alignof(InputType) >= alignof(Storage));
79  }
80 
81  template<typename InputType>
83  : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
84  {
85  static_assert(alignof(InputType) >= alignof(Storage));
86  }
87 
89 
90  const Type *constPointer() const
91  {
92  return reinterpret_cast<const Type *>(m_pointer.data());
93  }
94 
96  {
97  return m_pointer.tag() == Mutable ? reinterpret_cast<Type *>(m_pointer.data()) : nullptr;
98  }
99  };
100 }
101 
102 template<class Iterator, typename IteratorCategory>
103 class QTaggedIterator : public Iterator
104 {
105 public:
106  using iterator_category = IteratorCategory;
107  QTaggedIterator(Iterator &&it) : Iterator(std::move(it))
108  {
109  const QMetaContainer metaContainer = this->metaContainer();
110  if (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory>
111  && !metaContainer.hasRandomAccessIterator()) {
112  qFatal("You cannot use this iterator as a random access iterator");
113  this->clearIterator();
114  }
115 
116  if (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory>
117  && !metaContainer.hasBidirectionalIterator()) {
118  qFatal("You cannot use this iterator as a bidirectional iterator");
119  this->clearIterator();
120  }
121 
122  if (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory>
123  && !metaContainer.hasForwardIterator()) {
124  qFatal("You cannot use this iterator as a forward iterator");
125  this->clearIterator();
126  }
127 
128  if (std::is_base_of_v<std::input_iterator_tag, IteratorCategory>
129  && !metaContainer.hasInputIterator()) {
130  qFatal("You cannot use this iterator as an input iterator");
131  this->clearIterator();
132  }
133  }
134 
135  bool operator==(const QTaggedIterator &o) const { return Iterator::operator==(o); }
136  bool operator!=(const QTaggedIterator &o) const { return Iterator::operator!=(o); }
137  QTaggedIterator &operator++() { Iterator::operator++(); return *this; }
138  QTaggedIterator operator++(int x) { return QTaggedIterator(Iterator::operator++(x)); }
139  QTaggedIterator &operator--() { Iterator::operator--(); return *this; }
140  QTaggedIterator operator--(int x) { return QTaggedIterator(Iterator::operator--(x)); }
142  QTaggedIterator &operator-=(qsizetype j) { Iterator::operator-=(j); return *this; }
143  QTaggedIterator operator+(qsizetype j) const { return QTaggedIterator(Iterator::operator+(j)); }
144  QTaggedIterator operator-(qsizetype j) const { return QTaggedIterator(Iterator::operator-(j)); }
146 
147  bool operator<(const QTaggedIterator &j) { return operator-(j) < 0; }
148  bool operator>=(const QTaggedIterator &j) { return !operator<(j); }
149  bool operator>(const QTaggedIterator &j) { return operator-(j) > 0; }
150  bool operator<=(const QTaggedIterator &j) { return !operator>(j); }
151 
152  friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; }
153 };
154 
155 template<class Container>
156 class QIterable;
157 
158 template<class Container>
160 {
161 private:
163  void *m_iterator = nullptr;
164 
165 protected:
166  QBaseIterator() = default;
168  : m_iterable(iterable), m_iterator(iterator)
169  {}
170 
172  : m_iterable(iterable), m_iterator(iterator)
173  {}
174 
176  : m_iterable(std::move(other.m_iterable)), m_iterator(std::move(other.m_iterator))
177  {
178  other.m_iterator = nullptr;
179  }
180 
182  : m_iterable(other.m_iterable)
183  {
184  initIterator(other.m_iterator);
185  }
186 
188 
190  {
191  if (this != &other) {
192  clearIterator();
193  m_iterable = std::move(other.m_iterable);
194  m_iterator = std::move(other.m_iterator);
195  other.m_iterator = nullptr;
196  }
197  return *this;
198  }
199 
201  {
202  if (this != &other) {
203  clearIterator();
204  m_iterable = other.m_iterable;
205  initIterator(other.m_iterator);
206  }
207  return *this;
208  }
209 
211  {
212  return m_iterable.mutablePointer();
213  }
214 
216  {
217  return m_iterable.constPointer();
218  }
219 
220  void initIterator(const void *copy)
221  {
222  if (!copy)
223  return;
224  if (auto *mutableIt = mutableIterable()) {
225  m_iterator = metaContainer().begin(mutableIt->mutableIterable());
226  metaContainer().copyIterator(m_iterator, copy);
227  } else if (auto *constIt = constIterable()) {
228  m_iterator = metaContainer().constBegin(constIt->constIterable());
229  metaContainer().copyConstIterator(m_iterator, copy);
230  }
231  }
232 
234  {
235  if (!m_iterator)
236  return;
237  if (mutableIterable())
238  metaContainer().destroyIterator(m_iterator);
239  else
240  metaContainer().destroyConstIterator(m_iterator);
241  }
242 
243 public:
244  void *mutableIterator() { return m_iterator; }
245  const void *constIterator() const { return m_iterator; }
246  Container metaContainer() const { return constIterable()->m_metaContainer; }
247 };
248 
249 template<class Container>
250 struct QIterator : public QBaseIterator<Container>
251 {
252 public:
254 
255  explicit QIterator(QIterable<Container> *iterable, void *iterator)
256  : QBaseIterator<Container>(iterable, iterator)
257  {
258  Q_ASSERT(iterable != nullptr);
259  }
260 
261  bool operator==(const QIterator &o) const
262  {
263  return this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
264  }
265 
266  bool operator!=(const QIterator &o) const
267  {
268  return !this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
269  }
270 
272  {
273  this->metaContainer().advanceIterator(this->mutableIterator(), 1);
274  return *this;
275  }
276 
278  {
279  QIterable<Container> *iterable = this->mutableIterable();
280  const Container metaContainer = this->metaContainer();
281  QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
282  metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
283  metaContainer.advanceIterator(this->mutableIterator(), 1);
284  return result;
285  }
286 
288  {
289  this->metaContainer().advanceIterator(this->mutableIterator(), -1);
290  return *this;
291  }
292 
294  {
295  QIterable<Container> *iterable = this->mutableIterable();
296  const Container metaContainer = this->metaContainer();
297  QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
298  metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
299  metaContainer.advanceIterator(this->mutableIterator(), -1);
300  return result;
301  }
302 
304  {
305  this->metaContainer().advanceIterator(this->mutableIterator(), j);
306  return *this;
307  }
308 
310  {
311  this->metaContainer().advanceIterator(this->mutableIterator(), -j);
312  return *this;
313  }
314 
316  {
317  QIterable<Container> *iterable = this->mutableIterable();
318  const Container metaContainer = this->metaContainer();
319  QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
320  metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
321  metaContainer.advanceIterator(result.mutableIterator(), j);
322  return result;
323  }
324 
326  {
327  QIterable<Container> *iterable = this->mutableIterable();
328  const Container metaContainer = this->metaContainer();
329  QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
330  metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
331  metaContainer.advanceIterator(result.mutableIterator(), -j);
332  return result;
333  }
334 
336  {
337  return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
338  }
339 
340  friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; }
341 };
342 
343 template<class Container>
344 struct QConstIterator : public QBaseIterator<Container>
345 {
346 public:
348 
349  explicit QConstIterator(const QIterable<Container> *iterable, void *iterator)
350  : QBaseIterator<Container>(iterable, iterator)
351  {
352  }
353 
354  bool operator==(const QConstIterator &o) const
355  {
356  return this->metaContainer().compareConstIterator(
357  this->constIterator(), o.constIterator());
358  }
359 
360  bool operator!=(const QConstIterator &o) const
361  {
362  return !this->metaContainer().compareConstIterator(
363  this->constIterator(), o.constIterator());
364  }
365 
367  {
368  this->metaContainer().advanceConstIterator(this->mutableIterator(), 1);
369  return *this;
370  }
371 
373  {
374  const Container metaContainer = this->metaContainer();
375  QConstIterator result(this->constIterable(), metaContainer.constBegin(
376  this->constIterable()->constIterable()));
377  metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
378  metaContainer.advanceConstIterator(this->mutableIterator(), 1);
379  return result;
380  }
381 
383  {
384  this->metaContainer().advanceConstIterator(this->mutableIterator(), -1);
385  return *this;
386  }
387 
389  {
390  const Container metaContainer = this->metaContainer();
391  QConstIterator result(this->constIterable(), metaContainer.constBegin(
392  this->constIterable()->constIterable()));
393  metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
394  metaContainer.advanceConstIterator(this->mutableIterator(), -1);
395  return result;
396  }
397 
399  {
400  this->metaContainer().advanceConstIterator(this->mutableIterator(), j);
401  return *this;
402  }
403 
405  {
406  this->metaContainer().advanceConstIterator(this->mutableIterator(), -j);
407  return *this;
408  }
409 
411  {
412  const Container metaContainer = this->metaContainer();
414  this->constIterable(),
415  metaContainer.constBegin(this->constIterable()->constIterable()));
416  metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
417  metaContainer.advanceConstIterator(result.mutableIterator(), j);
418  return result;
419  }
420 
422  {
423  const Container metaContainer = this->metaContainer();
424  QConstIterator result(this->constIterable(), metaContainer.constBegin(
425  this->constIterable()->constIterable()));
426  metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
427  metaContainer.advanceConstIterator(result.mutableIterator(), -j);
428  return result;
429  }
430 
432  {
433  return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
434  }
435 
437  {
438  return k + j;
439  }
440 };
441 
442 template<class Container>
444 {
445  friend class QBaseIterator<Container>;
446 
447 protected:
451 
452 public:
453  template<class T>
456  {
457  }
458 
459  template<class T>
462  {
463  }
464 
465  template<typename Pointer>
468  {
469  }
470 
473  {
474  }
475 
478  {
479  }
480 
481  bool canInputIterate() const
482  {
483  return m_metaContainer.hasInputIterator();
484  }
485 
486  bool canForwardIterate() const
487  {
488  return m_metaContainer.hasForwardIterator();
489  }
490 
491  bool canReverseIterate() const
492  {
493  return m_metaContainer.hasBidirectionalIterator();
494  }
495 
497  {
498  return m_metaContainer.hasRandomAccessIterator();
499  }
500 
501  const void *constIterable() const { return m_iterable.constPointer(); }
503 
505  {
506  return QConstIterator(this, m_metaContainer.constBegin(constIterable()));
507  }
508 
510  {
511  return QConstIterator(this, m_metaContainer.constEnd(constIterable()));
512  }
513 
515  {
516  return QIterator(this, m_metaContainer.begin(mutableIterable()));
517  }
518 
520  {
521  return QIterator(this, m_metaContainer.end(mutableIterable()));
522  }
523 
524  qsizetype size() const
525  {
526  const void *container = constIterable();
527  if (m_metaContainer.hasSize())
528  return m_metaContainer.size(container);
529  if (!m_metaContainer.hasConstIterator())
530  return -1;
531 
532  const void *begin = m_metaContainer.constBegin(container);
533  const void *end = m_metaContainer.constEnd(container);
534  const qsizetype size = m_metaContainer.diffConstIterator(end, begin);
535  m_metaContainer.destroyConstIterator(begin);
536  m_metaContainer.destroyConstIterator(end);
537  return size;
538  }
539 
541  {
542  return m_metaContainer;
543  }
544 };
545 
547 
548 #endif // QITERABLE_H
void * mutableIterator()
Definition: qiterable.h:244
const void * constIterator() const
Definition: qiterable.h:245
const QIterable< Container > * constIterable() const
Definition: qiterable.h:215
QBaseIterator & operator=(QBaseIterator &&other)
Definition: qiterable.h:189
void clearIterator()
Definition: qiterable.h:233
QBaseIterator(const QIterable< Container > *iterable, void *iterator)
Definition: qiterable.h:167
QBaseIterator(QBaseIterator &&other)
Definition: qiterable.h:175
QBaseIterator & operator=(const QBaseIterator &other)
Definition: qiterable.h:200
void initIterator(const void *copy)
Definition: qiterable.h:220
QBaseIterator(const QBaseIterator &other)
Definition: qiterable.h:181
QBaseIterator(QIterable< Container > *iterable, void *iterator)
Definition: qiterable.h:171
QBaseIterator()=default
QIterable< Container > * mutableIterable() const
Definition: qiterable.h:210
Container metaContainer() const
Definition: qiterable.h:246
QIterable is a template class that is the base class for QSequentialIterable and QAssociativeIterable...
Definition: qiterable.h:444
qsizetype size() const
Definition: qiterable.h:524
uint m_revision
Definition: qiterable.h:448
bool canRandomAccessIterate() const
Definition: qiterable.h:496
QConstIterator< Container > constBegin() const
Definition: qiterable.h:504
QIterable(const Container &metaContainer, Pointer iterable)
Definition: qiterable.h:466
bool canInputIterate() const
Definition: qiterable.h:481
QIterator< Container > mutableEnd()
Definition: qiterable.h:519
QIterable(const Container &metaContainer, qsizetype alignment, const void *p)
Definition: qiterable.h:471
Container m_metaContainer
Definition: qiterable.h:450
QIterable(const Container &metaContainer, const T *p)
Definition: qiterable.h:454
void * mutableIterable()
Definition: qiterable.h:502
QIterator< Container > mutableBegin()
Definition: qiterable.h:514
Container metaContainer() const
Definition: qiterable.h:540
QtPrivate::QConstPreservingPointer< void, quint16 > m_iterable
Definition: qiterable.h:449
QIterable(const Container &metaContainer, T *p)
Definition: qiterable.h:460
const void * constIterable() const
Definition: qiterable.h:501
bool canForwardIterate() const
Definition: qiterable.h:486
QIterable(const Container &metaContainer, qsizetype alignment, void *p)
Definition: qiterable.h:476
bool canReverseIterate() const
Definition: qiterable.h:491
QConstIterator< Container > constEnd() const
Definition: qiterable.h:509
bool hasRandomAccessIterator() const
bool hasInputIterator() const
bool hasBidirectionalIterator() const
bool hasForwardIterator() const
QTaggedIterator is a template class that wraps an iterator and exposes standard iterator traits.
Definition: qiterable.h:104
bool operator!=(const QTaggedIterator &o) const
Definition: qiterable.h:136
QTaggedIterator & operator++()
Definition: qiterable.h:137
bool operator<(const QTaggedIterator &j)
Definition: qiterable.h:147
QTaggedIterator & operator-=(qsizetype j)
Definition: qiterable.h:142
friend QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k)
Definition: qiterable.h:152
QTaggedIterator(Iterator &&it)
Definition: qiterable.h:107
bool operator<=(const QTaggedIterator &j)
Definition: qiterable.h:150
QTaggedIterator operator+(qsizetype j) const
Definition: qiterable.h:143
qsizetype operator-(const QTaggedIterator &j) const
Definition: qiterable.h:145
QTaggedIterator & operator+=(qsizetype j)
Definition: qiterable.h:141
bool operator>(const QTaggedIterator &j)
Definition: qiterable.h:149
QTaggedIterator operator--(int x)
Definition: qiterable.h:140
QTaggedIterator operator-(qsizetype j) const
Definition: qiterable.h:144
QTaggedIterator operator++(int x)
Definition: qiterable.h:138
QTaggedIterator & operator--()
Definition: qiterable.h:139
bool operator==(const QTaggedIterator &o) const
Definition: qiterable.h:135
IteratorCategory iterator_category
Definition: qiterable.h:106
bool operator>=(const QTaggedIterator &j)
Definition: qiterable.h:148
T * data() const noexcept
Tag tag() const noexcept
QConstPreservingPointer(const void *pointer, qsizetype alignment)
Definition: qiterable.h:60
QConstPreservingPointer(const InputType *pointer)
Definition: qiterable.h:75
QConstPreservingPointer(void *pointer, qsizetype alignment)
Definition: qiterable.h:67
const Type * constPointer() const
Definition: qiterable.h:90
QConstPreservingPointer(std::nullptr_t)
Definition: qiterable.h:58
QConstPreservingPointer(InputType *pointer)
Definition: qiterable.h:82
#define this
Definition: dialogs.cpp:56
uint alignment
int InputType
Definition: global.h:39
typename C::iterator iterator
Definition: qfloat16.h:381
void
Definition: png.h:1080
QString & operator+=(QString &that, const ProString &other)
Definition: proitems.h:262
constexpr bool operator!=(const timespec &t1, const timespec &t2)
Definition: qcore_unix_p.h:124
constexpr timespec operator-(const timespec &t1, const timespec &t2)
Definition: qcore_unix_p.h:139
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned int uint
Definition: qglobal.h:334
#define qFatal
Definition: qlogging.h:181
bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two)
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLsizei const void * pointer
Definition: qopenglext.h:384
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
Q_UNUSED(salary)
[21]
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QStringList::Iterator it
The QConstIterator allows iteration over a container in a QVariant.
Definition: qiterable.h:345
bool operator==(const QConstIterator &o) const
Definition: qiterable.h:354
QConstIterator operator--(int)
Definition: qiterable.h:388
QConstIterator operator-(qsizetype j) const
Definition: qiterable.h:421
QConstIterator & operator--()
Definition: qiterable.h:382
QConstIterator operator+(qsizetype j) const
Definition: qiterable.h:410
friend QConstIterator operator+(qsizetype j, const QConstIterator &k)
Definition: qiterable.h:436
qsizetype difference_type
Definition: qiterable.h:347
QConstIterator & operator++()
Definition: qiterable.h:366
qsizetype operator-(const QConstIterator &j) const
Definition: qiterable.h:431
QConstIterator & operator+=(qsizetype j)
Definition: qiterable.h:398
QConstIterator(const QIterable< Container > *iterable, void *iterator)
Definition: qiterable.h:349
QConstIterator operator++(int)
Definition: qiterable.h:372
bool operator!=(const QConstIterator &o) const
Definition: qiterable.h:360
QConstIterator & operator-=(qsizetype j)
Definition: qiterable.h:404
The QIterator is a template class that allows iteration over a container in a QVariant.
Definition: qiterable.h:251
bool operator!=(const QIterator &o) const
Definition: qiterable.h:266
QIterator & operator++()
Definition: qiterable.h:271
QIterator & operator-=(qsizetype j)
Definition: qiterable.h:309
QIterator operator++(int)
Definition: qiterable.h:277
qsizetype operator-(const QIterator &j) const
Definition: qiterable.h:335
QIterator & operator+=(qsizetype j)
Definition: qiterable.h:303
QIterator(QIterable< Container > *iterable, void *iterator)
Definition: qiterable.h:255
QIterator operator+(qsizetype j) const
Definition: qiterable.h:315
QIterator operator--(int)
Definition: qiterable.h:293
QIterator & operator--()
Definition: qiterable.h:287
qsizetype difference_type
Definition: qiterable.h:253
bool operator==(const QIterator &o) const
Definition: qiterable.h:261
friend QIterator operator+(qsizetype j, const QIterator &k)
Definition: qiterable.h:340
QIterator operator-(qsizetype j) const
Definition: qiterable.h:325
Definition: main.cpp:38
Definition: data.cpp:95
Definition: moc.h:48