diff options
Diffstat (limited to 'src/corelib/kernel/qiterable.h')
-rw-r--r-- | src/corelib/kernel/qiterable.h | 486 |
1 files changed, 412 insertions, 74 deletions
diff --git a/src/corelib/kernel/qiterable.h b/src/corelib/kernel/qiterable.h index ad13d971ec..8a230d5f0e 100644 --- a/src/corelib/kernel/qiterable.h +++ b/src/corelib/kernel/qiterable.h @@ -43,7 +43,6 @@ #include <QtCore/qglobal.h> #include <QtCore/qtypeinfo.h> #include <QtCore/qmetacontainer.h> -#include <QtCore/qmetatype.h> #include <QtCore/qtaggedpointer.h> QT_BEGIN_NAMESPACE @@ -100,114 +99,453 @@ namespace QtPrivate { }; } -class Q_CORE_EXPORT QSequentialIterable +template<class Iterator, typename IteratorCategory> +class QTaggedIterator : public Iterator { - uint m_revision = 0; - QtPrivate::QConstPreservingPointer<void, quint16> m_iterable; - QMetaSequence m_metaSequence; +public: + using iterator_category = IteratorCategory; + QTaggedIterator(Iterator &&it) : Iterator(std::move(it)) + { + const QMetaContainer metaContainer = this->metaContainer(); + if (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory> + && !metaContainer.hasRandomAccessIterator()) { + qFatal("You cannot use this iterator as a random access iterator"); + this->clearIterator(); + } + + if (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory> + && !metaContainer.hasBidirectionalIterator()) { + qFatal("You cannot use this iterator as a bidirectional iterator"); + this->clearIterator(); + } + + if (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory> + && !metaContainer.hasForwardIterator()) { + qFatal("You cannot use this iterator as a forward iterator"); + this->clearIterator(); + } + + if (std::is_base_of_v<std::input_iterator_tag, IteratorCategory> + && !metaContainer.hasInputIterator()) { + qFatal("You cannot use this iterator as an input iterator"); + this->clearIterator(); + } + } + + bool operator==(const QTaggedIterator &o) const { return Iterator::operator==(o); } + bool operator!=(const QTaggedIterator &o) const { return Iterator::operator!=(o); } + QTaggedIterator &operator++() { Iterator::operator++(); return *this; } + QTaggedIterator operator++(int x) { return QTaggedIterator(Iterator::operator++(x)); }; + QTaggedIterator &operator--() { Iterator::operator--(); return *this; } + QTaggedIterator operator--(int x) { return QTaggedIterator(Iterator::operator--(x)); }; + QTaggedIterator &operator+=(qsizetype j) { Iterator::operator+=(j); return *this; } + QTaggedIterator &operator-=(qsizetype j) { Iterator::operator-=(j); return *this; } + QTaggedIterator operator+(qsizetype j) const { return QTaggedIterator(Iterator::operator+(j)); } + QTaggedIterator operator-(qsizetype j) const { return QTaggedIterator(Iterator::operator-(j)); } + qsizetype operator-(const QTaggedIterator &j) const { return Iterator::operator-(j); } + + bool operator<(const QTaggedIterator &j) { return operator-(j) < 0; } + bool operator>=(const QTaggedIterator &j) { return !operator<(j); } + bool operator>(const QTaggedIterator &j) { return operator-(j) > 0; } + bool operator<=(const QTaggedIterator &j) { return !operator>(j); } + + friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; } +}; + +template<class Container> +class QIterable; + +template<class Container> +class QBaseIterator +{ +private: + QtPrivate::QConstPreservingPointer<QIterable<Container>> m_iterable; + void *m_iterator = nullptr; + +protected: + QBaseIterator() = default; + QBaseIterator(const QIterable<Container> *iterable, void *iterator) + : m_iterable(iterable), m_iterator(iterator) + {} + + QBaseIterator(QIterable<Container> *iterable, void *iterator) + : m_iterable(iterable), m_iterator(iterator) + {} + + QBaseIterator(QBaseIterator &&other) + : m_iterable(std::move(other.m_iterable)), m_iterator(std::move(other.m_iterator)) + { + other.m_iterator = nullptr; + } + + QBaseIterator(const QBaseIterator &other) + : m_iterable(other.m_iterable) + { + initIterator(other.m_iterator); + } + + ~QBaseIterator() { clearIterator(); } + + QBaseIterator &operator=(QBaseIterator &&other) + { + if (this != &other) { + clearIterator(); + m_iterable = std::move(other.m_iterable); + m_iterator = std::move(other.m_iterator); + other.m_iterator = nullptr; + } + return *this; + } + + QBaseIterator &operator=(const QBaseIterator &other) + { + if (this != &other) { + clearIterator(); + m_iterable = other.m_iterable; + initIterator(other.m_iterator); + } + return *this; + } + + QIterable<Container> *mutableIterable() const + { + return m_iterable.mutablePointer(); + } + + const QIterable<Container> *constIterable() const + { + return m_iterable.constPointer(); + } + + void initIterator(const void *copy) + { + if (!copy) + return; + if (auto *mutableIt = mutableIterable()) { + m_iterator = metaContainer().begin(mutableIt->mutableIterable()); + metaContainer().copyIterator(m_iterator, copy); + } else if (auto *constIt = constIterable()) { + m_iterator = metaContainer().constBegin(constIt->constIterable()); + metaContainer().copyConstIterator(m_iterator, copy); + } + } + + void clearIterator() + { + if (!m_iterator) + return; + if (mutableIterable()) + metaContainer().destroyIterator(m_iterator); + else + metaContainer().destroyConstIterator(m_iterator); + } + +public: + void *mutableIterator() { return m_iterator; } + const void *constIterator() const { return m_iterator; } + Container metaContainer() const { return constIterable()->m_metaContainer; } +}; +template<class Container> +struct QIterator : public QBaseIterator<Container> +{ public: - struct Q_CORE_EXPORT const_iterator + using difference_type = qsizetype; + + explicit QIterator(QIterable<Container> *iterable, void *iterator) + : QBaseIterator<Container>(iterable, iterator) { - private: - const QSequentialIterable *m_iterable = nullptr; - void *m_iterator = nullptr; - QAtomicInt *m_ref = nullptr; + Q_ASSERT(iterable != nullptr); + } - friend class QSequentialIterable; - explicit const_iterator(const QSequentialIterable *iterable, void *iterator); + bool operator==(const QIterator &o) const + { + return this->metaContainer().compareIterator(this->constIterator(), o.constIterator()); + } - public: - ~const_iterator(); - - const_iterator(const const_iterator &other); - - const_iterator& operator=(const const_iterator &other); - - const QVariant operator*() const; - bool operator==(const const_iterator &o) const; - bool operator!=(const const_iterator &o) const; - const_iterator &operator++(); - const_iterator operator++(int); - const_iterator &operator--(); - const_iterator operator--(int); - const_iterator &operator+=(int j); - const_iterator &operator-=(int j); - const_iterator operator+(int j) const; - const_iterator operator-(int j) const; - friend inline const_iterator operator+(int j, const const_iterator &k) { return k + j; } - }; + bool operator!=(const QIterator &o) const + { + return !this->metaContainer().compareIterator(this->constIterator(), o.constIterator()); + } + + QIterator &operator++() + { + this->metaContainer().advanceIterator(this->mutableIterator(), 1); + return *this; + } + + QIterator operator++(int) + { + QIterable<Container> *iterable = this->mutableIterable(); + const Container metaContainer = this->metaContainer(); + QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); + metaContainer.copyIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceIterator(this->mutableIterator(), 1); + return result; + } + + QIterator &operator--() + { + this->metaContainer().advanceIterator(this->mutableIterator(), -1); + return *this; + } + + QIterator operator--(int) + { + QIterable<Container> *iterable = this->mutableIterable(); + const Container metaContainer = this->metaContainer(); + QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); + metaContainer.copyIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceIterator(this->mutableIterator(), -1); + return result; + } + + QIterator &operator+=(qsizetype j) + { + this->metaContainer().advanceIterator(this->mutableIterator(), j); + return *this; + } + + QIterator &operator-=(qsizetype j) + { + this->metaContainer().advanceIterator(this->mutableIterator(), -j); + return *this; + } + + QIterator operator+(qsizetype j) const + { + QIterable<Container> *iterable = this->mutableIterable(); + const Container metaContainer = this->metaContainer(); + QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); + metaContainer.copyIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceIterator(result.mutableIterator(), j); + return result; + } + + QIterator operator-(qsizetype j) const + { + QIterable<Container> *iterable = this->mutableIterable(); + const Container metaContainer = this->metaContainer(); + QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); + metaContainer.copyIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceIterator(result.mutableIterator(), -j); + return result; + } + + qsizetype operator-(const QIterator &j) const + { + return this->metaContainer().diffIterator(this->constIterator(), j.constIterator()); + } + + friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; } +}; + +template<class Container> +struct QConstIterator : public QBaseIterator<Container> +{ +public: + using difference_type = qsizetype; + + explicit QConstIterator(const QIterable<Container> *iterable, void *iterator) + : QBaseIterator<Container>(iterable, iterator) + { + } + + bool operator==(const QConstIterator &o) const + { + return this->metaContainer().compareConstIterator( + this->constIterator(), o.constIterator()); + } + + bool operator!=(const QConstIterator &o) const + { + return !this->metaContainer().compareConstIterator( + this->constIterator(), o.constIterator()); + } + + QConstIterator &operator++() + { + this->metaContainer().advanceConstIterator(this->mutableIterator(), 1); + return *this; + } + + QConstIterator operator++(int) + { + const Container metaContainer = this->metaContainer(); + QConstIterator result(this->constIterable(), metaContainer.constBegin( + this->constIterable()->constIterable())); + metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceConstIterator(this->mutableIterator(), 1); + return result; + } + + QConstIterator &operator--() + { + this->metaContainer().advanceConstIterator(this->mutableIterator(), -1); + return *this; + } + + QConstIterator operator--(int) + { + const Container metaContainer = this->metaContainer(); + QConstIterator result(this->constIterable(), metaContainer.constBegin( + this->constIterable()->constIterable())); + metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceConstIterator(this->mutableIterator(), -1); + return result; + } + + QConstIterator &operator+=(qsizetype j) + { + this->metaContainer().advanceConstIterator(this->mutableIterator(), j); + return *this; + } + + QConstIterator &operator-=(qsizetype j) + { + this->metaContainer().advanceConstIterator(this->mutableIterator(), -j); + return *this; + } + + QConstIterator operator+(qsizetype j) const + { + const Container metaContainer = this->metaContainer(); + QConstIterator result( + this->constIterable(), + metaContainer.constBegin(this->constIterable()->constIterable())); + metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceConstIterator(result.mutableIterator(), j); + return result; + } + + QConstIterator operator-(qsizetype j) const + { + const Container metaContainer = this->metaContainer(); + QConstIterator result(this->constIterable(), metaContainer.constBegin( + this->constIterable()->constIterable())); + metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator()); + metaContainer.advanceConstIterator(result.mutableIterator(), -j); + return result; + } + + qsizetype operator-(const QConstIterator &j) const + { + return this->metaContainer().diffIterator(this->constIterator(), j.constIterator()); + } + + friend inline QConstIterator operator+(qsizetype j, const QConstIterator &k) + { + return k + j; + } +}; + +template<class Container> +class QIterable +{ + friend class QBaseIterator<Container>; - friend struct const_iterator; +protected: + uint m_revision = 0; + QtPrivate::QConstPreservingPointer<void, quint16> m_iterable; + Container m_metaContainer; + +public: + QIterable() = default; template<class T> - QSequentialIterable(const T *p) - : m_iterable(p) - , m_metaSequence(QMetaSequence::fromContainer<T>()) + QIterable(const Container &metaContainer, const T *p) + : m_iterable(p), m_metaContainer(metaContainer) { - Q_UNUSED(m_revision); } - QSequentialIterable() = default; + template<class T> + QIterable(const Container &metaContainer, T *p) + : m_iterable(p), m_metaContainer(metaContainer) + { + } template<typename Pointer> - QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable) - : m_iterable(iterable) - , m_metaSequence(metaSequence) + QIterable(const Container &metaContainer, Pointer iterable) + : m_iterable(iterable), m_metaContainer(metaContainer) { } - const_iterator begin() const; - const_iterator end() const; + QIterable(const Container &metaContainer, qsizetype alignment, const void *p) + : m_iterable(p, alignment), m_metaContainer(metaContainer) + { + } + + QIterable(const Container &metaContainer, qsizetype alignment, void *p) + : m_iterable(p, alignment), m_metaContainer(metaContainer) + { + } - QVariant at(qsizetype idx) const; - qsizetype size() const; + bool canInputIterate() const + { + return m_metaContainer.hasInputIterator(); + } + + bool canForwardIterate() const + { + return m_metaContainer.hasForwardIterator(); + } - enum Position { Unspecified, AtBegin, AtEnd }; - void addValue(const QVariant &value, Position position = Unspecified); - void removeValue(Position position = Unspecified); + bool canReverseIterate() const + { + return m_metaContainer.hasBidirectionalIterator(); + } - bool canForwardIterate() const; - bool canReverseIterate() const; + bool canRandomAccessIterate() const + { + return m_metaContainer.hasRandomAccessIterator(); + } const void *constIterable() const { return m_iterable.constPointer(); } // TODO: fix this when introducing mutable iterables void *mutableIterable() { return const_cast<void *>(m_iterable.constPointer()); } - QMetaSequence metaSequence() const { return m_metaSequence; } - QMetaType valueMetaType() const { return m_metaSequence.valueMetaType(); } -}; + QConstIterator<Container> constBegin() const + { + return QConstIterator(this, m_metaContainer.constBegin(constIterable())); + } -namespace QtPrivate { + QConstIterator<Container> constEnd() const + { + return QConstIterator(this, m_metaContainer.constEnd(constIterable())); + } -template<typename From> -struct QSequentialIterableConvertFunctor -{ - QSequentialIterable operator()(const From &f) const + QIterator<Container> mutableBegin() { - return QSequentialIterable(&f); + return QIterator(this, m_metaContainer.begin(mutableIterable())); } -}; -template<typename T> -struct SequentialValueTypeIsMetaType<T, true> -{ - static bool registerConverter(int id) + QIterator<Container> mutableEnd() { - const int toId = qMetaTypeId<QSequentialIterable>(); - if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { - QSequentialIterableConvertFunctor<T> o; - return QMetaType::registerConverter<T, QSequentialIterable>(o); - } - return true; + return QIterator(this, m_metaContainer.end(mutableIterable())); } -}; -} + qsizetype size() const + { + const void *container = constIterable(); + if (m_metaContainer.hasSize()) + return m_metaContainer.size(container); + if (!m_metaContainer.hasConstIterator()) + return -1; + + const void *begin = m_metaContainer.constBegin(container); + const void *end = m_metaContainer.constEnd(container); + const qsizetype size = m_metaContainer.diffConstIterator(end, begin); + m_metaContainer.destroyConstIterator(begin); + m_metaContainer.destroyConstIterator(end); + return size; + } -Q_DECLARE_TYPEINFO(QSequentialIterable, Q_MOVABLE_TYPE); -Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_MOVABLE_TYPE); + Container metaContainer() const + { + return m_metaContainer; + }; +}; QT_END_NAMESPACE |