From 5c808073af5b8f1290602fcccf60666c9a3682f8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Sep 2020 18:25:02 +0200 Subject: 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 --- src/corelib/kernel/kernel.pri | 6 + src/corelib/kernel/qassociativeiterable.cpp | 253 +++++++++++ src/corelib/kernel/qassociativeiterable.h | 194 ++++++++ src/corelib/kernel/qiterable.cpp | 680 ++++++++++++++++++---------- src/corelib/kernel/qiterable.h | 486 +++++++++++++++++--- src/corelib/kernel/qiterable_p.cpp | 63 +++ src/corelib/kernel/qiterable_p.h | 80 ++++ src/corelib/kernel/qmetatype.cpp | 65 +-- src/corelib/kernel/qmetatype.h | 318 ++----------- src/corelib/kernel/qsequentialiterable.cpp | 258 +++++++++++ src/corelib/kernel/qsequentialiterable.h | 186 ++++++++ src/corelib/kernel/qvariant.cpp | 355 +-------------- src/corelib/kernel/qvariant.h | 55 --- 13 files changed, 1985 insertions(+), 1014 deletions(-) create mode 100644 src/corelib/kernel/qassociativeiterable.cpp create mode 100644 src/corelib/kernel/qassociativeiterable.h create mode 100644 src/corelib/kernel/qiterable_p.cpp create mode 100644 src/corelib/kernel/qiterable_p.h create mode 100644 src/corelib/kernel/qsequentialiterable.cpp create mode 100644 src/corelib/kernel/qsequentialiterable.h (limited to 'src/corelib/kernel') 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 +#include + +#include + +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::value() const +{ + const QMetaType mappedMetaType(metaContainer().mappedMetaType()); + return QVariantRef(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::operator*() const +{ + return QVariantRef(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::operator->() const +{ + return QVariantPointer(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 +#include + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QAssociativeIterator : public QIterator +{ +public: + using key_type = QVariant; + using mapped_type = QVariant; + using reference = QVariantRef; + using pointer = QVariantPointer; + + QAssociativeIterator(QIterator &&it) + : QIterator(std::move(it)) + {} + + QVariant key() const; + QVariantRef value() const; + + QVariantRef operator*() const; + QVariantPointer operator->() const; +}; + +class Q_CORE_EXPORT QAssociativeConstIterator : public QConstIterator +{ +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 +{ +public: + using iterator = QTaggedIterator; + using const_iterator = QTaggedIterator; + + using RandomAccessIterator = QTaggedIterator; + using BidirectionalIterator = QTaggedIterator; + using ForwardIterator = QTaggedIterator; + using InputIterator = QTaggedIterator; + + using RandomAccessConstIterator = QTaggedIterator; + using BidirectionalConstIterator = QTaggedIterator; + using ForwardConstIterator = QTaggedIterator; + using InputConstIterator = QTaggedIterator; + + template + QAssociativeIterable(const T *p) + : QIterable(QMetaAssociation::fromContainer(), p) + { + } + + template + QAssociativeIterable(T *p) + : QIterable(QMetaAssociation::fromContainer(), p) + { + } + + QAssociativeIterable() = default; + + template + 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 &&other) : QIterable(std::move(other)) {} + + QAssociativeIterable &operator=(QIterable &&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::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() ? &v : v.data(); + metaAssociation.mappedAtIterator(m_pointer->constIterator(), dataPtr); + return v; +} + +template<> +inline QVariantRef &QVariantRef::operator=( + const QVariant &value) +{ + if (m_pointer == nullptr) + return *this; + const QMetaType metaType(m_pointer->metaContainer().mappedMetaType()); + const void *dataPtr = metaType == QMetaType::fromType() + ? &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 -#include 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()) - 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()) { - 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()) - 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 #include #include -#include #include QT_BEGIN_NAMESPACE @@ -100,114 +99,453 @@ namespace QtPrivate { }; } -class Q_CORE_EXPORT QSequentialIterable +template +class QTaggedIterator : public Iterator { - uint m_revision = 0; - QtPrivate::QConstPreservingPointer 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 + && !metaContainer.hasRandomAccessIterator()) { + qFatal("You cannot use this iterator as a random access iterator"); + this->clearIterator(); + } + + if (std::is_base_of_v + && !metaContainer.hasBidirectionalIterator()) { + qFatal("You cannot use this iterator as a bidirectional iterator"); + this->clearIterator(); + } + + if (std::is_base_of_v + && !metaContainer.hasForwardIterator()) { + qFatal("You cannot use this iterator as a forward iterator"); + this->clearIterator(); + } + + if (std::is_base_of_v + && !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 QIterable; + +template +class QBaseIterator +{ +private: + QtPrivate::QConstPreservingPointer> m_iterable; + void *m_iterator = nullptr; + +protected: + QBaseIterator() = default; + QBaseIterator(const QIterable *iterable, void *iterator) + : m_iterable(iterable), m_iterator(iterator) + {} + + QBaseIterator(QIterable *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 *mutableIterable() const + { + return m_iterable.mutablePointer(); + } + + const QIterable *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 +struct QIterator : public QBaseIterator +{ public: - struct Q_CORE_EXPORT const_iterator + using difference_type = qsizetype; + + explicit QIterator(QIterable *iterable, void *iterator) + : QBaseIterator(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 *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 *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 *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 *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 +struct QConstIterator : public QBaseIterator +{ +public: + using difference_type = qsizetype; + + explicit QConstIterator(const QIterable *iterable, void *iterator) + : QBaseIterator(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 QIterable +{ + friend class QBaseIterator; - friend struct const_iterator; +protected: + uint m_revision = 0; + QtPrivate::QConstPreservingPointer m_iterable; + Container m_metaContainer; + +public: + QIterable() = default; template - QSequentialIterable(const T *p) - : m_iterable(p) - , m_metaSequence(QMetaSequence::fromContainer()) + QIterable(const Container &metaContainer, const T *p) + : m_iterable(p), m_metaContainer(metaContainer) { - Q_UNUSED(m_revision); } - QSequentialIterable() = default; + template + QIterable(const Container &metaContainer, T *p) + : m_iterable(p), m_metaContainer(metaContainer) + { + } template - 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(m_iterable.constPointer()); } - QMetaSequence metaSequence() const { return m_metaSequence; } - QMetaType valueMetaType() const { return m_metaSequence.valueMetaType(); } -}; + QConstIterator constBegin() const + { + return QConstIterator(this, m_metaContainer.constBegin(constIterable())); + } -namespace QtPrivate { + QConstIterator constEnd() const + { + return QConstIterator(this, m_metaContainer.constEnd(constIterable())); + } -template -struct QSequentialIterableConvertFunctor -{ - QSequentialIterable operator()(const From &f) const + QIterator mutableBegin() { - return QSequentialIterable(&f); + return QIterator(this, m_metaContainer.begin(mutableIterable())); } -}; -template -struct SequentialValueTypeIsMetaType -{ - static bool registerConverter(int id) + QIterator mutableEnd() { - const int toId = qMetaTypeId(); - if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { - QSequentialIterableConvertFunctor o; - return QMetaType::registerConverter(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 + +QT_BEGIN_NAMESPACE + +namespace QIterablePrivate { + +const void *coerceType(QVariant &value, const QMetaType &type) +{ + if (type == QMetaType::fromType()) { + 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 +#include + +QT_BEGIN_NAMESPACE + +namespace QIterablePrivate { + +const void *coerceType(QVariant &value, const QMetaType &type); + +template +static QVariant retrieveElement(const QMetaType &type, Callback callback) +{ + QVariant v(type); + void *dataPtr; + if (type == QMetaType::fromType()) + 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())); + customTypesConversionRegistry()->function( + qMakePair(fromType.id(), qMetaTypeId>())); 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())); + customTypesConversionRegistry()->function( + qMakePair(fromType.id(), qMetaTypeId>())); if (!f) return false; - QtMetaTypePrivate::QAssociativeIterableImpl iter; - (*f)(from, &iter); - QAssociativeIterable map(iter); + QAssociativeIterable map; + (*f)(from, &map); QVariantMap &h = *static_cast(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())); + customTypesConversionRegistry()->function( + qMakePair(fromType.id(), qMetaTypeId>())); if (!f) return false; - QtMetaTypePrivate::QAssociativeIterableImpl iter; - (*f)(from, &iter); - QAssociativeIterable map(iter); + QAssociativeIterable map; + (*f)(from, &map); QVariantHash &h = *static_cast(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(from)); return true; } + + QSequentialIterable impl; + if (QMetaType::convert( + fromType, from, QMetaType::fromType>(), &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(to); if (fromType.id() == QMetaType::QVariantMap) { - i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast(from))); + i = QAssociativeIterable(reinterpret_cast(from)); return true; } if (fromType.id() == QMetaType::QVariantHash) { - i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast(from))); + i = QAssociativeIterable(reinterpret_cast(from)); return true; } - QAssociativeIterableImpl impl; - if (QMetaType::convert(fromType, from, QMetaType::fromType(), &impl)) { - i = QAssociativeIterable(impl); + + QAssociativeIterable impl; + if (QMetaType::convert( + fromType, from, QMetaType::fromType>(), &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()) return convertToSequentialIterable(fromType, from, to); if (toTypeId == qMetaTypeId()) return convertToAssociativeIterable(fromType, from, to); -#ifndef QT_BOOTSTRAPPED // handle QObject conversion if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) { QObject *fromObject = *static_cast(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())) + fromTypeId, qMetaTypeId>())) return true; if ((toTypeId == QVariantHash || toTypeId == QVariantMap) && hasRegisteredConverterFunction( - fromTypeId, qMetaTypeId())) + fromTypeId, qMetaTypeId>())) return true; +#endif if (toTypeId == QVariantPair && hasRegisteredConverterFunction( fromTypeId, qMetaTypeId())) 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 #include #include +#include #ifndef QT_NO_QOBJECT #include #endif @@ -600,268 +601,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags) Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \ namespace QtMetaTypePrivate { -namespace QtMetaTypePrivate { - -template -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(*src)); - } - - static void advance(void **iterator, int step) - { - const_iterator &it = *static_cast(*iterator); - std::advance(it, step); - } - - static void destroy(void **ptr) - { - delete static_cast(*ptr); - } - - static bool equal(void * const *it, void * const *other) - { - return *static_cast(*it) == *static_cast(*other); - } -}; - -template -struct IteratorOwner : IteratorOwnerCommon -{ - static void getData(void * const *iterator, void *dataPtr) - { - const_iterator *it = static_cast(*iterator); - typename const_iterator::value_type *data = static_cast(dataPtr); - *data = **it; - } - - static void getData(const_iterator it, void *dataPtr) - { - typename const_iterator::value_type *data = static_cast(dataPtr); - *data = *it; - } -}; - -template -struct IteratorOwner -{ -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::value, Dummy, value_type>::type value_type_OR_Dummy; -public: - static void assign(void **ptr, const value_type_OR_Dummy *iterator ) - { - *ptr = const_cast(iterator); - } - static void assign(void **ptr, void * const * src) - { - *ptr = static_cast(*src); - } - - static void advance(void **iterator, int step) - { - value_type *it = static_cast(*iterator); - std::advance(it, step); - *iterator = it; - } - - static void destroy(void **) - { - } - - static void getData(void * const *iterator, void *dataPtr) - { - *static_cast(dataPtr) = *static_cast(*iterator); - } - - static void getData(const value_type_OR_Dummy *it, void *dataPtr) - { - *static_cast(dataPtr) = *static_cast(it); - } - - static bool equal(void * const *it, void * const *other) - { - return static_cast(*it) == static_cast(*other); - } -}; - -} namespace QtMetaTypePrivate { -template::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 >::value> -struct StlStyleAssociativeContainerAccessor; - -template -struct StlStyleAssociativeContainerAccessor -{ - 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 -struct AssociativeContainerAccessor : public StlStyleAssociativeContainerAccessor -{ -}; - -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 - static int sizeImpl(const void *p) - { return int(std::distance(static_cast(p)->begin(), - static_cast(p)->end())); } - - template - static void findImpl(const void *container, const void *p, void **iterator) - { IteratorOwner::assign(iterator, - static_cast(container)->find(*static_cast(p))); } - - template - static void advanceImpl(void **p, int step) - { std::advance(*static_cast(*p), step); } - - template - static void beginImpl(const void *container, void **iterator) - { IteratorOwner::assign(iterator, static_cast(container)->begin()); } - - template - static void endImpl(const void *container, void **iterator) - { IteratorOwner::assign(iterator, static_cast(container)->end()); } - - template - static void getKeyImpl(void * const *iterator, void *dataPtr) - { - auto *data = static_cast(dataPtr); - *data = AssociativeContainerAccessor::getKey(*static_cast(*iterator)); - } - - template - static void getValueImpl(void * const *iterator, void *dataPtr) - { - auto *data = static_cast(dataPtr); - *data = AssociativeContainerAccessor::getValue(*static_cast(*iterator)); - } - -public: - template QAssociativeIterableImpl(const T*p) - : _iterable(p) - , _iterator(nullptr) - , _metaType_key(QMetaType::fromType()) - , _metaType_value(QMetaType::fromType()) - , _size(sizeImpl) - , _find(findImpl) - , _begin(beginImpl) - , _end(endImpl) - , _advance(advanceImpl) - , _getKey(getKeyImpl) - , _getValue(getValueImpl) - , _destroyIter(IteratorOwner::destroy) - , _equalIter(IteratorOwner::equal) - , _copyIter(IteratorOwner::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 -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::registerConverter(int id) } namespace QtPrivate { - template - struct AssociativeValueTypeIsMetaType + +template +struct QSequentialIterableConvertFunctor +{ + QIterable operator()(const From &f) const { - static bool registerConverter(int id) - { - const int toId = qMetaTypeId(); - if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { - QtMetaTypePrivate::QAssociativeIterableConvertFunctor o; - return QMetaType::registerConverter(o); - } - return true; + return QIterable(QMetaSequence::fromContainer(), &f); + } +}; + +template +struct SequentialValueTypeIsMetaType +{ + static bool registerConverter(int id) + { + const int toId = qMetaTypeId>(); + if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { + QSequentialIterableConvertFunctor o; + return QMetaType::registerConverter>(o); } - }; + return true; + } +}; + +template +struct QAssociativeIterableConvertFunctor +{ + QIterable operator()(const From &f) const + { + return QIterable(QMetaAssociation::fromContainer(), &f); + } +}; + +template +struct AssociativeValueTypeIsMetaType +{ + static bool registerConverter(int id) + { + const int toId = qMetaTypeId>(); + if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { + QAssociativeIterableConvertFunctor o; + return QMetaType::registerConverter>(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 +#include + +#include + +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()) + 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::operator*() const +{ + return QVariantRef(this); +} + +/*! + Returns the current item, converted to a QVariantPointer. +*/ +QVariantPointer QSequentialIterator::operator->() const +{ + return QVariantPointer(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 +#include + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QSequentialIterator : public QIterator +{ +public: + using value_type = QVariant; + using reference = QVariantRef; + using pointer = QVariantPointer; + + QSequentialIterator(QIterator &&it) + : QIterator(std::move(it)) + {} + + QVariantRef operator*() const; + QVariantPointer operator->() const; +}; + +class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator +{ +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 +{ +public: + using iterator = QTaggedIterator; + using const_iterator = QTaggedIterator; + + using RandomAccessIterator = QTaggedIterator; + using BidirectionalIterator = QTaggedIterator; + using ForwardIterator = QTaggedIterator; + using InputIterator = QTaggedIterator; + + using RandomAccessConstIterator = QTaggedIterator; + using BidirectionalConstIterator = QTaggedIterator; + using ForwardConstIterator = QTaggedIterator; + using InputConstIterator = QTaggedIterator; + + template + QSequentialIterable(const T *p) + : QIterable(QMetaSequence::fromContainer(), p) + { + Q_UNUSED(m_revision); + } + + template + QSequentialIterable(T *p) + : QIterable(QMetaSequence::fromContainer(), p) + { + } + + QSequentialIterable() = default; + + template + 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 &&other) : QIterable(std::move(other)) {} + + QSequentialIterable &operator=(QIterable &&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::operator QVariant() const +{ + if (m_pointer == nullptr) + return QVariant(); + const QMetaType metaType(m_pointer->metaContainer().valueMetaType()); + QVariant v(metaType); + void *dataPtr = metaType == QMetaType::fromType() ? &v : v.data(); + m_pointer->metaContainer().valueAtIterator(m_pointer->constIterator(), dataPtr); + return v; +} + +template<> +inline QVariantRef &QVariantRef::operator=( + const QVariant &value) +{ + if (m_pointer == nullptr) + return *this; + const QMetaType metaType(m_pointer->metaContainer().valueMetaType()); + const void *dataPtr = metaType == QMetaType::fromType() + ? &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 @@ -2616,348 +2616,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \internal */ -/*! - \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()) - 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()) - 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 @@ -2978,6 +2636,13 @@ QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::opera Creates a QVariantRef from an \a pointer. */ +/*! + \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) @@ -2992,6 +2657,12 @@ QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::opera QVariantRef refers to. */ +/*! + \fn QVariantRef::operator QVariant() const + + Resolves the QVariantRef to an actual QVariant. +*/ + /*! \fn void swap(QVariantRef a, QVariantRef b) 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 inline T qvariant_cast(const QVariant &v) -- cgit v1.2.3