File indexing completed on 2026-09-22 09:02:12
0001
0002
0003
0004
0005 #ifndef QITERABLE_H
0006 #define QITERABLE_H
0007
0008 #include <QtCore/qglobal.h>
0009 #include <QtCore/qtypeinfo.h>
0010 #include <QtCore/qtaggedpointer.h>
0011
0012 QT_BEGIN_NAMESPACE
0013
0014 namespace QtPrivate {
0015 template<typename Type, typename Storage = Type>
0016 class QConstPreservingPointer
0017 {
0018 enum Tag : bool { Const, Mutable };
0019 QTaggedPointer<Storage, Tag> m_pointer;
0020
0021 public:
0022 Q_NODISCARD_CTOR QConstPreservingPointer(std::nullptr_t) : m_pointer(nullptr, Const) {}
0023
0024 Q_NODISCARD_CTOR QConstPreservingPointer(const void *pointer, qsizetype alignment)
0025 : m_pointer(reinterpret_cast<Storage *>(const_cast<void *>(pointer)), Const)
0026 {
0027 Q_UNUSED(alignment);
0028 Q_ASSERT(alignment > qsizetype(alignof(Storage)));
0029 }
0030
0031 Q_NODISCARD_CTOR QConstPreservingPointer(void *pointer, qsizetype alignment)
0032 : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
0033 {
0034 Q_UNUSED(alignment);
0035 Q_ASSERT(alignment > qsizetype(alignof(Storage)));
0036 }
0037
0038 template<typename InputType>
0039 Q_NODISCARD_CTOR QConstPreservingPointer(const InputType *pointer)
0040 : m_pointer(reinterpret_cast<Storage *>(const_cast<InputType *>(pointer)), Const)
0041 {
0042 static_assert(alignof(InputType) >= alignof(Storage));
0043 }
0044
0045 template<typename InputType>
0046 Q_NODISCARD_CTOR QConstPreservingPointer(InputType *pointer)
0047 : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
0048 {
0049 static_assert(alignof(InputType) >= alignof(Storage));
0050 }
0051
0052 Q_NODISCARD_CTOR QConstPreservingPointer() = default;
0053
0054 const Type *constPointer() const
0055 {
0056 return reinterpret_cast<const Type *>(m_pointer.data());
0057 }
0058
0059 Type *mutablePointer() const
0060 {
0061 return m_pointer.tag() == Mutable ? reinterpret_cast<Type *>(m_pointer.data()) : nullptr;
0062 }
0063 };
0064
0065 enum class SynthesizedAccessFunction: quint8
0066 {
0067 IterableSize,
0068 SequenceAt
0069 };
0070
0071 Q_CORE_EXPORT void warnSynthesizedIterableAccess(SynthesizedAccessFunction function);
0072 }
0073
0074 template<class Iterator, typename IteratorCategory>
0075 class QTaggedIterator : public Iterator
0076 {
0077 public:
0078 using iterator_category = IteratorCategory;
0079 QTaggedIterator(Iterator &&it) : Iterator(std::move(it))
0080 {
0081 [[maybe_unused]] const auto metaContainer = this->metaContainer();
0082 if constexpr (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory>) {
0083 if (!metaContainer.hasRandomAccessIterator()) {
0084 qFatal("You cannot use this iterator as a random access iterator");
0085 this->clearIterator();
0086 }
0087 }
0088
0089 if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory>) {
0090 if (!metaContainer.hasBidirectionalIterator()) {
0091 qFatal("You cannot use this iterator as a bidirectional iterator");
0092 this->clearIterator();
0093 }
0094 }
0095
0096 if constexpr (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory>) {
0097 if (!metaContainer.hasForwardIterator()) {
0098 qFatal("You cannot use this iterator as a forward iterator");
0099 this->clearIterator();
0100 }
0101 }
0102
0103 if constexpr (std::is_base_of_v<std::input_iterator_tag, IteratorCategory>) {
0104 if (!metaContainer.hasInputIterator()) {
0105 qFatal("You cannot use this iterator as an input iterator");
0106 this->clearIterator();
0107 }
0108 }
0109 }
0110
0111 bool operator==(const QTaggedIterator &o) const { return Iterator::operator==(o); }
0112 bool operator!=(const QTaggedIterator &o) const { return Iterator::operator!=(o); }
0113 QTaggedIterator &operator++() { Iterator::operator++(); return *this; }
0114 QTaggedIterator operator++(int x) { return QTaggedIterator(Iterator::operator++(x)); }
0115 QTaggedIterator &operator--() { Iterator::operator--(); return *this; }
0116 QTaggedIterator operator--(int x) { return QTaggedIterator(Iterator::operator--(x)); }
0117 QTaggedIterator &operator+=(qsizetype j) { Iterator::operator+=(j); return *this; }
0118 QTaggedIterator &operator-=(qsizetype j) { Iterator::operator-=(j); return *this; }
0119 QTaggedIterator operator+(qsizetype j) const { return QTaggedIterator(Iterator::operator+(j)); }
0120 QTaggedIterator operator-(qsizetype j) const { return QTaggedIterator(Iterator::operator-(j)); }
0121 qsizetype operator-(const QTaggedIterator &j) const { return Iterator::operator-(j); }
0122
0123 bool operator<(const QTaggedIterator &j) { return operator-(j) < 0; }
0124 bool operator>=(const QTaggedIterator &j) { return !operator<(j); }
0125 bool operator>(const QTaggedIterator &j) { return operator-(j) > 0; }
0126 bool operator<=(const QTaggedIterator &j) { return !operator>(j); }
0127
0128 friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; }
0129 };
0130
0131 template<class Container>
0132 class QIterable;
0133
0134 template<class Container>
0135 class QBaseIterator
0136 {
0137 private:
0138 QtPrivate::QConstPreservingPointer<QIterable<Container>> m_iterable;
0139 void *m_iterator = nullptr;
0140
0141 protected:
0142 QBaseIterator() = default;
0143 QBaseIterator(const QIterable<Container> *iterable, void *iterator)
0144 : m_iterable(iterable), m_iterator(iterator)
0145 {}
0146
0147 QBaseIterator(QIterable<Container> *iterable, void *iterator)
0148 : m_iterable(iterable), m_iterator(iterator)
0149 {}
0150
0151 QBaseIterator(QBaseIterator &&other)
0152 : m_iterable(std::move(other.m_iterable)), m_iterator(std::move(other.m_iterator))
0153 {
0154 other.m_iterator = nullptr;
0155 }
0156
0157 QBaseIterator(const QBaseIterator &other)
0158 : m_iterable(other.m_iterable)
0159 {
0160 initIterator(other.m_iterator);
0161 }
0162
0163 ~QBaseIterator() { clearIterator(); }
0164
0165 QBaseIterator &operator=(QBaseIterator &&other)
0166 {
0167 if (this != &other) {
0168 clearIterator();
0169 m_iterable = std::move(other.m_iterable);
0170 m_iterator = std::move(other.m_iterator);
0171 other.m_iterator = nullptr;
0172 }
0173 return *this;
0174 }
0175
0176 QBaseIterator &operator=(const QBaseIterator &other)
0177 {
0178 if (this != &other) {
0179 clearIterator();
0180 m_iterable = other.m_iterable;
0181 initIterator(other.m_iterator);
0182 }
0183 return *this;
0184 }
0185
0186 QIterable<Container> *mutableIterable() const
0187 {
0188 return m_iterable.mutablePointer();
0189 }
0190
0191 const QIterable<Container> *constIterable() const
0192 {
0193 return m_iterable.constPointer();
0194 }
0195
0196 void initIterator(const void *copy)
0197 {
0198 if (!copy)
0199 return;
0200 if (auto *mutableIt = mutableIterable()) {
0201 m_iterator = metaContainer().begin(mutableIt->mutableIterable());
0202 metaContainer().copyIterator(m_iterator, copy);
0203 } else if (auto *constIt = constIterable()) {
0204 m_iterator = metaContainer().constBegin(constIt->constIterable());
0205 metaContainer().copyConstIterator(m_iterator, copy);
0206 }
0207 }
0208
0209 void clearIterator()
0210 {
0211 if (!m_iterator)
0212 return;
0213 if (mutableIterable())
0214 metaContainer().destroyIterator(m_iterator);
0215 else
0216 metaContainer().destroyConstIterator(m_iterator);
0217 }
0218
0219 public:
0220 void *mutableIterator() { return m_iterator; }
0221 const void *constIterator() const { return m_iterator; }
0222 Container metaContainer() const { return constIterable()->m_metaContainer; }
0223 };
0224
0225 template<class Container>
0226 struct QIterator : public QBaseIterator<Container>
0227 {
0228 public:
0229 using difference_type = qsizetype;
0230
0231 explicit QIterator(QIterable<Container> *iterable, void *iterator)
0232 : QBaseIterator<Container>(iterable, iterator)
0233 {
0234 Q_ASSERT(iterable != nullptr);
0235 }
0236
0237 bool operator==(const QIterator &o) const
0238 {
0239 return this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
0240 }
0241
0242 bool operator!=(const QIterator &o) const
0243 {
0244 return !this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
0245 }
0246
0247 QIterator &operator++()
0248 {
0249 this->metaContainer().advanceIterator(this->mutableIterator(), 1);
0250 return *this;
0251 }
0252
0253 QIterator operator++(int)
0254 {
0255 QIterable<Container> *iterable = this->mutableIterable();
0256 const Container metaContainer = this->metaContainer();
0257 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
0258 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
0259 metaContainer.advanceIterator(this->mutableIterator(), 1);
0260 return result;
0261 }
0262
0263 QIterator &operator--()
0264 {
0265 this->metaContainer().advanceIterator(this->mutableIterator(), -1);
0266 return *this;
0267 }
0268
0269 QIterator operator--(int)
0270 {
0271 QIterable<Container> *iterable = this->mutableIterable();
0272 const Container metaContainer = this->metaContainer();
0273 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
0274 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
0275 metaContainer.advanceIterator(this->mutableIterator(), -1);
0276 return result;
0277 }
0278
0279 QIterator &operator+=(qsizetype j)
0280 {
0281 this->metaContainer().advanceIterator(this->mutableIterator(), j);
0282 return *this;
0283 }
0284
0285 QIterator &operator-=(qsizetype j)
0286 {
0287 this->metaContainer().advanceIterator(this->mutableIterator(), -j);
0288 return *this;
0289 }
0290
0291 QIterator operator+(qsizetype j) const
0292 {
0293 QIterable<Container> *iterable = this->mutableIterable();
0294 const Container metaContainer = this->metaContainer();
0295 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
0296 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
0297 metaContainer.advanceIterator(result.mutableIterator(), j);
0298 return result;
0299 }
0300
0301 QIterator operator-(qsizetype j) const
0302 {
0303 QIterable<Container> *iterable = this->mutableIterable();
0304 const Container metaContainer = this->metaContainer();
0305 QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
0306 metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
0307 metaContainer.advanceIterator(result.mutableIterator(), -j);
0308 return result;
0309 }
0310
0311 qsizetype operator-(const QIterator &j) const
0312 {
0313 return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
0314 }
0315
0316 friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; }
0317 };
0318
0319 template<class Container>
0320 struct QConstIterator : public QBaseIterator<Container>
0321 {
0322 public:
0323 using difference_type = qsizetype;
0324
0325 explicit QConstIterator(const QIterable<Container> *iterable, void *iterator)
0326 : QBaseIterator<Container>(iterable, iterator)
0327 {
0328 }
0329
0330 bool operator==(const QConstIterator &o) const
0331 {
0332 return this->metaContainer().compareConstIterator(
0333 this->constIterator(), o.constIterator());
0334 }
0335
0336 bool operator!=(const QConstIterator &o) const
0337 {
0338 return !this->metaContainer().compareConstIterator(
0339 this->constIterator(), o.constIterator());
0340 }
0341
0342 QConstIterator &operator++()
0343 {
0344 this->metaContainer().advanceConstIterator(this->mutableIterator(), 1);
0345 return *this;
0346 }
0347
0348 QConstIterator operator++(int)
0349 {
0350 const Container metaContainer = this->metaContainer();
0351 QConstIterator result(this->constIterable(), metaContainer.constBegin(
0352 this->constIterable()->constIterable()));
0353 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
0354 metaContainer.advanceConstIterator(this->mutableIterator(), 1);
0355 return result;
0356 }
0357
0358 QConstIterator &operator--()
0359 {
0360 this->metaContainer().advanceConstIterator(this->mutableIterator(), -1);
0361 return *this;
0362 }
0363
0364 QConstIterator operator--(int)
0365 {
0366 const Container metaContainer = this->metaContainer();
0367 QConstIterator result(this->constIterable(), metaContainer.constBegin(
0368 this->constIterable()->constIterable()));
0369 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
0370 metaContainer.advanceConstIterator(this->mutableIterator(), -1);
0371 return result;
0372 }
0373
0374 QConstIterator &operator+=(qsizetype j)
0375 {
0376 this->metaContainer().advanceConstIterator(this->mutableIterator(), j);
0377 return *this;
0378 }
0379
0380 QConstIterator &operator-=(qsizetype j)
0381 {
0382 this->metaContainer().advanceConstIterator(this->mutableIterator(), -j);
0383 return *this;
0384 }
0385
0386 QConstIterator operator+(qsizetype j) const
0387 {
0388 const Container metaContainer = this->metaContainer();
0389 QConstIterator result(
0390 this->constIterable(),
0391 metaContainer.constBegin(this->constIterable()->constIterable()));
0392 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
0393 metaContainer.advanceConstIterator(result.mutableIterator(), j);
0394 return result;
0395 }
0396
0397 QConstIterator operator-(qsizetype j) const
0398 {
0399 const Container metaContainer = this->metaContainer();
0400 QConstIterator result(this->constIterable(), metaContainer.constBegin(
0401 this->constIterable()->constIterable()));
0402 metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
0403 metaContainer.advanceConstIterator(result.mutableIterator(), -j);
0404 return result;
0405 }
0406
0407 qsizetype operator-(const QConstIterator &j) const
0408 {
0409 return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
0410 }
0411
0412 friend inline QConstIterator operator+(qsizetype j, const QConstIterator &k)
0413 {
0414 return k + j;
0415 }
0416 };
0417
0418 template<class Container>
0419 class QIterable
0420 {
0421 friend class QBaseIterator<Container>;
0422
0423 protected:
0424 uint m_revision = 0;
0425 QtPrivate::QConstPreservingPointer<void, quint16> m_iterable;
0426 Container m_metaContainer;
0427
0428 public:
0429 template<class T>
0430 QIterable(const Container &metaContainer, const T *p)
0431 : m_iterable(p), m_metaContainer(metaContainer)
0432 {
0433 }
0434
0435 template<class T>
0436 QIterable(const Container &metaContainer, T *p)
0437 : m_iterable(p), m_metaContainer(metaContainer)
0438 {
0439 }
0440
0441 template<typename Pointer>
0442 QIterable(const Container &metaContainer, Pointer iterable)
0443 : m_iterable(iterable), m_metaContainer(metaContainer)
0444 {
0445 }
0446
0447 QIterable(const Container &metaContainer, qsizetype alignment, const void *p)
0448 : m_iterable(p, alignment), m_metaContainer(metaContainer)
0449 {
0450 }
0451
0452 QIterable(const Container &metaContainer, qsizetype alignment, void *p)
0453 : m_iterable(p, alignment), m_metaContainer(metaContainer)
0454 {
0455 }
0456
0457 bool canInputIterate() const
0458 {
0459 return m_metaContainer.hasInputIterator();
0460 }
0461
0462 bool canForwardIterate() const
0463 {
0464 return m_metaContainer.hasForwardIterator();
0465 }
0466
0467 bool canReverseIterate() const
0468 {
0469 return m_metaContainer.hasBidirectionalIterator();
0470 }
0471
0472 bool canRandomAccessIterate() const
0473 {
0474 return m_metaContainer.hasRandomAccessIterator();
0475 }
0476
0477 const void *constIterable() const { return m_iterable.constPointer(); }
0478 void *mutableIterable() { return m_iterable.mutablePointer(); }
0479
0480 QConstIterator<Container> constBegin() const
0481 {
0482 return QConstIterator(this, m_metaContainer.constBegin(constIterable()));
0483 }
0484
0485 QConstIterator<Container> constEnd() const
0486 {
0487 return QConstIterator(this, m_metaContainer.constEnd(constIterable()));
0488 }
0489
0490 QIterator<Container> mutableBegin()
0491 {
0492 return QIterator(this, m_metaContainer.begin(mutableIterable()));
0493 }
0494
0495 QIterator<Container> mutableEnd()
0496 {
0497 return QIterator(this, m_metaContainer.end(mutableIterable()));
0498 }
0499
0500 qsizetype size() const
0501 {
0502 const void *container = constIterable();
0503 if (m_metaContainer.hasSize())
0504 return m_metaContainer.size(container);
0505
0506 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
0507
0508 return -1;
0509 #else
0510 QtPrivate::warnSynthesizedIterableAccess(
0511 QtPrivate::SynthesizedAccessFunction::IterableSize);
0512
0513 if (!m_metaContainer.hasConstIterator())
0514 return -1;
0515
0516 const void *begin = m_metaContainer.constBegin(container);
0517 const void *end = m_metaContainer.constEnd(container);
0518 const qsizetype size = m_metaContainer.diffConstIterator(end, begin);
0519 m_metaContainer.destroyConstIterator(begin);
0520 m_metaContainer.destroyConstIterator(end);
0521 return size;
0522 #endif
0523 }
0524
0525 void clear()
0526 {
0527 m_metaContainer.clear(mutableIterable());
0528 }
0529
0530 Container metaContainer() const
0531 {
0532 return m_metaContainer;
0533 }
0534 };
0535
0536 QT_END_NAMESPACE
0537
0538 #endif