summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-09-10 18:25:02 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-19 11:14:30 +0200
commit5c808073af5b8f1290602fcccf60666c9a3682f8 (patch)
tree97545220e79498a2dc2bb95f41da14ecce75cbd0 /src/corelib/kernel
parentb30801f64db5211bfb4392f13a6ff06d30288cb5 (diff)
Extend QSequentialIterable and add QAssociativeIterable
And add mutable iterators. This requires some refactoring of the existing iterators. Task-number: QTBUG-81716 Change-Id: I61b3a3e8c0df5fd449679257a29d9f0c3d19c4f0 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri6
-rw-r--r--src/corelib/kernel/qassociativeiterable.cpp253
-rw-r--r--src/corelib/kernel/qassociativeiterable.h194
-rw-r--r--src/corelib/kernel/qiterable.cpp680
-rw-r--r--src/corelib/kernel/qiterable.h486
-rw-r--r--src/corelib/kernel/qiterable_p.cpp63
-rw-r--r--src/corelib/kernel/qiterable_p.h80
-rw-r--r--src/corelib/kernel/qmetatype.cpp65
-rw-r--r--src/corelib/kernel/qmetatype.h318
-rw-r--r--src/corelib/kernel/qsequentialiterable.cpp258
-rw-r--r--src/corelib/kernel/qsequentialiterable.h186
-rw-r--r--src/corelib/kernel/qvariant.cpp355
-rw-r--r--src/corelib/kernel/qvariant.h55
13 files changed, 1985 insertions, 1014 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 07ca3c12ae..098a15f012 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -36,6 +36,9 @@ HEADERS += \
kernel/qobject_p.h \
kernel/qcoreglobaldata_p.h \
kernel/qiterable.h \
+ kernel/qiterable_p.h \
+ kernel/qsequentialiterable.h \
+ kernel/qassociativeiterable.h \
kernel/qsharedmemory.h \
kernel/qsharedmemory_p.h \
kernel/qsystemsemaphore.h \
@@ -72,6 +75,9 @@ SOURCES += \
kernel/qvariant.cpp \
kernel/qcoreglobaldata.cpp \
kernel/qiterable.cpp \
+ kernel/qiterable_p.cpp \
+ kernel/qsequentialiterable.cpp \
+ kernel/qassociativeiterable.cpp \
kernel/qsharedmemory.cpp \
kernel/qsystemsemaphore.cpp \
kernel/qpointer.cpp \
diff --git a/src/corelib/kernel/qassociativeiterable.cpp b/src/corelib/kernel/qassociativeiterable.cpp
new file mode 100644
index 0000000000..780ae35a42
--- /dev/null
+++ b/src/corelib/kernel/qassociativeiterable.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qassociativeiterable.h>
+#include <QtCore/qvariant.h>
+
+#include <QtCore/private/qiterable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Returns the key this iterator points to.
+*/
+QVariant QAssociativeIterator::key() const
+{
+ return QIterablePrivate::retrieveElement(
+ metaContainer().keyMetaType(), [this](void *dataPtr) {
+ metaContainer().keyAtIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the mapped value this iterator points to. If the container does not
+ provide a mapped value (for example a set), returns an invalid QVariantRef.
+*/
+QVariantRef<QAssociativeIterator> QAssociativeIterator::value() const
+{
+ const QMetaType mappedMetaType(metaContainer().mappedMetaType());
+ return QVariantRef<QAssociativeIterator>(mappedMetaType.isValid() ? this : nullptr);
+}
+
+/*!
+ Returns the current item, converted to a QVariantRef. The resulting
+ QVariantRef resolves to the mapped value if there is one, or to the key
+ value if not.
+*/
+QVariantRef<QAssociativeIterator> QAssociativeIterator::operator*() const
+{
+ return QVariantRef<QAssociativeIterator>(this);
+}
+
+/*!
+ Returns the current item, converted to a QVariantPointer. The resulting
+ QVariantPointer resolves to the mapped value if there is one, or to the key
+ value if not.
+*/
+QVariantPointer<QAssociativeIterator> QAssociativeIterator::operator->() const
+{
+ return QVariantPointer<QAssociativeIterator>(this);
+}
+
+/*!
+ Returns the key this iterator points to.
+*/
+QVariant QAssociativeConstIterator::key() const
+{
+ return QIterablePrivate::retrieveElement(
+ metaContainer().keyMetaType(), [this](void *dataPtr) {
+ metaContainer().keyAtConstIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the mapped value this iterator points to, or an invalid QVariant if
+ there is no mapped value.
+*/
+QVariant QAssociativeConstIterator::value() const
+{
+ return QIterablePrivate::retrieveElement(
+ metaContainer().mappedMetaType(), [this](void *dataPtr) {
+ metaContainer().mappedAtConstIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the current item, converted to a QVariant. The returned value is the
+ mapped value at the current iterator if there is one, or otherwise the key.
+*/
+QVariant QAssociativeConstIterator::operator*() const
+{
+ const QMetaType mappedMetaType(metaContainer().mappedMetaType());
+ return mappedMetaType.isValid() ? value() : key();
+}
+
+/*!
+ Returns the current item, converted to a QVariantConstPointer. The
+ QVariantConstPointer will resolve to the mapped value at the current
+ iterator if there is one, or otherwise the key.
+*/
+QVariantConstPointer QAssociativeConstIterator::operator->() const
+{
+ return QVariantConstPointer(operator*());
+}
+
+/*!
+ \class QAssociativeIterable
+ \since 5.2
+ \inmodule QtCore
+ \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
+
+ This class allows several methods of accessing the elements of an associative container held within
+ a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
+ be converted to a QVariantHash or QVariantMap or if a custom mutable view has been registered.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ The container itself is not copied before iterating over it.
+
+ \sa QVariant
+*/
+
+/*!
+ \typedef QAssociativeIterable::RandomAccessIterator
+ Exposes an iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::BidirectionalIterator
+ Exposes an iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::ForwardIterator
+ Exposes an iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::InputIterator
+ Exposes an iterator using std::input_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::RandomAccessConstIterator
+ Exposes a const_iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::BidirectionalConstIterator
+ Exposes a const_iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::ForwardConstIterator
+ Exposes a const_iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::InputConstIterator
+ Exposes a const_iterator using std::input_iterator_tag.
+*/
+
+/*!
+ Retrieves a const_iterator pointing to the element at the given \a key, or
+ the end of the container if that key does not exist.
+ */
+QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
+{
+ const QMetaAssociation meta = metaContainer();
+ QVariant converted = key;
+ const void *keyData = QIterablePrivate::coerceType(converted, meta.keyMetaType());
+ return const_iterator(QConstIterator(
+ this, meta.createConstIteratorAtKey(constIterable(), keyData)));
+}
+
+/*!
+ Retrieves an iterator pointing to the element at the given \a key, or
+ the end of the container if that key does not exist.
+ */
+QAssociativeIterable::iterator QAssociativeIterable::mutableFind(const QVariant &key)
+{
+ const QMetaAssociation meta = metaContainer();
+ QVariant converted = key;
+ const void *keyData = QIterablePrivate::coerceType(converted, meta.keyMetaType());
+ return iterator(QIterator(this, meta.createIteratorAtKey(mutableIterable(), keyData)));
+}
+
+/*!
+ Retrieves the mapped value at the given \a key, or an invalid QVariant
+ if the key does not exist.
+ */
+QVariant QAssociativeIterable::value(const QVariant &key) const
+{
+ const QMetaAssociation meta = metaContainer();
+ QVariant converted = key;
+ const void *keyData = QIterablePrivate::coerceType(converted, meta.keyMetaType());
+ QVariant result(QMetaType(meta.mappedMetaType()));
+ meta.mappedAtKey(constIterable(), keyData, result.data());
+ return result;
+}
+
+/*!
+ \class QAssociativeIterable::const_iterator
+ \since 5.2
+ \inmodule QtCore
+ \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
+
+ A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ \sa QAssociativeIterable
+*/
+
+/*!
+ \class QAssociativeIterable::iterator
+ \since 6.0
+ \inmodule QtCore
+ \brief The QAssociativeIterable::iterator allows iteration over a container in a QVariant.
+
+ A QAssociativeIterable::iterator can only be created by a QAssociativeIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \sa QAssociativeIterable
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qassociativeiterable.h b/src/corelib/kernel/qassociativeiterable.h
new file mode 100644
index 0000000000..1122fd118d
--- /dev/null
+++ b/src/corelib/kernel/qassociativeiterable.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QASSOCIATIVEITERABLE_H
+#define QASSOCIATIVEITERABLE_H
+
+#include <QtCore/qiterable.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QAssociativeIterator : public QIterator<QMetaAssociation>
+{
+public:
+ using key_type = QVariant;
+ using mapped_type = QVariant;
+ using reference = QVariantRef<QAssociativeIterator>;
+ using pointer = QVariantPointer<QAssociativeIterator>;
+
+ QAssociativeIterator(QIterator &&it)
+ : QIterator(std::move(it))
+ {}
+
+ QVariant key() const;
+ QVariantRef<QAssociativeIterator> value() const;
+
+ QVariantRef<QAssociativeIterator> operator*() const;
+ QVariantPointer<QAssociativeIterator> operator->() const;
+};
+
+class Q_CORE_EXPORT QAssociativeConstIterator : public QConstIterator<QMetaAssociation>
+{
+public:
+ using key_type = QVariant;
+ using mapped_type = QVariant;
+ using reference = const QVariant &;
+ using pointer = QVariantConstPointer;
+
+ QAssociativeConstIterator(QConstIterator &&it)
+ : QConstIterator(std::move(it))
+ {}
+
+ QVariant key() const;
+ QVariant value() const;
+
+ QVariant operator*() const;
+ QVariantConstPointer operator->() const;
+};
+
+class Q_CORE_EXPORT QAssociativeIterable : public QIterable<QMetaAssociation>
+{
+public:
+ using iterator = QTaggedIterator<QAssociativeIterator, void>;
+ using const_iterator = QTaggedIterator<QAssociativeConstIterator, void>;
+
+ using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
+ using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
+ using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
+ using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
+
+ using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
+ using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
+ using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
+ using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
+
+ template<class T>
+ QAssociativeIterable(const T *p)
+ : QIterable(QMetaAssociation::fromContainer<T>(), p)
+ {
+ }
+
+ template<class T>
+ QAssociativeIterable(T *p)
+ : QIterable(QMetaAssociation::fromContainer<T>(), p)
+ {
+ }
+
+ QAssociativeIterable() = default;
+
+ template<typename Pointer>
+ QAssociativeIterable(const QMetaAssociation &metaAssociation, Pointer iterable)
+ : QIterable(metaAssociation, iterable)
+ {
+ }
+
+ QAssociativeIterable(const QMetaAssociation &metaSequence, const QMetaType &metaType,
+ void *iterable)
+ : QIterable(metaSequence, metaType.alignOf(), iterable)
+ {
+ }
+
+ QAssociativeIterable(const QMetaAssociation &metaSequence, const QMetaType &metaType,
+ const void *iterable)
+ : QIterable(metaSequence, metaType.alignOf(), iterable)
+ {
+ }
+
+ QAssociativeIterable(QIterable<QMetaAssociation> &&other) : QIterable(std::move(other)) {}
+
+ QAssociativeIterable &operator=(QIterable<QMetaAssociation> &&other)
+ {
+ QIterable::operator=(std::move(other));
+ return *this;
+ }
+
+ const_iterator begin() const { return constBegin(); }
+ const_iterator end() const { return constEnd(); }
+
+ const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
+ const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
+
+ iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
+ iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
+
+ const_iterator find(const QVariant &key) const;
+ const_iterator constFind(const QVariant &key) const { return find(key); }
+ iterator mutableFind(const QVariant &key);
+
+ QVariant value(const QVariant &key) const;
+};
+
+template<>
+inline QVariantRef<QAssociativeIterator>::operator QVariant() const
+{
+ if (m_pointer == nullptr)
+ return QVariant();
+ const auto metaAssociation = m_pointer->metaContainer();
+ QMetaType metaType(metaAssociation.mappedMetaType());
+ if (!metaType.isValid())
+ return m_pointer->key();
+
+ QVariant v(metaType);
+ void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
+ metaAssociation.mappedAtIterator(m_pointer->constIterator(), dataPtr);
+ return v;
+}
+
+template<>
+inline QVariantRef<QAssociativeIterator> &QVariantRef<QAssociativeIterator>::operator=(
+ const QVariant &value)
+{
+ if (m_pointer == nullptr)
+ return *this;
+ const QMetaType metaType(m_pointer->metaContainer().mappedMetaType());
+ const void *dataPtr = metaType == QMetaType::fromType<QVariant>()
+ ? &value
+ : value.constData();
+ m_pointer->metaContainer().setMappedAtIterator(m_pointer->constIterator(), dataPtr);
+ return *this;
+}
+
+Q_DECLARE_TYPEINFO(QAssociativeIterable, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QAssociativeIterable::iterator, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QAssociativeIterable::const_iterator, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QASSOCIATIVEITERABLE_H
diff --git a/src/corelib/kernel/qiterable.cpp b/src/corelib/kernel/qiterable.cpp
index 5aed1832af..f397749e51 100644
--- a/src/corelib/kernel/qiterable.cpp
+++ b/src/corelib/kernel/qiterable.cpp
@@ -38,271 +38,495 @@
****************************************************************************/
#include <QtCore/qiterable.h>
-#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
/*!
- \class QSequentialIterable
- \since 5.2
+ \class QBaseIterator
+
+ QBaseIterator forms the common base class for all iterators operating on
+ subclasses of QIterable.
+*/
+
+/*!
+ \fn QBaseIterator::QBaseIterator(const QIterable *iterable, void *iterator)
+
+ \internal
+ Creates a const QBaseIterator from an \a iterable and an \a iterator.
+ */
+
+/*!
+ \fn QBaseIterator::QBaseIterator(QIterable *iterable, void *iterator)
+
+ \internal
+ Creates a non-const QBaseIterator from an \a iterable and an \a iterator.
+ */
+
+/*!
+ \fn QBaseIterator::QBaseIterator(QBaseIterator &&other)
+
+ \internal
+ Move-constructs a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \fn QBaseIterator::QBaseIterator(const QBaseIterator &other)
+
+ \internal
+ Copy-constructs a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \fn QBaseIterator::~QBaseIterator()
+
+ \internal
+ Destroys a QBaseIterator.
+ */
+
+/*!
+ \fn QBaseIterator &QBaseIterator::operator=(const QBaseIterator &other)
+
+ \internal
+ Copy-assigns a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \fn void QBaseIterator::initIterator(const void *copy)
+
+ \internal
+ Initializes the internal native iterator by duplicating \a copy, if given.
+ */
+
+/*!
+ \fn void QBaseIterator::clearIterator()
+
+ \internal
+ Destroys the internal native iterator.
+ */
+
+
+/*!
+ \fn QMetaContainer QBaseIterator::metaContainer() const
+
+ \internal
+ Returns the meta sequence.
+ */
+
+/*!
+ \fn QIterable *QBaseIterator::mutableIterable() const
+
+ \internal
+ Returns a non-const pointer to the iterable, if the original iterable was
+ non-const. Otherwise returns nullptr.
+ */
+
+/*!
+ \fn const QIterable *QBaseIterator::constIterable() const
+
+ \internal
+ Returns a const pointer to the iterable.
+ */
+
+/*!
+ \fn void *QBaseIterator::mutableIterator()
+
+ Returns a non-const pointer to the internal native iterator.
+ */
+
+/*!
+ \fn const void *QBaseIterator::constIterator() const
+
+ Returns a const pointer to the internal native iterator.
+ */
+
+/*!
+ \fn QBaseIterator &QBaseIterator::operator=(QBaseIterator &&other)
+
+ \internal
+ Move-assigns a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \class Qiterator
+ \since 6.0
\inmodule QtCore
- \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
+ \brief The QIterator allows iteration over a container in a QVariant.
+
+ A QIterator can only be created by a QIterable instance, and can be used
+ in a way similar to other stl-style iterators. Generally, QIterator should
+ not be used directly, but through its derived classes provided by
+ QSequentialIterable and QAssociativeIterable.
+
+ \sa QIterable
+*/
- This class allows several methods of accessing the values of a container held within
- a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
- be converted to a QVariantList.
+/*!
+ \fn QIterator::QIterator(QIterable *iterable, void *iterator)
- \snippet code/src_corelib_kernel_qvariant.cpp 9
+ Creates an iterator from an \a iterable and a pointer to a native \a iterator.
+ */
- The container itself is not copied before iterating over it.
+/*!
+ \fn bool QIterator::operator==(const QIterator &other) const
- \sa QVariant
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
*/
-QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable *iterable, void *iterator)
- : m_iterable(iterable), m_iterator(iterator), m_ref(new QAtomicInt(0))
-{
- m_ref->ref();
-}
+/*!
+ \fn bool QIterator::operator!=(const QIterator &other) const
-/*! \fn QSequentialIterable::const_iterator QSequentialIterable::begin() const
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
- Returns a QSequentialIterable::const_iterator for the beginning of the container. This
- can be used in stl-style iteration.
+ \sa operator==()
+*/
- \sa end()
+/*!
+ \fn QIterator &QIterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QSequentialIterable::end() leads to undefined results.
+
+ \sa operator--()
*/
-QSequentialIterable::const_iterator QSequentialIterable::begin() const
-{
- return const_iterator(this, m_metaSequence.constBegin(m_iterable.constPointer()));
-}
/*!
- Returns a QSequentialIterable::const_iterator for the end of the container. This
- can be used in stl-style iteration.
+ \fn QIterator QIterator::operator++(int)
+ \overload
- \sa begin()
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
*/
-QSequentialIterable::const_iterator QSequentialIterable::end() const
-{
- return const_iterator(this, m_metaSequence.constEnd(m_iterable.constPointer()));
-}
+
/*!
- Returns the value at position \a idx in the container.
+ \fn QIterator &QIterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QSequentialIterable::begin() leads to undefined results.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator++(), canReverseIterate()
*/
-QVariant QSequentialIterable::at(qsizetype idx) const
-{
- QVariant v(m_metaSequence.valueMetaType());
- void *dataPtr;
- if (m_metaSequence.valueMetaType() == QMetaType::fromType<QVariant>())
- dataPtr = &v;
- else
- dataPtr = v.data();
- const QMetaSequence metaSequence = m_metaSequence;
- if (metaSequence.canGetValueAtIndex()) {
- metaSequence.valueAtIndex(m_iterable.constPointer(), idx, dataPtr);
- } else if (metaSequence.canGetValueAtConstIterator()) {
- void *iterator = metaSequence.constBegin(m_iterable.constPointer());
- metaSequence.advanceConstIterator(iterator, idx);
- metaSequence.valueAtConstIterator(iterator, dataPtr);
- metaSequence.destroyConstIterator(iterator);
- }
+/*!
+ \fn QIterator QIterator::operator--(int)
- return v;
-}
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa canReverseIterate()
+*/
/*!
- Returns the number of values in the container.
+ \fn QIterator &QIterator::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QIterator &QIterator::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+=(), operator-(), canReverseIterate()
*/
-qsizetype QSequentialIterable::size() const
-{
- const QMetaSequence metaSequence = m_metaSequence;
- const void *container = m_iterable.constPointer();
- if (metaSequence.hasSize())
- return metaSequence.size(container);
- if (!metaSequence.hasConstIterator())
- return -1;
-
- const void *begin = metaSequence.constBegin(container);
- const void *end = metaSequence.constEnd(container);
- const qsizetype size = metaSequence.diffConstIterator(end, begin);
- metaSequence.destroyConstIterator(begin);
- metaSequence.destroyConstIterator(end);
- return size;
-}
-
-/*!
- * Adds \a value to the container, at \a position, if possible.
+
+/*!
+ \fn QIterator QIterator::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn QIterator QIterator::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+(), operator-=(), canReverseIterate()
+*/
+
+/*!
+ \fn qsizetype QIterator::operator-(const QIterator &j) const
+
+ Returns the distance between the two iterators.
+
+ \sa operator+(), operator-=(), canReverseIterator()
*/
-void QSequentialIterable::addValue(const QVariant &value, Position position)
-{
- QVariant converted;
- const void *valuePtr;
- if (valueMetaType() == QMetaType::fromType<QVariant>()) {
- valuePtr = &value;
- } else if (valueMetaType() == value.metaType()) {
- valuePtr = value.constData();
- } else if (value.canConvert(valueMetaType())) {
- converted = value;
- converted.convert(valueMetaType());
- valuePtr = converted.constData();
- } else {
- converted = QVariant(valueMetaType());
- valuePtr = converted.constData();
- }
-
- switch (position) {
- case AtBegin:
- if (metaSequence().canAddValueAtBegin())
- metaSequence().addValueAtBegin(mutableIterable(), valuePtr);
- break;
- case AtEnd:
- if (metaSequence().canAddValueAtEnd())
- metaSequence().addValueAtEnd(mutableIterable(), valuePtr);
- break;
- case Unspecified:
- if (metaSequence().canAddValue())
- metaSequence().addValue(mutableIterable(), valuePtr);
- break;
- }
-}
-
-/*!
- * Removes a value from the container, at \a position, if possible.
+
+/*!
+ QConstIterator::QConstIterator(const QIterable *iterable, void *iterator)
+
+ Creates a QConstIterator to wrap \a iterator, operating on \a iterable.
*/
-void QSequentialIterable::removeValue(Position position)
-{
- switch (position) {
- case AtBegin:
- if (metaSequence().canRemoveValueAtBegin())
- metaSequence().removeValueAtBegin(mutableIterable());
- break;
- case AtEnd:
- if (metaSequence().canRemoveValueAtEnd())
- metaSequence().removeValueAtEnd(mutableIterable());
- break;
- case Unspecified:
- if (metaSequence().canRemoveValue())
- metaSequence().removeValue(mutableIterable());
- break;
- }
-}
/*!
+ bool QConstIterator::operator==(const QConstIterator &other) const
+
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ bool QConstIterator::operator!=(const QConstIterator &other) const
+
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QConstIterator &QConstIterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QIterable::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QConstIterator QConstIterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
+*/
+
+/*!
+ \fn QConstIterator &QConstIterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QIterable::begin() leads to undefined results.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator++(), canReverseIterate()
+*/
+
+/*!
+ \fn QConstIterator QConstIterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa canReverseIterate()
+*/
+
+/*!
+ \fn QConstIterator &QConstIterator::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QConstIterator &QConstIterator::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+=(), operator-(), canReverseIterate()
+*/
+
+/*!
+ \fn QConstIterator QConstIterator::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn QConstIterator QConstIterator::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+(), operator-=(), canReverseIterate()
+*/
+
+/*!
+ \fn qsizetype QConstIterator::operator-(const QConstIterator &j) const
+
+ Returns the distance between the two iterators.
+
+ \sa operator+(), operator-=(), canReverseIterator()
+ */
+
+/*!
+ \class QIterable
+ \since 6.0
+
+ QIterable is the base class for QSequentialIterable and QAssociativeIterable.
+*/
+
+/*!
+ \fn bool QIterable::canInputIterate() const
+
+ Returns whether the container has an input iterator. This corresponds to
+ the std::input_iterator_tag iterator trait of the iterator and
+ const_iterator of the container.
+*/
+
+/*!
+ \fn bool QIterable::canForwardIterate() const
+
Returns whether it is possible to iterate over the container in forward
direction. This corresponds to the std::forward_iterator_tag iterator trait
of the iterator and const_iterator of the container.
*/
-bool QSequentialIterable::canForwardIterate() const
-{
- return m_metaSequence.hasForwardIterator();
-}
/*!
+ \fn bool QIterable::canReverseIterate() const
+
Returns whether it is possible to iterate over the container in reverse. This
corresponds to the std::bidirectional_iterator_tag iterator trait of the
const_iterator of the container.
*/
-bool QSequentialIterable::canReverseIterate() const
-{
- return m_metaSequence.hasBidirectionalIterator();
-}
/*!
- \class QSequentialIterable::const_iterator
- \since 5.2
- \inmodule QtCore
- \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
+ \fn bool QIterable::canRandomAccessIterate() const
- A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
- and can be used in a way similar to other stl-style iterators.
+ Returns whether it is possible to efficiently skip over multiple values
+ using and iterator. This corresponds to the std::random_access_iterator_tag
+ iterator trait of the iterator and const_iterator of the container.
+*/
+
+/*!
+ \fn QConstIterator QIterable::constBegin() const
- \snippet code/src_corelib_kernel_qvariant.cpp 9
+ Returns a QConstIterator for the beginning of the container. This
+ can be used in stl-style iteration.
- \sa QSequentialIterable
+ \sa end()
*/
+/*!
+ \fn QConstIterator QIterable::constEnd() const
+
+ Returns a Qterable::QConstIterator for the end of the container. This
+ can be used in stl-style iteration.
+
+ \sa begin()
+*/
/*!
- Destroys the QSequentialIterable::const_iterator.
+ \fn QIterator QIterable::mutableBegin()
+
+ Returns a QIterator for the beginning of the container. This
+ can be used in stl-style iteration.
+
+ \sa end()
*/
-QSequentialIterable::const_iterator::~const_iterator() {
- if (!m_ref->deref()) {
- m_iterable->m_metaSequence.destroyConstIterator(m_iterator);
- delete m_ref;
- }
-}
/*!
- Creates a copy of \a other.
+ \fn QIterator QIterable::mutableEnd()
+
+ Returns a QSequentialIterable::iterator for the end of the container. This
+ can be used in stl-style iteration.
+
+ \sa begin()
+*/
+
+/*!
+ \fn qsizetype QIterable::size() const
+
+ Returns the number of values in the container.
*/
-QSequentialIterable::const_iterator::const_iterator(const const_iterator &other)
- : m_iterable(other.m_iterable), m_iterator(other.m_iterator), m_ref(other.m_ref)
-{
- m_ref->ref();
-}
/*!
- Assigns \a other to this.
+ \class QTaggedIterator
+ \since 6.0
+ \inmodule QtCore
+ \brief Wraps an iterator and exposes standard iterator traits.
+
+ In order to use an iterator any of the standard algorithms, it iterator
+ traits need to be known. As QSequentialIterable can work with many different
+ kinds of containers, we cannot declare the traits in the iterator classes
+ themselves. StdIterator gives you a way to explicitly declare a trait for
+ a concrete instance of an iterator or QConstIterator.
*/
-QSequentialIterable::const_iterator&
-QSequentialIterable::const_iterator::operator=(const const_iterator &other)
-{
- if (this == &other)
- return *this;
- other.m_ref->ref();
- if (!m_ref->deref()) {
- m_iterable->m_metaSequence.destroyConstIterator(m_iterator);
- delete m_ref;
- }
- m_iterable = other.m_iterable;
- m_iterator = other.m_iterator;
- m_ref = other.m_ref;
- return *this;
-}
/*!
- Returns the current item, converted to a QVariant.
+ \fn QTaggedIterator::StdIterator(Iterator &&it)
+
+ Constructs a StdIterator from an iterator or QConstIterator \a it. Checks
+ whether the IteratorCategory passed as template argument matches the run
+ time capabilities of \a it and refuses \a it if not.
*/
-const QVariant QSequentialIterable::const_iterator::operator*() const
-{
- QVariant v(m_iterable->m_metaSequence.valueMetaType());
- void *dataPtr;
- if (m_iterable->m_metaSequence.valueMetaType() == QMetaType::fromType<QVariant>())
- dataPtr = &v;
- else
- dataPtr = v.data();
- m_iterable->m_metaSequence.valueAtConstIterator(m_iterator, dataPtr);
- return v;
-}
/*!
+ \fn bool QTaggedIterator::operator==(const StdIterator &other) const
+
Returns \c true if \a other points to the same item as this
iterator; otherwise returns \c false.
\sa operator!=()
*/
-bool QSequentialIterable::const_iterator::operator==(const const_iterator &other) const
-{
- return m_iterable->m_metaSequence.compareConstIterator(
- m_iterator, other.m_iterator);
-}
/*!
+ \fn bool QTaggedIterator::operator!=(const StdIterator &other) const
+
Returns \c true if \a other points to a different item than this
iterator; otherwise returns \c false.
\sa operator==()
*/
-bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other) const
-{
- return !m_iterable->m_metaSequence.compareConstIterator(
- m_iterator, other.m_iterator);
-}
/*!
+ \fn QTaggedIterator &QTaggedIterator::operator++()
+
The prefix ++ operator (\c{++it}) advances the iterator to the
next item in the container and returns an iterator to the new current
item.
@@ -311,30 +535,20 @@ bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other
\sa operator--()
*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++()
-{
- m_iterable->m_metaSequence.advanceConstIterator(m_iterator, 1);
- return *this;
-}
/*!
+ \fn QTaggedIterator QTaggedIterator::operator++(int)
\overload
The postfix ++ operator (\c{it++}) advances the iterator to the
next item in the container and returns an iterator to the previously
current item.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int)
-{
- const_iterator result(
- m_iterable,
- m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer()));
- m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator);
- m_iterable->m_metaSequence.advanceConstIterator(m_iterator, 1);
- return result;
-}
+
/*!
+ \fn QTaggedIterator &QTaggedIterator::operator--()
+
The prefix -- operator (\c{--it}) makes the preceding item
current and returns an iterator to the new current item.
@@ -345,13 +559,9 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato
\sa operator++(), canReverseIterate()
*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--()
-{
- m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -1);
- return *this;
-}
/*!
+ \fn QTaggedIterator QTaggedIterator::operator--(int)
\overload
The postfix -- operator (\c{it--}) makes the preceding item
@@ -362,28 +572,19 @@ QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operat
\sa canReverseIterate()
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int)
-{
- const_iterator result(
- m_iterable,
- m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer()));
- m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator);
- m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -1);
- return result;
-}
+
/*!
+ \fn QTaggedIterator &QTaggedIterator::operator+=(qsizetype j)
+
Advances the iterator by \a j items.
\sa operator-=(), operator+()
*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j)
-{
- m_iterable->m_metaSequence.advanceConstIterator(m_iterator, j);
- return *this;
-}
/*!
+ \fn QTaggedIterator &QTaggedIterator::operator-=(qsizetype j)
+
Makes the iterator go back by \a j items.
If the container in the QVariant does not support bi-directional iteration, calling this function
@@ -391,29 +592,19 @@ QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operat
\sa operator+=(), operator-(), canReverseIterate()
*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j)
-{
- m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -j);
- return *this;
-}
/*!
+ \fn QTaggedIterator QTaggedIterator::operator+(qsizetype j) const
+
Returns an iterator to the item at \a j positions forward from
this iterator.
\sa operator-(), operator+=()
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const
-{
- const_iterator result(
- m_iterable,
- m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer()));
- m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator);
- m_iterable->m_metaSequence.advanceConstIterator(result.m_iterator, j);
- return result;
-}
/*!
+ \fn QTaggedIterator QTaggedIterator::operator-(qsizetype j) const
+
Returns an iterator to the item at \a j positions backward from
this iterator.
@@ -422,14 +613,13 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato
\sa operator+(), operator-=(), canReverseIterate()
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const
-{
- const_iterator result(
- m_iterable,
- m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer()));
- m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator);
- m_iterable->m_metaSequence.advanceConstIterator(result.m_iterator, -j);
- return result;
-}
+
+/*!
+ \fn qsizetype QTaggedIterator::operator-(const QTaggedIterator &j) const
+
+ Returns the distance between the two iterators.
+
+ \sa operator+(), operator-=(), canReverseIterator()
+*/
QT_END_NAMESPACE
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
diff --git a/src/corelib/kernel/qiterable_p.cpp b/src/corelib/kernel/qiterable_p.cpp
new file mode 100644
index 0000000000..ea569cebd5
--- /dev/null
+++ b/src/corelib/kernel/qiterable_p.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/private/qiterable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QIterablePrivate {
+
+const void *coerceType(QVariant &value, const QMetaType &type)
+{
+ if (type == QMetaType::fromType<QVariant>()) {
+ return &value;
+ } else if (type == value.metaType()) {
+ return value.constData();
+ } else if (value.canConvert(type)) {
+ value.convert(type);
+ return value.constData();
+ }
+
+ value = QVariant(type);
+ return value.constData();
+}
+
+} // namespace QIterablePrivate
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qiterable_p.h b/src/corelib/kernel/qiterable_p.h
new file mode 100644
index 0000000000..33b190a59a
--- /dev/null
+++ b/src/corelib/kernel/qiterable_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QITERABLE_P_H
+#define QITERABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QIterablePrivate {
+
+const void *coerceType(QVariant &value, const QMetaType &type);
+
+template<typename Callback>
+static QVariant retrieveElement(const QMetaType &type, Callback callback)
+{
+ QVariant v(type);
+ void *dataPtr;
+ if (type == QMetaType::fromType<QVariant>())
+ dataPtr = &v;
+ else
+ dataPtr = v.data();
+ callback(dataPtr);
+ return v;
+}
+
+} // namespace QIterablePrivate
+
+QT_END_NAMESPACE
+
+#endif // QITERABLE_P_H
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 7b78b96d09..7977335c98 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -54,7 +54,6 @@
#include "quuid.h"
#include "qvariant.h"
#include "qdatastream.h"
-#include "qiterable.h"
#if QT_CONFIG(regularexpression)
# include "qregularexpression.h"
@@ -73,6 +72,8 @@
# include "qcbormap.h"
# include "qbytearraylist.h"
# include "qmetaobject.h"
+# include "qsequentialiterable.h"
+# include "qassociativeiterable.h"
#endif
#if QT_CONFIG(itemmodel)
@@ -1829,11 +1830,12 @@ static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType
}
}
+#ifndef QT_BOOTSTRAPPED
static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
{
const QMetaType::ConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromType.id(),
- qMetaTypeId<QSequentialIterable>()));
+ customTypesConversionRegistry()->function(
+ qMakePair(fromType.id(), qMetaTypeId<QIterable<QMetaSequence>>()));
if (!f)
return false;
@@ -1851,14 +1853,13 @@ static bool convertIterableToVariantList(QMetaType fromType, const void *from, v
static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
{
const QMetaType::ConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromType.id(),
- qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()));
+ customTypesConversionRegistry()->function(
+ qMakePair(fromType.id(), qMetaTypeId<QIterable<QMetaAssociation>>()));
if (!f)
return false;
- QtMetaTypePrivate::QAssociativeIterableImpl iter;
- (*f)(from, &iter);
- QAssociativeIterable map(iter);
+ QAssociativeIterable map;
+ (*f)(from, &map);
QVariantMap &h = *static_cast<QVariantMap *>(to);
h.clear();
auto end = map.end();
@@ -1870,14 +1871,13 @@ static bool convertIterableToVariantMap(QMetaType fromType, const void *from, vo
static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
{
const QMetaType::ConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromType.id(),
- qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()));
+ customTypesConversionRegistry()->function(
+ qMakePair(fromType.id(), qMetaTypeId<QIterable<QMetaAssociation>>()));
if (!f)
return false;
- QtMetaTypePrivate::QAssociativeIterableImpl iter;
- (*f)(from, &iter);
- QAssociativeIterable map(iter);
+ QAssociativeIterable map;
+ (*f)(from, &map);
QVariantHash &h = *static_cast<QVariantHash *>(to);
h.clear();
h.reserve(map.size());
@@ -1886,6 +1886,7 @@ static bool convertIterableToVariantHash(QMetaType fromType, const void *from, v
h.insert(it.key().toString(), it.value());
return true;
}
+#endif
static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
{
@@ -1917,6 +1918,7 @@ static bool convertIterableToVariantPair(QMetaType fromType, const void *from, v
return true;
}
+#ifndef QT_BOOTSTRAPPED
static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
{
using namespace QtMetaTypePrivate;
@@ -1935,6 +1937,14 @@ static bool convertToSequentialIterable(QMetaType fromType, const void *from, vo
i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
return true;
}
+
+ QSequentialIterable impl;
+ if (QMetaType::convert(
+ fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &impl)) {
+ i = std::move(impl);
+ return true;
+ }
+
return false;
}
@@ -1944,23 +1954,24 @@ static bool convertToAssociativeIterable(QMetaType fromType, const void *from, v
QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
if (fromType.id() == QMetaType::QVariantMap) {
- i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast<const QVariantMap *>(from)));
+ i = QAssociativeIterable(reinterpret_cast<const QVariantMap *>(from));
return true;
}
if (fromType.id() == QMetaType::QVariantHash) {
- i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast<const QVariantHash *>(from)));
+ i = QAssociativeIterable(reinterpret_cast<const QVariantHash *>(from));
return true;
}
- QAssociativeIterableImpl impl;
- if (QMetaType::convert(fromType, from, QMetaType::fromType<QtMetaTypePrivate::QAssociativeIterableImpl>(), &impl)) {
- i = QAssociativeIterable(impl);
+
+ QAssociativeIterable impl;
+ if (QMetaType::convert(
+ fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &impl)) {
+ i = std::move(impl);
return true;
}
+
return false;
}
-
-#ifndef QT_BOOTSTRAPPED
static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
{
const QMetaObject *f = fromType.metaObject();
@@ -2022,6 +2033,10 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
}
}
+ if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
+ return true;
+
+#ifndef QT_BOOTSTRAPPED
// handle iterables
if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
return true;
@@ -2032,16 +2047,12 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
return true;
- if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
- return true;
-
if (toTypeId == qMetaTypeId<QSequentialIterable>())
return convertToSequentialIterable(fromType, from, to);
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
return convertToAssociativeIterable(fromType, from, to);
-#ifndef QT_BOOTSTRAPPED
// handle QObject conversion
if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
QObject *fromObject = *static_cast<QObject * const *>(from);
@@ -2153,13 +2164,15 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
if (f)
return true;
+#ifndef QT_BOOTSTRAPPED
if (toTypeId == QVariantList && hasRegisteredConverterFunction(
- fromTypeId, qMetaTypeId<QSequentialIterable>()))
+ fromTypeId, qMetaTypeId<QIterable<QMetaSequence>>()))
return true;
if ((toTypeId == QVariantHash || toTypeId == QVariantMap) && hasRegisteredConverterFunction(
- fromTypeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))
+ fromTypeId, qMetaTypeId<QIterable<QMetaAssociation>>()))
return true;
+#endif
if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
fromTypeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 6d31441b73..f28bfead5c 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -48,6 +48,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qdatastream.h>
+#include <QtCore/qiterable.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#endif
@@ -600,268 +601,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
namespace QtMetaTypePrivate {
-namespace QtMetaTypePrivate {
-
-template<typename const_iterator>
-struct IteratorOwnerCommon
-{
- static void assign(void **ptr, const_iterator iterator)
- {
- *ptr = new const_iterator(iterator);
- }
- static void assign(void **ptr, void * const * src)
- {
- *ptr = new const_iterator(*static_cast<const_iterator*>(*src));
- }
-
- static void advance(void **iterator, int step)
- {
- const_iterator &it = *static_cast<const_iterator*>(*iterator);
- std::advance(it, step);
- }
-
- static void destroy(void **ptr)
- {
- delete static_cast<const_iterator*>(*ptr);
- }
-
- static bool equal(void * const *it, void * const *other)
- {
- return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
- }
-};
-
-template<typename const_iterator>
-struct IteratorOwner : IteratorOwnerCommon<const_iterator>
-{
- static void getData(void * const *iterator, void *dataPtr)
- {
- const_iterator *it = static_cast<const_iterator*>(*iterator);
- typename const_iterator::value_type *data = static_cast<typename const_iterator::value_type *>(dataPtr);
- *data = **it;
- }
-
- static void getData(const_iterator it, void *dataPtr)
- {
- typename const_iterator::value_type *data = static_cast<typename const_iterator::value_type *>(dataPtr);
- *data = *it;
- }
-};
-
-template<typename value_type>
-struct IteratorOwner<const value_type*>
-{
-private:
- // We need to disable typed overloads of assign() and getData() if the value_type
- // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
- // type as part of the overload signature.
- struct Dummy {};
- typedef typename std::conditional<std::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
-public:
- static void assign(void **ptr, const value_type_OR_Dummy *iterator )
- {
- *ptr = const_cast<value_type*>(iterator);
- }
- static void assign(void **ptr, void * const * src)
- {
- *ptr = static_cast<value_type*>(*src);
- }
-
- static void advance(void **iterator, int step)
- {
- value_type *it = static_cast<value_type*>(*iterator);
- std::advance(it, step);
- *iterator = it;
- }
-
- static void destroy(void **)
- {
- }
-
- static void getData(void * const *iterator, void *dataPtr)
- {
- *static_cast<value_type *>(dataPtr) = *static_cast<value_type * const>(*iterator);
- }
-
- static void getData(const value_type_OR_Dummy *it, void *dataPtr)
- {
- *static_cast<value_type *>(dataPtr) = *static_cast<value_type const *>(it);
- }
-
- static bool equal(void * const *it, void * const *other)
- {
- return static_cast<value_type const *>(*it) == static_cast<value_type const *>(*other);
- }
-};
-
-}
namespace QtMetaTypePrivate {
-template<typename T, bool = std::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
-struct AssociativeContainerAccessor
-{
- static const typename T::key_type& getKey(const typename T::const_iterator &it)
- {
- return it.key();
- }
-
- static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
- {
- return it.value();
- }
-};
-
-template<typename T, bool = std::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
-struct StlStyleAssociativeContainerAccessor;
-
-template<typename T>
-struct StlStyleAssociativeContainerAccessor<T, true>
-{
- static const typename T::key_type& getKey(const typename T::const_iterator &it)
- {
- return it->first;
- }
-
- static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
- {
- return it->second;
- }
-};
-
-template<typename T>
-struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
-{
-};
-
-class QAssociativeIterableImpl
-{
-public:
- const void *_iterable;
- void *_iterator;
- QMetaType _metaType_key;
- QMetaType _metaType_value;
- typedef int(*sizeFunc)(const void *p);
- typedef void (*findFunc)(const void *container, const void *p, void **iterator);
- typedef void (*beginFunc)(const void *p, void **);
- typedef void (*advanceFunc)(void **p, int);
- typedef void (*getFunc)(void * const *p, void *dataPtr);
- typedef void (*destroyIterFunc)(void **p);
- typedef bool (*equalIterFunc)(void * const *p, void * const *other);
- typedef void (*copyIterFunc)(void **, void * const *);
-
- sizeFunc _size;
- findFunc _find;
- beginFunc _begin;
- beginFunc _end;
- advanceFunc _advance;
- getFunc _getKey;
- getFunc _getValue;
- destroyIterFunc _destroyIter;
- equalIterFunc _equalIter;
- copyIterFunc _copyIter;
-
- template<class T>
- static int sizeImpl(const void *p)
- { return int(std::distance(static_cast<const T*>(p)->begin(),
- static_cast<const T*>(p)->end())); }
-
- template<class T>
- static void findImpl(const void *container, const void *p, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator,
- static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
-
- template<class T>
- static void advanceImpl(void **p, int step)
- { std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
-
- template<class T>
- static void beginImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
-
- template<class T>
- static void endImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
-
- template<class T>
- static void getKeyImpl(void * const *iterator, void *dataPtr)
- {
- auto *data = static_cast<typename T::key_type *>(dataPtr);
- *data = AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator));
- }
-
- template<class T>
- static void getValueImpl(void * const *iterator, void *dataPtr)
- {
- auto *data = static_cast<typename T::mapped_type *>(dataPtr);
- *data = AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator));
- }
-
-public:
- template<class T> QAssociativeIterableImpl(const T*p)
- : _iterable(p)
- , _iterator(nullptr)
- , _metaType_key(QMetaType::fromType<typename T::key_type>())
- , _metaType_value(QMetaType::fromType<typename T::mapped_type>())
- , _size(sizeImpl<T>)
- , _find(findImpl<T>)
- , _begin(beginImpl<T>)
- , _end(endImpl<T>)
- , _advance(advanceImpl<T>)
- , _getKey(getKeyImpl<T>)
- , _getValue(getValueImpl<T>)
- , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
- , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
- , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
- {
- }
-
- QAssociativeIterableImpl()
- : _iterable(nullptr)
- , _iterator(nullptr)
- , _size(nullptr)
- , _find(nullptr)
- , _begin(nullptr)
- , _end(nullptr)
- , _advance(nullptr)
- , _getKey(nullptr)
- , _getValue(nullptr)
- , _destroyIter(nullptr)
- , _equalIter(nullptr)
- , _copyIter(nullptr)
- {
- }
-
- inline void begin() { _begin(_iterable, &_iterator); }
- inline void end() { _end(_iterable, &_iterator); }
- inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
- inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
-
- inline void destroyIter() { _destroyIter(&_iterator); }
-
- inline void getCurrentKey(void *dataPtr) const { return _getKey(&_iterator, dataPtr); }
- inline void getCurrentValue(void *dataPtr) const { return _getValue(&_iterator, dataPtr); }
-
- inline void find(const void *key)
- { _find(_iterable, key, &_iterator); }
-
- int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
-
- void copy(const QAssociativeIterableImpl &other)
- {
- *this = other;
- _copyIter(&_iterator, &other._iterator);
- }
-};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QAssociativeIterableImpl, Q_MOVABLE_TYPE)
-
-template<typename From>
-struct QAssociativeIterableConvertFunctor
-{
- QAssociativeIterableImpl operator()(const From& f) const
- {
- return QAssociativeIterableImpl(&f);
- }
-};
class QPairVariantInterfaceImpl
{
@@ -1675,7 +1416,6 @@ QT_END_NAMESPACE
QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
QT_BEGIN_NAMESPACE
@@ -1692,19 +1432,53 @@ inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
}
namespace QtPrivate {
- template<typename T>
- struct AssociativeValueTypeIsMetaType<T, true>
+
+template<typename From>
+struct QSequentialIterableConvertFunctor
+{
+ QIterable<QMetaSequence> operator()(const From &f) const
{
- static bool registerConverter(int id)
- {
- const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
- return QMetaType::registerConverter<T, QtMetaTypePrivate::QAssociativeIterableImpl>(o);
- }
- return true;
+ return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
+ }
+};
+
+template<typename T>
+struct SequentialValueTypeIsMetaType<T, true>
+{
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QIterable<QMetaSequence>>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ QSequentialIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
}
- };
+ return true;
+ }
+};
+
+template<typename From>
+struct QAssociativeIterableConvertFunctor
+{
+ QIterable<QMetaAssociation> operator()(const From &f) const
+ {
+ return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
+ }
+};
+
+template<typename T>
+struct AssociativeValueTypeIsMetaType<T, true>
+{
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QIterable<QMetaAssociation>>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ QAssociativeIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
+ }
+ return true;
+ }
+};
+
}
namespace QtPrivate {
diff --git a/src/corelib/kernel/qsequentialiterable.cpp b/src/corelib/kernel/qsequentialiterable.cpp
new file mode 100644
index 0000000000..6ce41a1edf
--- /dev/null
+++ b/src/corelib/kernel/qsequentialiterable.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qsequentialiterable.h>
+#include <QtCore/qvariant.h>
+
+#include <QtCore/private/qiterable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSequentialIterable
+ \since 5.2
+ \inmodule QtCore
+ \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
+
+ This class allows several methods of accessing the values of a container held within
+ a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
+ be converted to a QVariantList.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ The container itself is not copied before iterating over it.
+
+ \sa QVariant
+*/
+
+/*!
+ \typedef QSequentialIterable::RandomAccessIterator
+ Exposes an iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::BidirectionalIterator
+ Exposes an iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::ForwardIterator
+ Exposes an iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::InputIterator
+ Exposes an iterator using std::input_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::RandomAccessConstIterator
+ Exposes a const_iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::BidirectionalConstIterator
+ Exposes a const_iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::ForwardConstIterator
+ Exposes a const_iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::InputConstIterator
+ Exposes a const_iterator using std::input_iterator_tag.
+*/
+
+/*!
+ Adds \a value to the container, at \a position, if possible.
+ */
+void QSequentialIterable::addValue(const QVariant &value, Position position)
+{
+ QVariant converted = value;
+ const void *valuePtr = QIterablePrivate::coerceType(converted, metaContainer().valueMetaType());
+
+ switch (position) {
+ case AtBegin:
+ if (metaContainer().canAddValueAtBegin())
+ metaContainer().addValueAtBegin(mutableIterable(), valuePtr);
+ break;
+ case AtEnd:
+ if (metaContainer().canAddValueAtEnd())
+ metaContainer().addValueAtEnd(mutableIterable(), valuePtr);
+ break;
+ case Unspecified:
+ if (metaContainer().canAddValue())
+ metaContainer().addValue(mutableIterable(), valuePtr);
+ break;
+ }
+}
+
+/*!
+ Removes a value from the container, at \a position, if possible.
+ */
+void QSequentialIterable::removeValue(Position position)
+{
+ switch (position) {
+ case AtBegin:
+ if (metaContainer().canRemoveValueAtBegin())
+ metaContainer().removeValueAtBegin(mutableIterable());
+ break;
+ case AtEnd:
+ if (metaContainer().canRemoveValueAtEnd())
+ metaContainer().removeValueAtEnd(mutableIterable());
+ break;
+ case Unspecified:
+ if (metaContainer().canRemoveValue())
+ metaContainer().removeValue(mutableIterable());
+ break;
+ }
+}
+
+QMetaType QSequentialIterable::valueMetaType() const
+{
+ return QMetaType(metaContainer().valueMetaType());
+}
+
+/*!
+ Returns the value at position \a idx in the container.
+*/
+QVariant QSequentialIterable::at(qsizetype idx) const
+{
+ QVariant v(valueMetaType());
+ void *dataPtr;
+ if (valueMetaType() == QMetaType::fromType<QVariant>())
+ dataPtr = &v;
+ else
+ dataPtr = v.data();
+
+ const QMetaSequence meta = metaContainer();
+ if (meta.canGetValueAtIndex()) {
+ meta.valueAtIndex(m_iterable.constPointer(), idx, dataPtr);
+ } else if (meta.canGetValueAtConstIterator()) {
+ void *iterator = meta.constBegin(m_iterable.constPointer());
+ meta.advanceConstIterator(iterator, idx);
+ meta.valueAtConstIterator(iterator, dataPtr);
+ meta.destroyConstIterator(iterator);
+ }
+
+ return v;
+}
+
+/*!
+ Sets the element at position \a idx in the container to \a value.
+*/
+void QSequentialIterable::set(qsizetype idx, const QVariant &value)
+{
+ QVariant converted = value;
+ const void *dataPtr = QIterablePrivate::coerceType(converted, metaContainer().valueMetaType());
+
+ const QMetaSequence meta = metaContainer();
+ if (meta.canSetValueAtIndex()) {
+ meta.setValueAtIndex(m_iterable.mutablePointer(), idx, dataPtr);
+ } else if (meta.canSetValueAtIterator()) {
+ void *iterator = meta.begin(m_iterable.mutablePointer());
+ meta.advanceIterator(iterator, idx);
+ meta.setValueAtIterator(iterator, dataPtr);
+ meta.destroyIterator(iterator);
+ }
+}
+
+/*!
+ \class QSequentialIterable::const_iterator
+ \since 5.2
+ \inmodule QtCore
+ \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
+
+ A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ \sa QSequentialIterable
+*/
+
+/*!
+ \class QSequentialIterable::iterator
+ \since 6.0
+ \inmodule QtCore
+ \brief The QSequentialIterable::iterator allows iteration over a container in a QVariant.
+
+ A QSequentialIterable::iterator can only be created by a QSequentialIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \sa QSequentialIterable
+*/
+
+/*!
+ Returns the current item, converted to a QVariantRef.
+*/
+QVariantRef<QSequentialIterator> QSequentialIterator::operator*() const
+{
+ return QVariantRef<QSequentialIterator>(this);
+}
+
+/*!
+ Returns the current item, converted to a QVariantPointer.
+*/
+QVariantPointer<QSequentialIterator> QSequentialIterator::operator->() const
+{
+ return QVariantPointer<QSequentialIterator>(this);
+}
+
+/*!
+ Returns the current item, converted to a QVariant.
+*/
+QVariant QSequentialConstIterator::operator*() const
+{
+ return QIterablePrivate::retrieveElement(metaContainer().valueMetaType(), [this](void *dataPtr) {
+ metaContainer().valueAtConstIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the current item, converted to a QVariantConstPointer.
+*/
+QVariantConstPointer QSequentialConstIterator::operator->() const
+{
+ return QVariantConstPointer(operator*());
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsequentialiterable.h b/src/corelib/kernel/qsequentialiterable.h
new file mode 100644
index 0000000000..72e17cfc65
--- /dev/null
+++ b/src/corelib/kernel/qsequentialiterable.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALITERABLE_H
+#define QSEQUENTIALITERABLE_H
+
+#include <QtCore/qiterable.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QSequentialIterator : public QIterator<QMetaSequence>
+{
+public:
+ using value_type = QVariant;
+ using reference = QVariantRef<QSequentialIterator>;
+ using pointer = QVariantPointer<QSequentialIterator>;
+
+ QSequentialIterator(QIterator &&it)
+ : QIterator(std::move(it))
+ {}
+
+ QVariantRef<QSequentialIterator> operator*() const;
+ QVariantPointer<QSequentialIterator> operator->() const;
+};
+
+class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator<QMetaSequence>
+{
+public:
+ using value_type = QVariant;
+ using reference = const QVariant &;
+ using pointer = QVariantConstPointer;
+
+ QSequentialConstIterator(QConstIterator &&it)
+ : QConstIterator(std::move(it))
+ {}
+
+ QVariant operator*() const;
+ QVariantConstPointer operator->() const;
+};
+
+class Q_CORE_EXPORT QSequentialIterable : public QIterable<QMetaSequence>
+{
+public:
+ using iterator = QTaggedIterator<QSequentialIterator, void>;
+ using const_iterator = QTaggedIterator<QSequentialConstIterator, void>;
+
+ using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
+ using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
+ using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
+ using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
+
+ using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
+ using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
+ using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
+ using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
+
+ template<class T>
+ QSequentialIterable(const T *p)
+ : QIterable(QMetaSequence::fromContainer<T>(), p)
+ {
+ Q_UNUSED(m_revision);
+ }
+
+ template<class T>
+ QSequentialIterable(T *p)
+ : QIterable(QMetaSequence::fromContainer<T>(), p)
+ {
+ }
+
+ QSequentialIterable() = default;
+
+ template<typename Pointer>
+ QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
+ : QIterable(metaSequence, iterable)
+ {
+ }
+
+ QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
+ void *iterable)
+ : QIterable(metaSequence, metaType.alignOf(), iterable)
+ {
+ }
+
+ QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
+ const void *iterable)
+ : QIterable(metaSequence, metaType.alignOf(), iterable)
+ {
+ }
+
+ QSequentialIterable(QIterable<QMetaSequence> &&other) : QIterable(std::move(other)) {}
+
+ QSequentialIterable &operator=(QIterable<QMetaSequence> &&other)
+ {
+ QIterable::operator=(std::move(other));
+ return *this;
+ }
+
+ const_iterator begin() const { return constBegin(); }
+ const_iterator end() const { return constEnd(); }
+
+ const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
+ const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
+
+ iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
+ iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
+
+ QVariant at(qsizetype idx) const;
+ void set(qsizetype idx, const QVariant &value);
+
+ enum Position { Unspecified, AtBegin, AtEnd };
+ void addValue(const QVariant &value, Position position = Unspecified);
+ void removeValue(Position position = Unspecified);
+
+ QMetaType valueMetaType() const;
+};
+
+template<>
+inline QVariantRef<QSequentialIterator>::operator QVariant() const
+{
+ if (m_pointer == nullptr)
+ return QVariant();
+ const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
+ QVariant v(metaType);
+ void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
+ m_pointer->metaContainer().valueAtIterator(m_pointer->constIterator(), dataPtr);
+ return v;
+}
+
+template<>
+inline QVariantRef<QSequentialIterator> &QVariantRef<QSequentialIterator>::operator=(
+ const QVariant &value)
+{
+ if (m_pointer == nullptr)
+ return *this;
+ const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
+ const void *dataPtr = metaType == QMetaType::fromType<QVariant>()
+ ? &value
+ : value.constData();
+ m_pointer->metaContainer().setValueAtIterator(m_pointer->constIterator(), dataPtr);
+ return *this;
+}
+
+Q_DECLARE_TYPEINFO(QSequentialIterable, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSequentialIterable::iterator, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QSEQUENTIALITERABLE_H
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index d0a548bc74..603c49ebfe 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2617,348 +2617,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
*/
/*!
- \class QAssociativeIterable
- \since 5.2
- \inmodule QtCore
- \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
-
- This class allows several methods of accessing the elements of an associative container held within
- a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
- be converted to a QVariantHash or QVariantMap.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- The container itself is not copied before iterating over it.
-
- \sa QVariant
-*/
-
-/*!
- \internal
-*/
-QAssociativeIterable::QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl)
- : m_impl(impl)
-{
-}
-
-QAssociativeIterable::const_iterator::const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_)
- : m_impl(iter.m_impl), ref(ref_)
-{
- ref->ref();
-}
-
-QAssociativeIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_)
- : m_impl(impl), ref(ref_)
-{
- ref->ref();
-}
-
-void QAssociativeIterable::const_iterator::begin()
-{
- m_impl.begin();
-}
-
-void QAssociativeIterable::const_iterator::end()
-{
- m_impl.end();
-}
-
-void QAssociativeIterable::const_iterator::find(const QVariant &key)
-{
- Q_ASSERT(key.metaType() == m_impl._metaType_key);
- m_impl.find(key.constData());
-}
-
-/*!
- Returns a QAssociativeIterable::const_iterator for the beginning of the container. This
- can be used in stl-style iteration.
-
- \sa end()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::begin() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.begin();
- return it;
-}
-
-/*!
- Returns a QAssociativeIterable::const_iterator for the end of the container. This
- can be used in stl-style iteration.
-
- \sa begin()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::end() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.end();
- return it;
-}
-
-/*!
- \since 5.5
-
- Returns a QAssociativeIterable::const_iterator for the given key \a key
- in the container, if the types are convertible.
-
- If the key is not found, returns end().
-
- This can be used in stl-style iteration.
-
- \sa begin(), end(), value()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
-{
- const_iterator it(*this, new QAtomicInt(0));
- QVariant key_ = key;
- if (key_.canConvert(m_impl._metaType_key) && key_.convert(m_impl._metaType_key))
- it.find(key_);
- else
- it.end();
- return it;
-}
-
-/*!
- Returns the value for the given \a key in the container, if the types are convertible.
-
- \sa find()
-*/
-QVariant QAssociativeIterable::value(const QVariant &key) const
-{
- const const_iterator it = find(key);
- if (it == end())
- return QVariant();
- return *it;
-}
-
-/*!
- Returns the number of elements in the container.
-*/
-int QAssociativeIterable::size() const
-{
- return m_impl.size();
-}
-
-/*!
- \class QAssociativeIterable::const_iterator
- \since 5.2
- \inmodule QtCore
- \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
-
- A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
- and can be used in a way similar to other stl-style iterators.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- \sa QAssociativeIterable
-*/
-
-
-/*!
- Destroys the QAssociativeIterable::const_iterator.
-*/
-QAssociativeIterable::const_iterator::~const_iterator()
-{
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
-}
-
-/*!
- Creates a copy of \a other.
-*/
-QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other)
- : m_impl(other.m_impl), ref(other.ref)
-{
- ref->ref();
-}
-
-/*!
- Assigns \a other to this.
-*/
-QAssociativeIterable::const_iterator&
-QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
-{
- other.ref->ref();
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
- m_impl = other.m_impl;
- ref = other.ref;
- return *this;
-}
-
-/*!
- Returns the current value, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::operator*() const
-{
- QVariant v(m_impl._metaType_value);
- void *dataPtr;
- if (m_impl._metaType_value == QMetaType::fromType<QVariant>())
- dataPtr = &v;
- else
- dataPtr = v.data();
- m_impl.getCurrentValue(dataPtr);
- return v;
-}
-
-/*!
- Returns the current key, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::key() const
-{
- QVariant v(m_impl._metaType_key);
- void *dataPtr;
- if (m_impl._metaType_key == QMetaType::fromType<QVariant>())
- dataPtr = &v;
- else
- dataPtr = v.data();
- m_impl.getCurrentKey(dataPtr);
- return v;
-}
-
-/*!
- Returns the current value, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::value() const
-{
- return operator*();
-}
-
-/*!
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const
-{
- return m_impl.equal(other.m_impl);
-}
-
-/*!
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const
-{
- return !m_impl.equal(other.m_impl);
-}
-
-/*!
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the container and returns an iterator to the new current
- item.
-
- Calling this function on QAssociativeIterable::end() leads to undefined results.
-
- \sa operator--()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++()
-{
- m_impl.advance(1);
- return *this;
-}
-
-/*!
- \overload
-
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the container and returns an iterator to the previously
- current item.
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int)
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(1);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QAssociativeIterable::begin() leads to undefined results.
-
- \sa operator++()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--()
-{
- m_impl.advance(-1);
- return *this;
-}
-
-/*!
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int)
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(-1);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- Advances the iterator by \a j items.
-
- \sa operator-=(), operator+()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j)
-{
- m_impl.advance(j);
- return *this;
-}
-
-/*!
- Makes the iterator go back by \a j items.
-
- \sa operator+=(), operator-()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j)
-{
- m_impl.advance(-j);
- return *this;
-}
-
-/*!
- Returns an iterator to the item at \a j positions forward from
- this iterator.
-
- \sa operator-(), operator+=()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(j);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- Returns an iterator to the item at \a j positions backward from
- this iterator.
-
- \sa operator+(), operator-=()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(-j);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
\class QVariantRef
\since 6.0
\inmodule QtCore
@@ -2979,6 +2637,13 @@ QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::opera
*/
/*!
+ \fn QVariantRef &QVariantRef::operator=(const QVariant &value)
+
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
+ */
+
+/*!
\fn QVariantRef &QVariantRef::operator=(const QVariantRef &value)
Assigns a new \a value to the value pointed to by the pointer this
@@ -2993,6 +2658,12 @@ QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::opera
*/
/*!
+ \fn QVariantRef::operator QVariant() const
+
+ Resolves the QVariantRef to an actual QVariant.
+*/
+
+/*!
\fn void swap(QVariantRef a, QVariantRef b)
Swaps the values pointed to by the pointers the QVariantRefs
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index f9d46472b0..1825d4be88 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -580,61 +580,6 @@ inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
#endif
Q_DECLARE_SHARED(QVariant)
-class Q_CORE_EXPORT QAssociativeIterable
-{
- QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
-public:
- struct Q_CORE_EXPORT const_iterator
- {
- private:
- QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
- QAtomicInt *ref;
- friend class QAssociativeIterable;
- explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_);
-
- explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_);
-
- void begin();
- void end();
- void find(const QVariant &key);
- public:
- ~const_iterator();
- const_iterator(const const_iterator &other);
-
- const_iterator& operator=(const const_iterator &other);
-
- const QVariant key() const;
-
- const QVariant value() const;
-
- 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; }
- };
-
- friend struct const_iterator;
-
- explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl);
- QAssociativeIterable() {}
-
- const_iterator begin() const;
- const_iterator end() const;
- const_iterator find(const QVariant &key) const;
-
- QVariant value(const QVariant &key) const;
-
- int size() const;
-};
-
#ifndef QT_MOC
template<typename T> inline T qvariant_cast(const QVariant &v)