Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:26

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 
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 // QITERABLE_H