summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qiterable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qiterable.h')
-rw-r--r--src/corelib/kernel/qiterable.h486
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