Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-22 09:02:12

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 // Qt-Security score:significant reason:default
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         // We shouldn't second-guess the underlying container, so we're not synthesizing a size.
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 // QITERABLE_H