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