Extend QSequentialIterable and add QAssociativeIterable
And add mutable iterators. This requires some refactoring of the existing iterators. Task-number: QTBUG-81716 Change-Id: I61b3a3e8c0df5fd449679257a29d9f0c3d19c4f0 Reviewed-by: Lars Knoll <lars.knoll@qt.io>bb10
parent
b30801f64d
commit
5c808073af
|
|
@ -70,6 +70,7 @@ qt_add_module(Core
|
|||
itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_p.h
|
||||
kernel/qabstracteventdispatcher.cpp kernel/qabstracteventdispatcher.h kernel/qabstracteventdispatcher_p.h
|
||||
kernel/qabstractnativeeventfilter.cpp kernel/qabstractnativeeventfilter.h
|
||||
kernel/qassociativeiterable.cpp kernel/qassociativeiterable.h
|
||||
kernel/qbasictimer.cpp kernel/qbasictimer.h
|
||||
kernel/qcoreapplication.cpp kernel/qcoreapplication.h kernel/qcoreapplication_p.h
|
||||
kernel/qcorecmdlineargs_p.h
|
||||
|
|
@ -79,7 +80,7 @@ qt_add_module(Core
|
|||
kernel/qelapsedtimer.cpp kernel/qelapsedtimer.h
|
||||
kernel/qeventloop.cpp kernel/qeventloop.h
|
||||
kernel/qfunctions_p.h
|
||||
kernel/qiterable.cpp kernel/qiterable.h
|
||||
kernel/qiterable.cpp kernel/qiterable.h kernel/qiterable_p.cpp kernel/qiterable_p.h
|
||||
kernel/qmath.cpp kernel/qmath.h
|
||||
kernel/qmetacontainer.cpp kernel/qmetacontainer.h
|
||||
kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h
|
||||
|
|
@ -96,6 +97,7 @@ qt_add_module(Core
|
|||
kernel/qpointer.cpp kernel/qpointer.h
|
||||
kernel/qproperty.cpp kernel/qproperty.h kernel/qproperty_p.h
|
||||
kernel/qpropertyprivate.h
|
||||
kernel/qsequentialiterable.cpp kernel/qsequentialiterable.h
|
||||
kernel/qsharedmemory.cpp kernel/qsharedmemory.h kernel/qsharedmemory_p.h
|
||||
kernel/qsignalmapper.cpp kernel/qsignalmapper.h
|
||||
kernel/qsocketnotifier.cpp kernel/qsocketnotifier.h
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ qt_add_module(Core
|
|||
itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_p.h
|
||||
kernel/qabstracteventdispatcher.cpp kernel/qabstracteventdispatcher.h kernel/qabstracteventdispatcher_p.h
|
||||
kernel/qabstractnativeeventfilter.cpp kernel/qabstractnativeeventfilter.h
|
||||
kernel/qassociativeiterable.cpp kernel/qassociativeiterable.h
|
||||
kernel/qbasictimer.cpp kernel/qbasictimer.h
|
||||
kernel/qcoreapplication.cpp kernel/qcoreapplication.h kernel/qcoreapplication_p.h
|
||||
kernel/qcorecmdlineargs_p.h
|
||||
|
|
@ -102,7 +103,7 @@ qt_add_module(Core
|
|||
kernel/qelapsedtimer.cpp kernel/qelapsedtimer.h
|
||||
kernel/qeventloop.cpp kernel/qeventloop.h
|
||||
kernel/qfunctions_p.h
|
||||
kernel/qiterable.cpp kernel/qiterable.h
|
||||
kernel/qiterable.cpp kernel/qiterable.h kernel/qiterable_p.cpp kernel/qiterable_p.h
|
||||
kernel/qmath.cpp kernel/qmath.h
|
||||
kernel/qmetacontainer.cpp kernel/qmetacontainer.h
|
||||
kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h
|
||||
|
|
@ -118,6 +119,7 @@ qt_add_module(Core
|
|||
kernel/qpointer.cpp kernel/qpointer.h
|
||||
kernel/qproperty.cpp kernel/qproperty.h kernel/qproperty_p.h
|
||||
kernel/qpropertyprivate.h
|
||||
kernel/qsequentialiterable.cpp kernel/qsequentialiterable.h
|
||||
kernel/qsharedmemory.cpp kernel/qsharedmemory.h kernel/qsharedmemory_p.h
|
||||
kernel/qsignalmapper.cpp kernel/qsignalmapper.h
|
||||
kernel/qsocketnotifier.cpp kernel/qsocketnotifier.h
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,253 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qassociativeiterable.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
#include <QtCore/private/qiterable_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
Returns the key this iterator points to.
|
||||
*/
|
||||
QVariant QAssociativeIterator::key() const
|
||||
{
|
||||
return QIterablePrivate::retrieveElement(
|
||||
metaContainer().keyMetaType(), [this](void *dataPtr) {
|
||||
metaContainer().keyAtIterator(constIterator(), dataPtr);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the mapped value this iterator points to. If the container does not
|
||||
provide a mapped value (for example a set), returns an invalid QVariantRef.
|
||||
*/
|
||||
QVariantRef<QAssociativeIterator> QAssociativeIterator::value() const
|
||||
{
|
||||
const QMetaType mappedMetaType(metaContainer().mappedMetaType());
|
||||
return QVariantRef<QAssociativeIterator>(mappedMetaType.isValid() ? this : nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariantRef. The resulting
|
||||
QVariantRef resolves to the mapped value if there is one, or to the key
|
||||
value if not.
|
||||
*/
|
||||
QVariantRef<QAssociativeIterator> QAssociativeIterator::operator*() const
|
||||
{
|
||||
return QVariantRef<QAssociativeIterator>(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariantPointer. The resulting
|
||||
QVariantPointer resolves to the mapped value if there is one, or to the key
|
||||
value if not.
|
||||
*/
|
||||
QVariantPointer<QAssociativeIterator> QAssociativeIterator::operator->() const
|
||||
{
|
||||
return QVariantPointer<QAssociativeIterator>(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the key this iterator points to.
|
||||
*/
|
||||
QVariant QAssociativeConstIterator::key() const
|
||||
{
|
||||
return QIterablePrivate::retrieveElement(
|
||||
metaContainer().keyMetaType(), [this](void *dataPtr) {
|
||||
metaContainer().keyAtConstIterator(constIterator(), dataPtr);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the mapped value this iterator points to, or an invalid QVariant if
|
||||
there is no mapped value.
|
||||
*/
|
||||
QVariant QAssociativeConstIterator::value() const
|
||||
{
|
||||
return QIterablePrivate::retrieveElement(
|
||||
metaContainer().mappedMetaType(), [this](void *dataPtr) {
|
||||
metaContainer().mappedAtConstIterator(constIterator(), dataPtr);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariant. The returned value is the
|
||||
mapped value at the current iterator if there is one, or otherwise the key.
|
||||
*/
|
||||
QVariant QAssociativeConstIterator::operator*() const
|
||||
{
|
||||
const QMetaType mappedMetaType(metaContainer().mappedMetaType());
|
||||
return mappedMetaType.isValid() ? value() : key();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariantConstPointer. The
|
||||
QVariantConstPointer will resolve to the mapped value at the current
|
||||
iterator if there is one, or otherwise the key.
|
||||
*/
|
||||
QVariantConstPointer QAssociativeConstIterator::operator->() const
|
||||
{
|
||||
return QVariantConstPointer(operator*());
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QAssociativeIterable
|
||||
\since 5.2
|
||||
\inmodule QtCore
|
||||
\brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
|
||||
|
||||
This class allows several methods of accessing the elements of an associative container held within
|
||||
a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
|
||||
be converted to a QVariantHash or QVariantMap or if a custom mutable view has been registered.
|
||||
|
||||
\snippet code/src_corelib_kernel_qvariant.cpp 10
|
||||
|
||||
The container itself is not copied before iterating over it.
|
||||
|
||||
\sa QVariant
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::RandomAccessIterator
|
||||
Exposes an iterator using std::random_access_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::BidirectionalIterator
|
||||
Exposes an iterator using std::bidirectional_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::ForwardIterator
|
||||
Exposes an iterator using std::forward_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::InputIterator
|
||||
Exposes an iterator using std::input_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::RandomAccessConstIterator
|
||||
Exposes a const_iterator using std::random_access_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::BidirectionalConstIterator
|
||||
Exposes a const_iterator using std::bidirectional_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::ForwardConstIterator
|
||||
Exposes a const_iterator using std::forward_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QAssociativeIterable::InputConstIterator
|
||||
Exposes a const_iterator using std::input_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Retrieves a const_iterator pointing to the element at the given \a key, or
|
||||
the end of the container if that key does not exist.
|
||||
*/
|
||||
QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
|
||||
{
|
||||
const QMetaAssociation meta = metaContainer();
|
||||
QVariant converted = key;
|
||||
const void *keyData = QIterablePrivate::coerceType(converted, meta.keyMetaType());
|
||||
return const_iterator(QConstIterator(
|
||||
this, meta.createConstIteratorAtKey(constIterable(), keyData)));
|
||||
}
|
||||
|
||||
/*!
|
||||
Retrieves an iterator pointing to the element at the given \a key, or
|
||||
the end of the container if that key does not exist.
|
||||
*/
|
||||
QAssociativeIterable::iterator QAssociativeIterable::mutableFind(const QVariant &key)
|
||||
{
|
||||
const QMetaAssociation meta = metaContainer();
|
||||
QVariant converted = key;
|
||||
const void *keyData = QIterablePrivate::coerceType(converted, meta.keyMetaType());
|
||||
return iterator(QIterator(this, meta.createIteratorAtKey(mutableIterable(), keyData)));
|
||||
}
|
||||
|
||||
/*!
|
||||
Retrieves the mapped value at the given \a key, or an invalid QVariant
|
||||
if the key does not exist.
|
||||
*/
|
||||
QVariant QAssociativeIterable::value(const QVariant &key) const
|
||||
{
|
||||
const QMetaAssociation meta = metaContainer();
|
||||
QVariant converted = key;
|
||||
const void *keyData = QIterablePrivate::coerceType(converted, meta.keyMetaType());
|
||||
QVariant result(QMetaType(meta.mappedMetaType()));
|
||||
meta.mappedAtKey(constIterable(), keyData, result.data());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QAssociativeIterable::const_iterator
|
||||
\since 5.2
|
||||
\inmodule QtCore
|
||||
\brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
|
||||
|
||||
A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
|
||||
and can be used in a way similar to other stl-style iterators.
|
||||
|
||||
\snippet code/src_corelib_kernel_qvariant.cpp 10
|
||||
|
||||
\sa QAssociativeIterable
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QAssociativeIterable::iterator
|
||||
\since 6.0
|
||||
\inmodule QtCore
|
||||
\brief The QAssociativeIterable::iterator allows iteration over a container in a QVariant.
|
||||
|
||||
A QAssociativeIterable::iterator can only be created by a QAssociativeIterable instance,
|
||||
and can be used in a way similar to other stl-style iterators.
|
||||
|
||||
\sa QAssociativeIterable
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QASSOCIATIVEITERABLE_H
|
||||
#define QASSOCIATIVEITERABLE_H
|
||||
|
||||
#include <QtCore/qiterable.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QAssociativeIterator : public QIterator<QMetaAssociation>
|
||||
{
|
||||
public:
|
||||
using key_type = QVariant;
|
||||
using mapped_type = QVariant;
|
||||
using reference = QVariantRef<QAssociativeIterator>;
|
||||
using pointer = QVariantPointer<QAssociativeIterator>;
|
||||
|
||||
QAssociativeIterator(QIterator &&it)
|
||||
: QIterator(std::move(it))
|
||||
{}
|
||||
|
||||
QVariant key() const;
|
||||
QVariantRef<QAssociativeIterator> value() const;
|
||||
|
||||
QVariantRef<QAssociativeIterator> operator*() const;
|
||||
QVariantPointer<QAssociativeIterator> operator->() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QAssociativeConstIterator : public QConstIterator<QMetaAssociation>
|
||||
{
|
||||
public:
|
||||
using key_type = QVariant;
|
||||
using mapped_type = QVariant;
|
||||
using reference = const QVariant &;
|
||||
using pointer = QVariantConstPointer;
|
||||
|
||||
QAssociativeConstIterator(QConstIterator &&it)
|
||||
: QConstIterator(std::move(it))
|
||||
{}
|
||||
|
||||
QVariant key() const;
|
||||
QVariant value() const;
|
||||
|
||||
QVariant operator*() const;
|
||||
QVariantConstPointer operator->() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QAssociativeIterable : public QIterable<QMetaAssociation>
|
||||
{
|
||||
public:
|
||||
using iterator = QTaggedIterator<QAssociativeIterator, void>;
|
||||
using const_iterator = QTaggedIterator<QAssociativeConstIterator, void>;
|
||||
|
||||
using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
|
||||
using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
|
||||
using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
|
||||
using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
|
||||
|
||||
using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
|
||||
using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
|
||||
using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
|
||||
using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
|
||||
|
||||
template<class T>
|
||||
QAssociativeIterable(const T *p)
|
||||
: QIterable(QMetaAssociation::fromContainer<T>(), p)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
QAssociativeIterable(T *p)
|
||||
: QIterable(QMetaAssociation::fromContainer<T>(), p)
|
||||
{
|
||||
}
|
||||
|
||||
QAssociativeIterable() = default;
|
||||
|
||||
template<typename Pointer>
|
||||
QAssociativeIterable(const QMetaAssociation &metaAssociation, Pointer iterable)
|
||||
: QIterable(metaAssociation, iterable)
|
||||
{
|
||||
}
|
||||
|
||||
QAssociativeIterable(const QMetaAssociation &metaSequence, const QMetaType &metaType,
|
||||
void *iterable)
|
||||
: QIterable(metaSequence, metaType.alignOf(), iterable)
|
||||
{
|
||||
}
|
||||
|
||||
QAssociativeIterable(const QMetaAssociation &metaSequence, const QMetaType &metaType,
|
||||
const void *iterable)
|
||||
: QIterable(metaSequence, metaType.alignOf(), iterable)
|
||||
{
|
||||
}
|
||||
|
||||
QAssociativeIterable(QIterable<QMetaAssociation> &&other) : QIterable(std::move(other)) {}
|
||||
|
||||
QAssociativeIterable &operator=(QIterable<QMetaAssociation> &&other)
|
||||
{
|
||||
QIterable::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator begin() const { return constBegin(); }
|
||||
const_iterator end() const { return constEnd(); }
|
||||
|
||||
const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
|
||||
const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
|
||||
|
||||
iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
|
||||
iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
|
||||
|
||||
const_iterator find(const QVariant &key) const;
|
||||
const_iterator constFind(const QVariant &key) const { return find(key); }
|
||||
iterator mutableFind(const QVariant &key);
|
||||
|
||||
QVariant value(const QVariant &key) const;
|
||||
};
|
||||
|
||||
template<>
|
||||
inline QVariantRef<QAssociativeIterator>::operator QVariant() const
|
||||
{
|
||||
if (m_pointer == nullptr)
|
||||
return QVariant();
|
||||
const auto metaAssociation = m_pointer->metaContainer();
|
||||
QMetaType metaType(metaAssociation.mappedMetaType());
|
||||
if (!metaType.isValid())
|
||||
return m_pointer->key();
|
||||
|
||||
QVariant v(metaType);
|
||||
void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
|
||||
metaAssociation.mappedAtIterator(m_pointer->constIterator(), dataPtr);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline QVariantRef<QAssociativeIterator> &QVariantRef<QAssociativeIterator>::operator=(
|
||||
const QVariant &value)
|
||||
{
|
||||
if (m_pointer == nullptr)
|
||||
return *this;
|
||||
const QMetaType metaType(m_pointer->metaContainer().mappedMetaType());
|
||||
const void *dataPtr = metaType == QMetaType::fromType<QVariant>()
|
||||
? &value
|
||||
: value.constData();
|
||||
m_pointer->metaContainer().setMappedAtIterator(m_pointer->constIterator(), dataPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Q_DECLARE_TYPEINFO(QAssociativeIterable, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QAssociativeIterable::iterator, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QAssociativeIterable::const_iterator, Q_MOVABLE_TYPE);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QASSOCIATIVEITERABLE_H
|
||||
|
|
@ -38,271 +38,155 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qiterable.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QSequentialIterable
|
||||
\since 5.2
|
||||
\inmodule QtCore
|
||||
\brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
|
||||
\class QBaseIterator
|
||||
|
||||
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
|
||||
QBaseIterator forms the common base class for all iterators operating on
|
||||
subclasses of QIterable.
|
||||
*/
|
||||
|
||||
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 QSequentialIterable::const_iterator QSequentialIterable::begin() const
|
||||
|
||||
Returns a QSequentialIterable::const_iterator for the beginning of the container. This
|
||||
can be used in stl-style iteration.
|
||||
|
||||
\sa end()
|
||||
*/
|
||||
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 QBaseIterator::QBaseIterator(const QIterable *iterable, void *iterator)
|
||||
|
||||
\sa begin()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
QVariant QSequentialIterable::at(qsizetype idx) const
|
||||
{
|
||||
QVariant v(m_metaSequence.valueMetaType());
|
||||
void *dataPtr;
|
||||
if (m_metaSequence.valueMetaType() == QMetaType::fromType<QVariant>())
|
||||
dataPtr = &v;
|
||||
else
|
||||
dataPtr = v.data();
|
||||
|
||||
const QMetaSequence metaSequence = m_metaSequence;
|
||||
if (metaSequence.canGetValueAtIndex()) {
|
||||
metaSequence.valueAtIndex(m_iterable.constPointer(), idx, dataPtr);
|
||||
} else if (metaSequence.canGetValueAtConstIterator()) {
|
||||
void *iterator = metaSequence.constBegin(m_iterable.constPointer());
|
||||
metaSequence.advanceConstIterator(iterator, idx);
|
||||
metaSequence.valueAtConstIterator(iterator, dataPtr);
|
||||
metaSequence.destroyConstIterator(iterator);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of values in the container.
|
||||
*/
|
||||
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.
|
||||
\internal
|
||||
Creates a const QBaseIterator from an \a iterable and an \a iterator.
|
||||
*/
|
||||
void QSequentialIterable::addValue(const QVariant &value, Position position)
|
||||
{
|
||||
QVariant converted;
|
||||
const void *valuePtr;
|
||||
if (valueMetaType() == QMetaType::fromType<QVariant>()) {
|
||||
valuePtr = &value;
|
||||
} else if (valueMetaType() == value.metaType()) {
|
||||
valuePtr = value.constData();
|
||||
} else if (value.canConvert(valueMetaType())) {
|
||||
converted = value;
|
||||
converted.convert(valueMetaType());
|
||||
valuePtr = converted.constData();
|
||||
} else {
|
||||
converted = QVariant(valueMetaType());
|
||||
valuePtr = converted.constData();
|
||||
}
|
||||
|
||||
switch (position) {
|
||||
case AtBegin:
|
||||
if (metaSequence().canAddValueAtBegin())
|
||||
metaSequence().addValueAtBegin(mutableIterable(), valuePtr);
|
||||
break;
|
||||
case AtEnd:
|
||||
if (metaSequence().canAddValueAtEnd())
|
||||
metaSequence().addValueAtEnd(mutableIterable(), valuePtr);
|
||||
break;
|
||||
case Unspecified:
|
||||
if (metaSequence().canAddValue())
|
||||
metaSequence().addValue(mutableIterable(), valuePtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Removes a value from the container, at \a position, if possible.
|
||||
\fn QBaseIterator::QBaseIterator(QIterable *iterable, void *iterator)
|
||||
|
||||
\internal
|
||||
Creates a non-const QBaseIterator from an \a iterable and an \a iterator.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
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 QBaseIterator::QBaseIterator(QBaseIterator &&other)
|
||||
|
||||
\internal
|
||||
Move-constructs a QBaseIterator from \a other, preserving its const-ness.
|
||||
*/
|
||||
|
||||
/*!
|
||||
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();
|
||||
}
|
||||
\fn QBaseIterator::QBaseIterator(const QBaseIterator &other)
|
||||
|
||||
\internal
|
||||
Copy-constructs a QBaseIterator from \a other, preserving its const-ness.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QSequentialIterable::const_iterator
|
||||
\since 5.2
|
||||
\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::const_iterator allows iteration over a container in a QVariant.
|
||||
\brief The QIterator 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.
|
||||
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.
|
||||
|
||||
\snippet code/src_corelib_kernel_qvariant.cpp 9
|
||||
|
||||
\sa QSequentialIterable
|
||||
\sa QIterable
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QIterator::QIterator(QIterable *iterable, void *iterator)
|
||||
|
||||
Creates an iterator from an \a iterable and a pointer to a native \a iterator.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Destroys the QSequentialIterable::const_iterator.
|
||||
*/
|
||||
QSequentialIterable::const_iterator::~const_iterator() {
|
||||
if (!m_ref->deref()) {
|
||||
m_iterable->m_metaSequence.destroyConstIterator(m_iterator);
|
||||
delete m_ref;
|
||||
}
|
||||
}
|
||||
\fn bool QIterator::operator==(const QIterator &other) const
|
||||
|
||||
/*!
|
||||
Creates a copy of \a other.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
const QVariant QSequentialIterable::const_iterator::operator*() const
|
||||
{
|
||||
QVariant v(m_iterable->m_metaSequence.valueMetaType());
|
||||
void *dataPtr;
|
||||
if (m_iterable->m_metaSequence.valueMetaType() == QMetaType::fromType<QVariant>())
|
||||
dataPtr = &v;
|
||||
else
|
||||
dataPtr = v.data();
|
||||
m_iterable->m_metaSequence.valueAtConstIterator(m_iterator, dataPtr);
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
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 QIterator::operator!=(const QIterator &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 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.
|
||||
|
|
@ -311,30 +195,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 QIterator QIterator::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 QIterator &QIterator::operator--()
|
||||
|
||||
The prefix -- operator (\c{--it}) makes the preceding item
|
||||
current and returns an iterator to the new current item.
|
||||
|
||||
|
|
@ -345,13 +219,10 @@ 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 QIterator QIterator::operator--(int)
|
||||
|
||||
\overload
|
||||
|
||||
The postfix -- operator (\c{it--}) makes the preceding item
|
||||
|
|
@ -362,28 +233,18 @@ 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 QIterator &QIterator::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 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
|
||||
|
|
@ -391,29 +252,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 QIterator QIterator::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 QIterator QIterator::operator-(qsizetype j) const
|
||||
|
||||
Returns an iterator to the item at \a j positions backward from
|
||||
this iterator.
|
||||
|
||||
|
|
@ -422,14 +273,353 @@ 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 QIterator::operator-(const QIterator &j) const
|
||||
|
||||
Returns the distance between the two iterators.
|
||||
|
||||
\sa operator+(), operator-=(), canReverseIterator()
|
||||
*/
|
||||
|
||||
/*!
|
||||
QConstIterator::QConstIterator(const QIterable *iterable, void *iterator)
|
||||
|
||||
Creates a QConstIterator to wrap \a iterator, operating on \a iterable.
|
||||
*/
|
||||
|
||||
/*!
|
||||
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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QIterable::canRandomAccessIterate() const
|
||||
|
||||
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
|
||||
|
||||
Returns a QConstIterator for the beginning of the container. This
|
||||
can be used in stl-style iteration.
|
||||
|
||||
\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()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QIterator QIterable::mutableBegin()
|
||||
|
||||
Returns a QIterator for the beginning of the container. This
|
||||
can be used in stl-style iteration.
|
||||
|
||||
\sa end()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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!=()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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==()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
|
||||
Calling this function on QSequentialIterable::end() leads to undefined results.
|
||||
|
||||
\sa operator--()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn QTaggedIterator &QTaggedIterator::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()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QTaggedIterator QTaggedIterator::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 QTaggedIterator &QTaggedIterator::operator+=(qsizetype j)
|
||||
|
||||
Advances the iterator by \a j items.
|
||||
|
||||
\sa operator-=(), operator+()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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
|
||||
leads to undefined results.
|
||||
|
||||
\sa operator+=(), operator-(), canReverseIterate()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QTaggedIterator QTaggedIterator::operator+(qsizetype j) const
|
||||
|
||||
Returns an iterator to the item at \a j positions forward from
|
||||
this iterator.
|
||||
|
||||
\sa operator-(), operator+=()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QTaggedIterator QTaggedIterator::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 QTaggedIterator::operator-(const QTaggedIterator &j) const
|
||||
|
||||
Returns the distance between the two iterators.
|
||||
|
||||
\sa operator+(), operator-=(), canReverseIterator()
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qtypeinfo.h>
|
||||
#include <QtCore/qmetacontainer.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#include <QtCore/qtaggedpointer.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -100,115 +99,454 @@ namespace QtPrivate {
|
|||
};
|
||||
}
|
||||
|
||||
class Q_CORE_EXPORT QSequentialIterable
|
||||
template<class Iterator, typename IteratorCategory>
|
||||
class QTaggedIterator : public Iterator
|
||||
{
|
||||
uint m_revision = 0;
|
||||
QtPrivate::QConstPreservingPointer<void, quint16> m_iterable;
|
||||
QMetaSequence m_metaSequence;
|
||||
public:
|
||||
using iterator_category = IteratorCategory;
|
||||
QTaggedIterator(Iterator &&it) : Iterator(std::move(it))
|
||||
{
|
||||
const QMetaContainer metaContainer = this->metaContainer();
|
||||
if (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory>
|
||||
&& !metaContainer.hasRandomAccessIterator()) {
|
||||
qFatal("You cannot use this iterator as a random access iterator");
|
||||
this->clearIterator();
|
||||
}
|
||||
|
||||
if (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory>
|
||||
&& !metaContainer.hasBidirectionalIterator()) {
|
||||
qFatal("You cannot use this iterator as a bidirectional iterator");
|
||||
this->clearIterator();
|
||||
}
|
||||
|
||||
if (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory>
|
||||
&& !metaContainer.hasForwardIterator()) {
|
||||
qFatal("You cannot use this iterator as a forward iterator");
|
||||
this->clearIterator();
|
||||
}
|
||||
|
||||
if (std::is_base_of_v<std::input_iterator_tag, IteratorCategory>
|
||||
&& !metaContainer.hasInputIterator()) {
|
||||
qFatal("You cannot use this iterator as an input iterator");
|
||||
this->clearIterator();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const QTaggedIterator &o) const { return Iterator::operator==(o); }
|
||||
bool operator!=(const QTaggedIterator &o) const { return Iterator::operator!=(o); }
|
||||
QTaggedIterator &operator++() { Iterator::operator++(); return *this; }
|
||||
QTaggedIterator operator++(int x) { return QTaggedIterator(Iterator::operator++(x)); };
|
||||
QTaggedIterator &operator--() { Iterator::operator--(); return *this; }
|
||||
QTaggedIterator operator--(int x) { return QTaggedIterator(Iterator::operator--(x)); };
|
||||
QTaggedIterator &operator+=(qsizetype j) { Iterator::operator+=(j); return *this; }
|
||||
QTaggedIterator &operator-=(qsizetype j) { Iterator::operator-=(j); return *this; }
|
||||
QTaggedIterator operator+(qsizetype j) const { return QTaggedIterator(Iterator::operator+(j)); }
|
||||
QTaggedIterator operator-(qsizetype j) const { return QTaggedIterator(Iterator::operator-(j)); }
|
||||
qsizetype operator-(const QTaggedIterator &j) const { return Iterator::operator-(j); }
|
||||
|
||||
bool operator<(const QTaggedIterator &j) { return operator-(j) < 0; }
|
||||
bool operator>=(const QTaggedIterator &j) { return !operator<(j); }
|
||||
bool operator>(const QTaggedIterator &j) { return operator-(j) > 0; }
|
||||
bool operator<=(const QTaggedIterator &j) { return !operator>(j); }
|
||||
|
||||
friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; }
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
class QIterable;
|
||||
|
||||
template<class Container>
|
||||
class QBaseIterator
|
||||
{
|
||||
private:
|
||||
QtPrivate::QConstPreservingPointer<QIterable<Container>> m_iterable;
|
||||
void *m_iterator = nullptr;
|
||||
|
||||
protected:
|
||||
QBaseIterator() = default;
|
||||
QBaseIterator(const QIterable<Container> *iterable, void *iterator)
|
||||
: m_iterable(iterable), m_iterator(iterator)
|
||||
{}
|
||||
|
||||
QBaseIterator(QIterable<Container> *iterable, void *iterator)
|
||||
: m_iterable(iterable), m_iterator(iterator)
|
||||
{}
|
||||
|
||||
QBaseIterator(QBaseIterator &&other)
|
||||
: m_iterable(std::move(other.m_iterable)), m_iterator(std::move(other.m_iterator))
|
||||
{
|
||||
other.m_iterator = nullptr;
|
||||
}
|
||||
|
||||
QBaseIterator(const QBaseIterator &other)
|
||||
: m_iterable(other.m_iterable)
|
||||
{
|
||||
initIterator(other.m_iterator);
|
||||
}
|
||||
|
||||
~QBaseIterator() { clearIterator(); }
|
||||
|
||||
QBaseIterator &operator=(QBaseIterator &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
clearIterator();
|
||||
m_iterable = std::move(other.m_iterable);
|
||||
m_iterator = std::move(other.m_iterator);
|
||||
other.m_iterator = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
QBaseIterator &operator=(const QBaseIterator &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
clearIterator();
|
||||
m_iterable = other.m_iterable;
|
||||
initIterator(other.m_iterator);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
QIterable<Container> *mutableIterable() const
|
||||
{
|
||||
return m_iterable.mutablePointer();
|
||||
}
|
||||
|
||||
const QIterable<Container> *constIterable() const
|
||||
{
|
||||
return m_iterable.constPointer();
|
||||
}
|
||||
|
||||
void initIterator(const void *copy)
|
||||
{
|
||||
if (!copy)
|
||||
return;
|
||||
if (auto *mutableIt = mutableIterable()) {
|
||||
m_iterator = metaContainer().begin(mutableIt->mutableIterable());
|
||||
metaContainer().copyIterator(m_iterator, copy);
|
||||
} else if (auto *constIt = constIterable()) {
|
||||
m_iterator = metaContainer().constBegin(constIt->constIterable());
|
||||
metaContainer().copyConstIterator(m_iterator, copy);
|
||||
}
|
||||
}
|
||||
|
||||
void clearIterator()
|
||||
{
|
||||
if (!m_iterator)
|
||||
return;
|
||||
if (mutableIterable())
|
||||
metaContainer().destroyIterator(m_iterator);
|
||||
else
|
||||
metaContainer().destroyConstIterator(m_iterator);
|
||||
}
|
||||
|
||||
public:
|
||||
struct Q_CORE_EXPORT const_iterator
|
||||
void *mutableIterator() { return m_iterator; }
|
||||
const void *constIterator() const { return m_iterator; }
|
||||
Container metaContainer() const { return constIterable()->m_metaContainer; }
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
struct QIterator : public QBaseIterator<Container>
|
||||
{
|
||||
public:
|
||||
using difference_type = qsizetype;
|
||||
|
||||
explicit QIterator(QIterable<Container> *iterable, void *iterator)
|
||||
: QBaseIterator<Container>(iterable, iterator)
|
||||
{
|
||||
private:
|
||||
const QSequentialIterable *m_iterable = nullptr;
|
||||
void *m_iterator = nullptr;
|
||||
QAtomicInt *m_ref = nullptr;
|
||||
Q_ASSERT(iterable != nullptr);
|
||||
}
|
||||
|
||||
friend class QSequentialIterable;
|
||||
explicit const_iterator(const QSequentialIterable *iterable, void *iterator);
|
||||
bool operator==(const QIterator &o) const
|
||||
{
|
||||
return this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
|
||||
}
|
||||
|
||||
public:
|
||||
~const_iterator();
|
||||
bool operator!=(const QIterator &o) const
|
||||
{
|
||||
return !this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
|
||||
}
|
||||
|
||||
const_iterator(const const_iterator &other);
|
||||
QIterator &operator++()
|
||||
{
|
||||
this->metaContainer().advanceIterator(this->mutableIterator(), 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator& operator=(const const_iterator &other);
|
||||
QIterator operator++(int)
|
||||
{
|
||||
QIterable<Container> *iterable = this->mutableIterable();
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
|
||||
metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceIterator(this->mutableIterator(), 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
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; }
|
||||
};
|
||||
QIterator &operator--()
|
||||
{
|
||||
this->metaContainer().advanceIterator(this->mutableIterator(), -1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend struct const_iterator;
|
||||
QIterator operator--(int)
|
||||
{
|
||||
QIterable<Container> *iterable = this->mutableIterable();
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
|
||||
metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceIterator(this->mutableIterator(), -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
QIterator &operator+=(qsizetype j)
|
||||
{
|
||||
this->metaContainer().advanceIterator(this->mutableIterator(), j);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QIterator &operator-=(qsizetype j)
|
||||
{
|
||||
this->metaContainer().advanceIterator(this->mutableIterator(), -j);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QIterator operator+(qsizetype j) const
|
||||
{
|
||||
QIterable<Container> *iterable = this->mutableIterable();
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
|
||||
metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceIterator(result.mutableIterator(), j);
|
||||
return result;
|
||||
}
|
||||
|
||||
QIterator operator-(qsizetype j) const
|
||||
{
|
||||
QIterable<Container> *iterable = this->mutableIterable();
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
|
||||
metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceIterator(result.mutableIterator(), -j);
|
||||
return result;
|
||||
}
|
||||
|
||||
qsizetype operator-(const QIterator &j) const
|
||||
{
|
||||
return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
|
||||
}
|
||||
|
||||
friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; }
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
struct QConstIterator : public QBaseIterator<Container>
|
||||
{
|
||||
public:
|
||||
using difference_type = qsizetype;
|
||||
|
||||
explicit QConstIterator(const QIterable<Container> *iterable, void *iterator)
|
||||
: QBaseIterator<Container>(iterable, iterator)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const QConstIterator &o) const
|
||||
{
|
||||
return this->metaContainer().compareConstIterator(
|
||||
this->constIterator(), o.constIterator());
|
||||
}
|
||||
|
||||
bool operator!=(const QConstIterator &o) const
|
||||
{
|
||||
return !this->metaContainer().compareConstIterator(
|
||||
this->constIterator(), o.constIterator());
|
||||
}
|
||||
|
||||
QConstIterator &operator++()
|
||||
{
|
||||
this->metaContainer().advanceConstIterator(this->mutableIterator(), 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QConstIterator operator++(int)
|
||||
{
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QConstIterator result(this->constIterable(), metaContainer.constBegin(
|
||||
this->constIterable()->constIterable()));
|
||||
metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceConstIterator(this->mutableIterator(), 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
QConstIterator &operator--()
|
||||
{
|
||||
this->metaContainer().advanceConstIterator(this->mutableIterator(), -1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QConstIterator operator--(int)
|
||||
{
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QConstIterator result(this->constIterable(), metaContainer.constBegin(
|
||||
this->constIterable()->constIterable()));
|
||||
metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceConstIterator(this->mutableIterator(), -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
QConstIterator &operator+=(qsizetype j)
|
||||
{
|
||||
this->metaContainer().advanceConstIterator(this->mutableIterator(), j);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QConstIterator &operator-=(qsizetype j)
|
||||
{
|
||||
this->metaContainer().advanceConstIterator(this->mutableIterator(), -j);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QConstIterator operator+(qsizetype j) const
|
||||
{
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QConstIterator result(
|
||||
this->constIterable(),
|
||||
metaContainer.constBegin(this->constIterable()->constIterable()));
|
||||
metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceConstIterator(result.mutableIterator(), j);
|
||||
return result;
|
||||
}
|
||||
|
||||
QConstIterator operator-(qsizetype j) const
|
||||
{
|
||||
const Container metaContainer = this->metaContainer();
|
||||
QConstIterator result(this->constIterable(), metaContainer.constBegin(
|
||||
this->constIterable()->constIterable()));
|
||||
metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
|
||||
metaContainer.advanceConstIterator(result.mutableIterator(), -j);
|
||||
return result;
|
||||
}
|
||||
|
||||
qsizetype operator-(const QConstIterator &j) const
|
||||
{
|
||||
return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
|
||||
}
|
||||
|
||||
friend inline QConstIterator operator+(qsizetype j, const QConstIterator &k)
|
||||
{
|
||||
return k + j;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
class QIterable
|
||||
{
|
||||
friend class QBaseIterator<Container>;
|
||||
|
||||
protected:
|
||||
uint m_revision = 0;
|
||||
QtPrivate::QConstPreservingPointer<void, quint16> m_iterable;
|
||||
Container m_metaContainer;
|
||||
|
||||
public:
|
||||
QIterable() = default;
|
||||
|
||||
template<class T>
|
||||
QSequentialIterable(const T *p)
|
||||
: m_iterable(p)
|
||||
, m_metaSequence(QMetaSequence::fromContainer<T>())
|
||||
QIterable(const Container &metaContainer, const T *p)
|
||||
: m_iterable(p), m_metaContainer(metaContainer)
|
||||
{
|
||||
Q_UNUSED(m_revision);
|
||||
}
|
||||
|
||||
QSequentialIterable() = default;
|
||||
template<class T>
|
||||
QIterable(const Container &metaContainer, T *p)
|
||||
: m_iterable(p), m_metaContainer(metaContainer)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Pointer>
|
||||
QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
|
||||
: m_iterable(iterable)
|
||||
, m_metaSequence(metaSequence)
|
||||
QIterable(const Container &metaContainer, Pointer iterable)
|
||||
: m_iterable(iterable), m_metaContainer(metaContainer)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
QIterable(const Container &metaContainer, qsizetype alignment, const void *p)
|
||||
: m_iterable(p, alignment), m_metaContainer(metaContainer)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant at(qsizetype idx) const;
|
||||
qsizetype size() const;
|
||||
QIterable(const Container &metaContainer, qsizetype alignment, void *p)
|
||||
: m_iterable(p, alignment), m_metaContainer(metaContainer)
|
||||
{
|
||||
}
|
||||
|
||||
enum Position { Unspecified, AtBegin, AtEnd };
|
||||
void addValue(const QVariant &value, Position position = Unspecified);
|
||||
void removeValue(Position position = Unspecified);
|
||||
bool canInputIterate() const
|
||||
{
|
||||
return m_metaContainer.hasInputIterator();
|
||||
}
|
||||
|
||||
bool canForwardIterate() const;
|
||||
bool canReverseIterate() const;
|
||||
bool canForwardIterate() const
|
||||
{
|
||||
return m_metaContainer.hasForwardIterator();
|
||||
}
|
||||
|
||||
bool canReverseIterate() const
|
||||
{
|
||||
return m_metaContainer.hasBidirectionalIterator();
|
||||
}
|
||||
|
||||
bool canRandomAccessIterate() const
|
||||
{
|
||||
return m_metaContainer.hasRandomAccessIterator();
|
||||
}
|
||||
|
||||
const void *constIterable() const { return m_iterable.constPointer(); }
|
||||
|
||||
// TODO: fix this when introducing mutable iterables
|
||||
void *mutableIterable() { return const_cast<void *>(m_iterable.constPointer()); }
|
||||
|
||||
QMetaSequence metaSequence() const { return m_metaSequence; }
|
||||
QMetaType valueMetaType() const { return m_metaSequence.valueMetaType(); }
|
||||
};
|
||||
|
||||
namespace QtPrivate {
|
||||
|
||||
template<typename From>
|
||||
struct QSequentialIterableConvertFunctor
|
||||
{
|
||||
QSequentialIterable operator()(const From &f) const
|
||||
QConstIterator<Container> constBegin() const
|
||||
{
|
||||
return QSequentialIterable(&f);
|
||||
return QConstIterator(this, m_metaContainer.constBegin(constIterable()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SequentialValueTypeIsMetaType<T, true>
|
||||
{
|
||||
static bool registerConverter(int id)
|
||||
QConstIterator<Container> constEnd() const
|
||||
{
|
||||
const int toId = qMetaTypeId<QSequentialIterable>();
|
||||
if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
|
||||
QSequentialIterableConvertFunctor<T> o;
|
||||
return QMetaType::registerConverter<T, QSequentialIterable>(o);
|
||||
}
|
||||
return true;
|
||||
return QConstIterator(this, m_metaContainer.constEnd(constIterable()));
|
||||
}
|
||||
|
||||
QIterator<Container> mutableBegin()
|
||||
{
|
||||
return QIterator(this, m_metaContainer.begin(mutableIterable()));
|
||||
}
|
||||
|
||||
QIterator<Container> mutableEnd()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Container metaContainer() const
|
||||
{
|
||||
return m_metaContainer;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_TYPEINFO(QSequentialIterable, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_MOVABLE_TYPE);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QITERABLE_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/private/qiterable_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QIterablePrivate {
|
||||
|
||||
const void *coerceType(QVariant &value, const QMetaType &type)
|
||||
{
|
||||
if (type == QMetaType::fromType<QVariant>()) {
|
||||
return &value;
|
||||
} else if (type == value.metaType()) {
|
||||
return value.constData();
|
||||
} else if (value.canConvert(type)) {
|
||||
value.convert(type);
|
||||
return value.constData();
|
||||
}
|
||||
|
||||
value = QVariant(type);
|
||||
return value.constData();
|
||||
}
|
||||
|
||||
} // namespace QIterablePrivate
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QITERABLE_P_H
|
||||
#define QITERABLE_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QIterablePrivate {
|
||||
|
||||
const void *coerceType(QVariant &value, const QMetaType &type);
|
||||
|
||||
template<typename Callback>
|
||||
static QVariant retrieveElement(const QMetaType &type, Callback callback)
|
||||
{
|
||||
QVariant v(type);
|
||||
void *dataPtr;
|
||||
if (type == QMetaType::fromType<QVariant>())
|
||||
dataPtr = &v;
|
||||
else
|
||||
dataPtr = v.data();
|
||||
callback(dataPtr);
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace QIterablePrivate
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QITERABLE_P_H
|
||||
|
|
@ -54,7 +54,6 @@
|
|||
#include "quuid.h"
|
||||
#include "qvariant.h"
|
||||
#include "qdatastream.h"
|
||||
#include "qiterable.h"
|
||||
|
||||
#if QT_CONFIG(regularexpression)
|
||||
# include "qregularexpression.h"
|
||||
|
|
@ -73,6 +72,8 @@
|
|||
# include "qcbormap.h"
|
||||
# include "qbytearraylist.h"
|
||||
# include "qmetaobject.h"
|
||||
# include "qsequentialiterable.h"
|
||||
# include "qassociativeiterable.h"
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(itemmodel)
|
||||
|
|
@ -1829,11 +1830,12 @@ static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
|
||||
{
|
||||
const QMetaType::ConverterFunction * const f =
|
||||
customTypesConversionRegistry()->function(qMakePair(fromType.id(),
|
||||
qMetaTypeId<QSequentialIterable>()));
|
||||
customTypesConversionRegistry()->function(
|
||||
qMakePair(fromType.id(), qMetaTypeId<QIterable<QMetaSequence>>()));
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
|
|
@ -1851,14 +1853,13 @@ static bool convertIterableToVariantList(QMetaType fromType, const void *from, v
|
|||
static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
|
||||
{
|
||||
const QMetaType::ConverterFunction * const f =
|
||||
customTypesConversionRegistry()->function(qMakePair(fromType.id(),
|
||||
qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()));
|
||||
customTypesConversionRegistry()->function(
|
||||
qMakePair(fromType.id(), qMetaTypeId<QIterable<QMetaAssociation>>()));
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl iter;
|
||||
(*f)(from, &iter);
|
||||
QAssociativeIterable map(iter);
|
||||
QAssociativeIterable map;
|
||||
(*f)(from, &map);
|
||||
QVariantMap &h = *static_cast<QVariantMap *>(to);
|
||||
h.clear();
|
||||
auto end = map.end();
|
||||
|
|
@ -1870,14 +1871,13 @@ static bool convertIterableToVariantMap(QMetaType fromType, const void *from, vo
|
|||
static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
|
||||
{
|
||||
const QMetaType::ConverterFunction * const f =
|
||||
customTypesConversionRegistry()->function(qMakePair(fromType.id(),
|
||||
qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()));
|
||||
customTypesConversionRegistry()->function(
|
||||
qMakePair(fromType.id(), qMetaTypeId<QIterable<QMetaAssociation>>()));
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl iter;
|
||||
(*f)(from, &iter);
|
||||
QAssociativeIterable map(iter);
|
||||
QAssociativeIterable map;
|
||||
(*f)(from, &map);
|
||||
QVariantHash &h = *static_cast<QVariantHash *>(to);
|
||||
h.clear();
|
||||
h.reserve(map.size());
|
||||
|
|
@ -1886,6 +1886,7 @@ static bool convertIterableToVariantHash(QMetaType fromType, const void *from, v
|
|||
h.insert(it.key().toString(), it.value());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
|
||||
{
|
||||
|
|
@ -1917,6 +1918,7 @@ static bool convertIterableToVariantPair(QMetaType fromType, const void *from, v
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
|
||||
{
|
||||
using namespace QtMetaTypePrivate;
|
||||
|
|
@ -1935,6 +1937,14 @@ static bool convertToSequentialIterable(QMetaType fromType, const void *from, vo
|
|||
i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
|
||||
return true;
|
||||
}
|
||||
|
||||
QSequentialIterable impl;
|
||||
if (QMetaType::convert(
|
||||
fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &impl)) {
|
||||
i = std::move(impl);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1944,23 +1954,24 @@ static bool convertToAssociativeIterable(QMetaType fromType, const void *from, v
|
|||
|
||||
QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
|
||||
if (fromType.id() == QMetaType::QVariantMap) {
|
||||
i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast<const QVariantMap *>(from)));
|
||||
i = QAssociativeIterable(reinterpret_cast<const QVariantMap *>(from));
|
||||
return true;
|
||||
}
|
||||
if (fromType.id() == QMetaType::QVariantHash) {
|
||||
i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast<const QVariantHash *>(from)));
|
||||
i = QAssociativeIterable(reinterpret_cast<const QVariantHash *>(from));
|
||||
return true;
|
||||
}
|
||||
QAssociativeIterableImpl impl;
|
||||
if (QMetaType::convert(fromType, from, QMetaType::fromType<QtMetaTypePrivate::QAssociativeIterableImpl>(), &impl)) {
|
||||
i = QAssociativeIterable(impl);
|
||||
|
||||
QAssociativeIterable impl;
|
||||
if (QMetaType::convert(
|
||||
fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &impl)) {
|
||||
i = std::move(impl);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
|
||||
{
|
||||
const QMetaObject *f = fromType.metaObject();
|
||||
|
|
@ -2022,6 +2033,10 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
|
|||
}
|
||||
}
|
||||
|
||||
if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
|
||||
return true;
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
// handle iterables
|
||||
if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
|
||||
return true;
|
||||
|
|
@ -2032,16 +2047,12 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
|
|||
if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
|
||||
return true;
|
||||
|
||||
if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
|
||||
return true;
|
||||
|
||||
if (toTypeId == qMetaTypeId<QSequentialIterable>())
|
||||
return convertToSequentialIterable(fromType, from, to);
|
||||
|
||||
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
|
||||
return convertToAssociativeIterable(fromType, from, to);
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
// handle QObject conversion
|
||||
if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
|
||||
QObject *fromObject = *static_cast<QObject * const *>(from);
|
||||
|
|
@ -2153,13 +2164,15 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
|
|||
if (f)
|
||||
return true;
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
if (toTypeId == QVariantList && hasRegisteredConverterFunction(
|
||||
fromTypeId, qMetaTypeId<QSequentialIterable>()))
|
||||
fromTypeId, qMetaTypeId<QIterable<QMetaSequence>>()))
|
||||
return true;
|
||||
|
||||
if ((toTypeId == QVariantHash || toTypeId == QVariantMap) && hasRegisteredConverterFunction(
|
||||
fromTypeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))
|
||||
fromTypeId, qMetaTypeId<QIterable<QMetaAssociation>>()))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
|
||||
fromTypeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include <QtCore/qvarlengtharray.h>
|
||||
#include <QtCore/qrefcount.h>
|
||||
#include <QtCore/qdatastream.h>
|
||||
#include <QtCore/qiterable.h>
|
||||
#ifndef QT_NO_QOBJECT
|
||||
#include <QtCore/qobjectdefs.h>
|
||||
#endif
|
||||
|
|
@ -600,268 +601,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
|
|||
Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
|
||||
namespace QtMetaTypePrivate {
|
||||
|
||||
namespace QtMetaTypePrivate {
|
||||
|
||||
template<typename const_iterator>
|
||||
struct IteratorOwnerCommon
|
||||
{
|
||||
static void assign(void **ptr, const_iterator iterator)
|
||||
{
|
||||
*ptr = new const_iterator(iterator);
|
||||
}
|
||||
static void assign(void **ptr, void * const * src)
|
||||
{
|
||||
*ptr = new const_iterator(*static_cast<const_iterator*>(*src));
|
||||
}
|
||||
|
||||
static void advance(void **iterator, int step)
|
||||
{
|
||||
const_iterator &it = *static_cast<const_iterator*>(*iterator);
|
||||
std::advance(it, step);
|
||||
}
|
||||
|
||||
static void destroy(void **ptr)
|
||||
{
|
||||
delete static_cast<const_iterator*>(*ptr);
|
||||
}
|
||||
|
||||
static bool equal(void * const *it, void * const *other)
|
||||
{
|
||||
return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename const_iterator>
|
||||
struct IteratorOwner : IteratorOwnerCommon<const_iterator>
|
||||
{
|
||||
static void getData(void * const *iterator, void *dataPtr)
|
||||
{
|
||||
const_iterator *it = static_cast<const_iterator*>(*iterator);
|
||||
typename const_iterator::value_type *data = static_cast<typename const_iterator::value_type *>(dataPtr);
|
||||
*data = **it;
|
||||
}
|
||||
|
||||
static void getData(const_iterator it, void *dataPtr)
|
||||
{
|
||||
typename const_iterator::value_type *data = static_cast<typename const_iterator::value_type *>(dataPtr);
|
||||
*data = *it;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename value_type>
|
||||
struct IteratorOwner<const value_type*>
|
||||
{
|
||||
private:
|
||||
// We need to disable typed overloads of assign() and getData() if the value_type
|
||||
// is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
|
||||
// type as part of the overload signature.
|
||||
struct Dummy {};
|
||||
typedef typename std::conditional<std::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
|
||||
public:
|
||||
static void assign(void **ptr, const value_type_OR_Dummy *iterator )
|
||||
{
|
||||
*ptr = const_cast<value_type*>(iterator);
|
||||
}
|
||||
static void assign(void **ptr, void * const * src)
|
||||
{
|
||||
*ptr = static_cast<value_type*>(*src);
|
||||
}
|
||||
|
||||
static void advance(void **iterator, int step)
|
||||
{
|
||||
value_type *it = static_cast<value_type*>(*iterator);
|
||||
std::advance(it, step);
|
||||
*iterator = it;
|
||||
}
|
||||
|
||||
static void destroy(void **)
|
||||
{
|
||||
}
|
||||
|
||||
static void getData(void * const *iterator, void *dataPtr)
|
||||
{
|
||||
*static_cast<value_type *>(dataPtr) = *static_cast<value_type * const>(*iterator);
|
||||
}
|
||||
|
||||
static void getData(const value_type_OR_Dummy *it, void *dataPtr)
|
||||
{
|
||||
*static_cast<value_type *>(dataPtr) = *static_cast<value_type const *>(it);
|
||||
}
|
||||
|
||||
static bool equal(void * const *it, void * const *other)
|
||||
{
|
||||
return static_cast<value_type const *>(*it) == static_cast<value_type const *>(*other);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace QtMetaTypePrivate {
|
||||
template<typename T, bool = std::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
|
||||
struct AssociativeContainerAccessor
|
||||
{
|
||||
static const typename T::key_type& getKey(const typename T::const_iterator &it)
|
||||
{
|
||||
return it.key();
|
||||
}
|
||||
|
||||
static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
|
||||
{
|
||||
return it.value();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool = std::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
|
||||
struct StlStyleAssociativeContainerAccessor;
|
||||
|
||||
template<typename T>
|
||||
struct StlStyleAssociativeContainerAccessor<T, true>
|
||||
{
|
||||
static const typename T::key_type& getKey(const typename T::const_iterator &it)
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
|
||||
static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
|
||||
{
|
||||
};
|
||||
|
||||
class QAssociativeIterableImpl
|
||||
{
|
||||
public:
|
||||
const void *_iterable;
|
||||
void *_iterator;
|
||||
QMetaType _metaType_key;
|
||||
QMetaType _metaType_value;
|
||||
typedef int(*sizeFunc)(const void *p);
|
||||
typedef void (*findFunc)(const void *container, const void *p, void **iterator);
|
||||
typedef void (*beginFunc)(const void *p, void **);
|
||||
typedef void (*advanceFunc)(void **p, int);
|
||||
typedef void (*getFunc)(void * const *p, void *dataPtr);
|
||||
typedef void (*destroyIterFunc)(void **p);
|
||||
typedef bool (*equalIterFunc)(void * const *p, void * const *other);
|
||||
typedef void (*copyIterFunc)(void **, void * const *);
|
||||
|
||||
sizeFunc _size;
|
||||
findFunc _find;
|
||||
beginFunc _begin;
|
||||
beginFunc _end;
|
||||
advanceFunc _advance;
|
||||
getFunc _getKey;
|
||||
getFunc _getValue;
|
||||
destroyIterFunc _destroyIter;
|
||||
equalIterFunc _equalIter;
|
||||
copyIterFunc _copyIter;
|
||||
|
||||
template<class T>
|
||||
static int sizeImpl(const void *p)
|
||||
{ return int(std::distance(static_cast<const T*>(p)->begin(),
|
||||
static_cast<const T*>(p)->end())); }
|
||||
|
||||
template<class T>
|
||||
static void findImpl(const void *container, const void *p, void **iterator)
|
||||
{ IteratorOwner<typename T::const_iterator>::assign(iterator,
|
||||
static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
|
||||
|
||||
template<class T>
|
||||
static void advanceImpl(void **p, int step)
|
||||
{ std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
|
||||
|
||||
template<class T>
|
||||
static void beginImpl(const void *container, void **iterator)
|
||||
{ IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
|
||||
|
||||
template<class T>
|
||||
static void endImpl(const void *container, void **iterator)
|
||||
{ IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
|
||||
|
||||
template<class T>
|
||||
static void getKeyImpl(void * const *iterator, void *dataPtr)
|
||||
{
|
||||
auto *data = static_cast<typename T::key_type *>(dataPtr);
|
||||
*data = AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void getValueImpl(void * const *iterator, void *dataPtr)
|
||||
{
|
||||
auto *data = static_cast<typename T::mapped_type *>(dataPtr);
|
||||
*data = AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator));
|
||||
}
|
||||
|
||||
public:
|
||||
template<class T> QAssociativeIterableImpl(const T*p)
|
||||
: _iterable(p)
|
||||
, _iterator(nullptr)
|
||||
, _metaType_key(QMetaType::fromType<typename T::key_type>())
|
||||
, _metaType_value(QMetaType::fromType<typename T::mapped_type>())
|
||||
, _size(sizeImpl<T>)
|
||||
, _find(findImpl<T>)
|
||||
, _begin(beginImpl<T>)
|
||||
, _end(endImpl<T>)
|
||||
, _advance(advanceImpl<T>)
|
||||
, _getKey(getKeyImpl<T>)
|
||||
, _getValue(getValueImpl<T>)
|
||||
, _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
|
||||
, _equalIter(IteratorOwner<typename T::const_iterator>::equal)
|
||||
, _copyIter(IteratorOwner<typename T::const_iterator>::assign)
|
||||
{
|
||||
}
|
||||
|
||||
QAssociativeIterableImpl()
|
||||
: _iterable(nullptr)
|
||||
, _iterator(nullptr)
|
||||
, _size(nullptr)
|
||||
, _find(nullptr)
|
||||
, _begin(nullptr)
|
||||
, _end(nullptr)
|
||||
, _advance(nullptr)
|
||||
, _getKey(nullptr)
|
||||
, _getValue(nullptr)
|
||||
, _destroyIter(nullptr)
|
||||
, _equalIter(nullptr)
|
||||
, _copyIter(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void begin() { _begin(_iterable, &_iterator); }
|
||||
inline void end() { _end(_iterable, &_iterator); }
|
||||
inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
|
||||
inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
|
||||
|
||||
inline void destroyIter() { _destroyIter(&_iterator); }
|
||||
|
||||
inline void getCurrentKey(void *dataPtr) const { return _getKey(&_iterator, dataPtr); }
|
||||
inline void getCurrentValue(void *dataPtr) const { return _getValue(&_iterator, dataPtr); }
|
||||
|
||||
inline void find(const void *key)
|
||||
{ _find(_iterable, key, &_iterator); }
|
||||
|
||||
int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
|
||||
|
||||
void copy(const QAssociativeIterableImpl &other)
|
||||
{
|
||||
*this = other;
|
||||
_copyIter(&_iterator, &other._iterator);
|
||||
}
|
||||
};
|
||||
QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QAssociativeIterableImpl, Q_MOVABLE_TYPE)
|
||||
|
||||
template<typename From>
|
||||
struct QAssociativeIterableConvertFunctor
|
||||
{
|
||||
QAssociativeIterableImpl operator()(const From& f) const
|
||||
{
|
||||
return QAssociativeIterableImpl(&f);
|
||||
}
|
||||
};
|
||||
|
||||
class QPairVariantInterfaceImpl
|
||||
{
|
||||
|
|
@ -1675,7 +1416,6 @@ QT_END_NAMESPACE
|
|||
|
||||
QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
|
||||
|
||||
Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
|
||||
Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -1692,19 +1432,53 @@ inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
|
|||
}
|
||||
|
||||
namespace QtPrivate {
|
||||
template<typename T>
|
||||
struct AssociativeValueTypeIsMetaType<T, true>
|
||||
|
||||
template<typename From>
|
||||
struct QSequentialIterableConvertFunctor
|
||||
{
|
||||
QIterable<QMetaSequence> operator()(const From &f) const
|
||||
{
|
||||
static bool registerConverter(int id)
|
||||
{
|
||||
const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
|
||||
if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
|
||||
QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
|
||||
return QMetaType::registerConverter<T, QtMetaTypePrivate::QAssociativeIterableImpl>(o);
|
||||
}
|
||||
return true;
|
||||
return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SequentialValueTypeIsMetaType<T, true>
|
||||
{
|
||||
static bool registerConverter(int id)
|
||||
{
|
||||
const int toId = qMetaTypeId<QIterable<QMetaSequence>>();
|
||||
if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
|
||||
QSequentialIterableConvertFunctor<T> o;
|
||||
return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
|
||||
}
|
||||
};
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From>
|
||||
struct QAssociativeIterableConvertFunctor
|
||||
{
|
||||
QIterable<QMetaAssociation> operator()(const From &f) const
|
||||
{
|
||||
return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct AssociativeValueTypeIsMetaType<T, true>
|
||||
{
|
||||
static bool registerConverter(int id)
|
||||
{
|
||||
const int toId = qMetaTypeId<QIterable<QMetaAssociation>>();
|
||||
if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
|
||||
QAssociativeIterableConvertFunctor<T> o;
|
||||
return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace QtPrivate {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,258 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qsequentialiterable.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
#include <QtCore/private/qiterable_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QSequentialIterable
|
||||
\since 5.2
|
||||
\inmodule QtCore
|
||||
\brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
|
||||
|
||||
This class allows several methods of accessing the values of a container held within
|
||||
a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
|
||||
be converted to a QVariantList.
|
||||
|
||||
\snippet code/src_corelib_kernel_qvariant.cpp 9
|
||||
|
||||
The container itself is not copied before iterating over it.
|
||||
|
||||
\sa QVariant
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::RandomAccessIterator
|
||||
Exposes an iterator using std::random_access_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::BidirectionalIterator
|
||||
Exposes an iterator using std::bidirectional_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::ForwardIterator
|
||||
Exposes an iterator using std::forward_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::InputIterator
|
||||
Exposes an iterator using std::input_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::RandomAccessConstIterator
|
||||
Exposes a const_iterator using std::random_access_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::BidirectionalConstIterator
|
||||
Exposes a const_iterator using std::bidirectional_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::ForwardConstIterator
|
||||
Exposes a const_iterator using std::forward_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QSequentialIterable::InputConstIterator
|
||||
Exposes a const_iterator using std::input_iterator_tag.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Adds \a value to the container, at \a position, if possible.
|
||||
*/
|
||||
void QSequentialIterable::addValue(const QVariant &value, Position position)
|
||||
{
|
||||
QVariant converted = value;
|
||||
const void *valuePtr = QIterablePrivate::coerceType(converted, metaContainer().valueMetaType());
|
||||
|
||||
switch (position) {
|
||||
case AtBegin:
|
||||
if (metaContainer().canAddValueAtBegin())
|
||||
metaContainer().addValueAtBegin(mutableIterable(), valuePtr);
|
||||
break;
|
||||
case AtEnd:
|
||||
if (metaContainer().canAddValueAtEnd())
|
||||
metaContainer().addValueAtEnd(mutableIterable(), valuePtr);
|
||||
break;
|
||||
case Unspecified:
|
||||
if (metaContainer().canAddValue())
|
||||
metaContainer().addValue(mutableIterable(), valuePtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a value from the container, at \a position, if possible.
|
||||
*/
|
||||
void QSequentialIterable::removeValue(Position position)
|
||||
{
|
||||
switch (position) {
|
||||
case AtBegin:
|
||||
if (metaContainer().canRemoveValueAtBegin())
|
||||
metaContainer().removeValueAtBegin(mutableIterable());
|
||||
break;
|
||||
case AtEnd:
|
||||
if (metaContainer().canRemoveValueAtEnd())
|
||||
metaContainer().removeValueAtEnd(mutableIterable());
|
||||
break;
|
||||
case Unspecified:
|
||||
if (metaContainer().canRemoveValue())
|
||||
metaContainer().removeValue(mutableIterable());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QMetaType QSequentialIterable::valueMetaType() const
|
||||
{
|
||||
return QMetaType(metaContainer().valueMetaType());
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the value at position \a idx in the container.
|
||||
*/
|
||||
QVariant QSequentialIterable::at(qsizetype idx) const
|
||||
{
|
||||
QVariant v(valueMetaType());
|
||||
void *dataPtr;
|
||||
if (valueMetaType() == QMetaType::fromType<QVariant>())
|
||||
dataPtr = &v;
|
||||
else
|
||||
dataPtr = v.data();
|
||||
|
||||
const QMetaSequence meta = metaContainer();
|
||||
if (meta.canGetValueAtIndex()) {
|
||||
meta.valueAtIndex(m_iterable.constPointer(), idx, dataPtr);
|
||||
} else if (meta.canGetValueAtConstIterator()) {
|
||||
void *iterator = meta.constBegin(m_iterable.constPointer());
|
||||
meta.advanceConstIterator(iterator, idx);
|
||||
meta.valueAtConstIterator(iterator, dataPtr);
|
||||
meta.destroyConstIterator(iterator);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the element at position \a idx in the container to \a value.
|
||||
*/
|
||||
void QSequentialIterable::set(qsizetype idx, const QVariant &value)
|
||||
{
|
||||
QVariant converted = value;
|
||||
const void *dataPtr = QIterablePrivate::coerceType(converted, metaContainer().valueMetaType());
|
||||
|
||||
const QMetaSequence meta = metaContainer();
|
||||
if (meta.canSetValueAtIndex()) {
|
||||
meta.setValueAtIndex(m_iterable.mutablePointer(), idx, dataPtr);
|
||||
} else if (meta.canSetValueAtIterator()) {
|
||||
void *iterator = meta.begin(m_iterable.mutablePointer());
|
||||
meta.advanceIterator(iterator, idx);
|
||||
meta.setValueAtIterator(iterator, dataPtr);
|
||||
meta.destroyIterator(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QSequentialIterable::const_iterator
|
||||
\since 5.2
|
||||
\inmodule QtCore
|
||||
\brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
|
||||
|
||||
A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
|
||||
and can be used in a way similar to other stl-style iterators.
|
||||
|
||||
\snippet code/src_corelib_kernel_qvariant.cpp 9
|
||||
|
||||
\sa QSequentialIterable
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QSequentialIterable::iterator
|
||||
\since 6.0
|
||||
\inmodule QtCore
|
||||
\brief The QSequentialIterable::iterator allows iteration over a container in a QVariant.
|
||||
|
||||
A QSequentialIterable::iterator can only be created by a QSequentialIterable instance,
|
||||
and can be used in a way similar to other stl-style iterators.
|
||||
|
||||
\sa QSequentialIterable
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariantRef.
|
||||
*/
|
||||
QVariantRef<QSequentialIterator> QSequentialIterator::operator*() const
|
||||
{
|
||||
return QVariantRef<QSequentialIterator>(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariantPointer.
|
||||
*/
|
||||
QVariantPointer<QSequentialIterator> QSequentialIterator::operator->() const
|
||||
{
|
||||
return QVariantPointer<QSequentialIterator>(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariant.
|
||||
*/
|
||||
QVariant QSequentialConstIterator::operator*() const
|
||||
{
|
||||
return QIterablePrivate::retrieveElement(metaContainer().valueMetaType(), [this](void *dataPtr) {
|
||||
metaContainer().valueAtConstIterator(constIterator(), dataPtr);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current item, converted to a QVariantConstPointer.
|
||||
*/
|
||||
QVariantConstPointer QSequentialConstIterator::operator->() const
|
||||
{
|
||||
return QVariantConstPointer(operator*());
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QSEQUENTIALITERABLE_H
|
||||
#define QSEQUENTIALITERABLE_H
|
||||
|
||||
#include <QtCore/qiterable.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QSequentialIterator : public QIterator<QMetaSequence>
|
||||
{
|
||||
public:
|
||||
using value_type = QVariant;
|
||||
using reference = QVariantRef<QSequentialIterator>;
|
||||
using pointer = QVariantPointer<QSequentialIterator>;
|
||||
|
||||
QSequentialIterator(QIterator &&it)
|
||||
: QIterator(std::move(it))
|
||||
{}
|
||||
|
||||
QVariantRef<QSequentialIterator> operator*() const;
|
||||
QVariantPointer<QSequentialIterator> operator->() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator<QMetaSequence>
|
||||
{
|
||||
public:
|
||||
using value_type = QVariant;
|
||||
using reference = const QVariant &;
|
||||
using pointer = QVariantConstPointer;
|
||||
|
||||
QSequentialConstIterator(QConstIterator &&it)
|
||||
: QConstIterator(std::move(it))
|
||||
{}
|
||||
|
||||
QVariant operator*() const;
|
||||
QVariantConstPointer operator->() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QSequentialIterable : public QIterable<QMetaSequence>
|
||||
{
|
||||
public:
|
||||
using iterator = QTaggedIterator<QSequentialIterator, void>;
|
||||
using const_iterator = QTaggedIterator<QSequentialConstIterator, void>;
|
||||
|
||||
using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
|
||||
using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
|
||||
using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
|
||||
using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
|
||||
|
||||
using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
|
||||
using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
|
||||
using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
|
||||
using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
|
||||
|
||||
template<class T>
|
||||
QSequentialIterable(const T *p)
|
||||
: QIterable(QMetaSequence::fromContainer<T>(), p)
|
||||
{
|
||||
Q_UNUSED(m_revision);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
QSequentialIterable(T *p)
|
||||
: QIterable(QMetaSequence::fromContainer<T>(), p)
|
||||
{
|
||||
}
|
||||
|
||||
QSequentialIterable() = default;
|
||||
|
||||
template<typename Pointer>
|
||||
QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
|
||||
: QIterable(metaSequence, iterable)
|
||||
{
|
||||
}
|
||||
|
||||
QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
|
||||
void *iterable)
|
||||
: QIterable(metaSequence, metaType.alignOf(), iterable)
|
||||
{
|
||||
}
|
||||
|
||||
QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
|
||||
const void *iterable)
|
||||
: QIterable(metaSequence, metaType.alignOf(), iterable)
|
||||
{
|
||||
}
|
||||
|
||||
QSequentialIterable(QIterable<QMetaSequence> &&other) : QIterable(std::move(other)) {}
|
||||
|
||||
QSequentialIterable &operator=(QIterable<QMetaSequence> &&other)
|
||||
{
|
||||
QIterable::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator begin() const { return constBegin(); }
|
||||
const_iterator end() const { return constEnd(); }
|
||||
|
||||
const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
|
||||
const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
|
||||
|
||||
iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
|
||||
iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
|
||||
|
||||
QVariant at(qsizetype idx) const;
|
||||
void set(qsizetype idx, const QVariant &value);
|
||||
|
||||
enum Position { Unspecified, AtBegin, AtEnd };
|
||||
void addValue(const QVariant &value, Position position = Unspecified);
|
||||
void removeValue(Position position = Unspecified);
|
||||
|
||||
QMetaType valueMetaType() const;
|
||||
};
|
||||
|
||||
template<>
|
||||
inline QVariantRef<QSequentialIterator>::operator QVariant() const
|
||||
{
|
||||
if (m_pointer == nullptr)
|
||||
return QVariant();
|
||||
const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
|
||||
QVariant v(metaType);
|
||||
void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
|
||||
m_pointer->metaContainer().valueAtIterator(m_pointer->constIterator(), dataPtr);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline QVariantRef<QSequentialIterator> &QVariantRef<QSequentialIterator>::operator=(
|
||||
const QVariant &value)
|
||||
{
|
||||
if (m_pointer == nullptr)
|
||||
return *this;
|
||||
const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
|
||||
const void *dataPtr = metaType == QMetaType::fromType<QVariant>()
|
||||
? &value
|
||||
: value.constData();
|
||||
m_pointer->metaContainer().setValueAtIterator(m_pointer->constIterator(), dataPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Q_DECLARE_TYPEINFO(QSequentialIterable, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QSequentialIterable::iterator, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_MOVABLE_TYPE);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QSEQUENTIALITERABLE_H
|
||||
|
|
@ -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<QVariant>())
|
||||
dataPtr = &v;
|
||||
else
|
||||
dataPtr = v.data();
|
||||
m_impl.getCurrentValue(dataPtr);
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current key, converted to a QVariant.
|
||||
*/
|
||||
const QVariant QAssociativeIterable::const_iterator::key() const
|
||||
{
|
||||
QVariant v(m_impl._metaType_key);
|
||||
void *dataPtr;
|
||||
if (m_impl._metaType_key == QMetaType::fromType<QVariant>())
|
||||
dataPtr = &v;
|
||||
else
|
||||
dataPtr = v.data();
|
||||
m_impl.getCurrentKey(dataPtr);
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the current value, converted to a QVariant.
|
||||
*/
|
||||
const QVariant QAssociativeIterable::const_iterator::value() const
|
||||
{
|
||||
return operator*();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if \a other points to the same item as this
|
||||
iterator; otherwise returns \c false.
|
||||
|
||||
\sa operator!=()
|
||||
*/
|
||||
bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const
|
||||
{
|
||||
return m_impl.equal(other.m_impl);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if \a other points to a different item than this
|
||||
iterator; otherwise returns \c false.
|
||||
|
||||
\sa operator==()
|
||||
*/
|
||||
bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const
|
||||
{
|
||||
return !m_impl.equal(other.m_impl);
|
||||
}
|
||||
|
||||
/*!
|
||||
The prefix ++ operator (\c{++it}) advances the iterator to the
|
||||
next item in the container and returns an iterator to the new current
|
||||
item.
|
||||
|
||||
Calling this function on QAssociativeIterable::end() leads to undefined results.
|
||||
|
||||
\sa operator--()
|
||||
*/
|
||||
QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++()
|
||||
{
|
||||
m_impl.advance(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
The postfix ++ operator (\c{it++}) advances the iterator to the
|
||||
next item in the container and returns an iterator to the previously
|
||||
current item.
|
||||
*/
|
||||
QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int)
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl impl;
|
||||
impl.copy(m_impl);
|
||||
m_impl.advance(1);
|
||||
return const_iterator(impl, new QAtomicInt(0));
|
||||
}
|
||||
|
||||
/*!
|
||||
The prefix -- operator (\c{--it}) makes the preceding item
|
||||
current and returns an iterator to the new current item.
|
||||
|
||||
Calling this function on QAssociativeIterable::begin() leads to undefined results.
|
||||
|
||||
\sa operator++()
|
||||
*/
|
||||
QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--()
|
||||
{
|
||||
m_impl.advance(-1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
The postfix -- operator (\c{it--}) makes the preceding item
|
||||
current and returns an iterator to the previously current item.
|
||||
*/
|
||||
QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int)
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl impl;
|
||||
impl.copy(m_impl);
|
||||
m_impl.advance(-1);
|
||||
return const_iterator(impl, new QAtomicInt(0));
|
||||
}
|
||||
|
||||
/*!
|
||||
Advances the iterator by \a j items.
|
||||
|
||||
\sa operator-=(), operator+()
|
||||
*/
|
||||
QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j)
|
||||
{
|
||||
m_impl.advance(j);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Makes the iterator go back by \a j items.
|
||||
|
||||
\sa operator+=(), operator-()
|
||||
*/
|
||||
QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j)
|
||||
{
|
||||
m_impl.advance(-j);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an iterator to the item at \a j positions forward from
|
||||
this iterator.
|
||||
|
||||
\sa operator-(), operator+=()
|
||||
*/
|
||||
QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl impl;
|
||||
impl.copy(m_impl);
|
||||
impl.advance(j);
|
||||
return const_iterator(impl, new QAtomicInt(0));
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an iterator to the item at \a j positions backward from
|
||||
this iterator.
|
||||
|
||||
\sa operator+(), operator-=()
|
||||
*/
|
||||
QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl impl;
|
||||
impl.copy(m_impl);
|
||||
impl.advance(-j);
|
||||
return const_iterator(impl, new QAtomicInt(0));
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QVariantRef
|
||||
\since 6.0
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -580,61 +580,6 @@ inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
|
|||
#endif
|
||||
Q_DECLARE_SHARED(QVariant)
|
||||
|
||||
class Q_CORE_EXPORT QAssociativeIterable
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
|
||||
public:
|
||||
struct Q_CORE_EXPORT const_iterator
|
||||
{
|
||||
private:
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
|
||||
QAtomicInt *ref;
|
||||
friend class QAssociativeIterable;
|
||||
explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_);
|
||||
|
||||
explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_);
|
||||
|
||||
void begin();
|
||||
void end();
|
||||
void find(const QVariant &key);
|
||||
public:
|
||||
~const_iterator();
|
||||
const_iterator(const const_iterator &other);
|
||||
|
||||
const_iterator& operator=(const const_iterator &other);
|
||||
|
||||
const QVariant key() const;
|
||||
|
||||
const QVariant value() const;
|
||||
|
||||
const QVariant operator*() const;
|
||||
bool operator==(const const_iterator &o) const;
|
||||
bool operator!=(const const_iterator &o) const;
|
||||
const_iterator &operator++();
|
||||
const_iterator operator++(int);
|
||||
const_iterator &operator--();
|
||||
const_iterator operator--(int);
|
||||
const_iterator &operator+=(int j);
|
||||
const_iterator &operator-=(int j);
|
||||
const_iterator operator+(int j) const;
|
||||
const_iterator operator-(int j) const;
|
||||
friend inline const_iterator operator+(int j, const const_iterator &k) { return k + j; }
|
||||
};
|
||||
|
||||
friend struct const_iterator;
|
||||
|
||||
explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl);
|
||||
QAssociativeIterable() {}
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
const_iterator find(const QVariant &key) const;
|
||||
|
||||
QVariant value(const QVariant &key) const;
|
||||
|
||||
int size() const;
|
||||
};
|
||||
|
||||
#ifndef QT_MOC
|
||||
|
||||
template<typename T> inline T qvariant_cast(const QVariant &v)
|
||||
|
|
|
|||
|
|
@ -4151,91 +4151,148 @@ struct KeyGetter<std::unordered_map<T, U> >
|
|||
};
|
||||
#endif
|
||||
|
||||
template<typename Iterator>
|
||||
void sortIterable(QSequentialIterable *iterable)
|
||||
{
|
||||
std::sort(Iterator(iterable->mutableBegin()), Iterator(iterable->mutableEnd()),
|
||||
[&](const QVariant &a, const QVariant &b) {
|
||||
return a.toInt() < b.toInt();
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
void testSequentialIteration()
|
||||
{
|
||||
int numSeen = 0;
|
||||
Container sequence;
|
||||
ContainerAPI<Container>::insert(sequence, 1);
|
||||
ContainerAPI<Container>::insert(sequence, 2);
|
||||
ContainerAPI<Container>::insert(sequence, 3);
|
||||
|
||||
QVariant listVariant = QVariant::fromValue(sequence);
|
||||
QVERIFY(listVariant.canConvert<QVariantList>());
|
||||
QVariantList varList = listVariant.value<QVariantList>();
|
||||
QCOMPARE(varList.size(), (int)std::distance(sequence.begin(), sequence.end()));
|
||||
QSequentialIterable listIter = listVariant.value<QSequentialIterable>();
|
||||
QCOMPARE(varList.size(), listIter.size());
|
||||
|
||||
typename Container::iterator containerIter = sequence.begin();
|
||||
const typename Container::iterator containerEnd = sequence.end();
|
||||
for (int i = 0; i < listIter.size(); ++i, ++containerIter, ++numSeen)
|
||||
{
|
||||
QVERIFY(ContainerAPI<Container >::compare(listIter.at(i), *containerIter));
|
||||
QVERIFY(ContainerAPI<Container >::compare(listIter.at(i), varList.at(i)));
|
||||
}
|
||||
QCOMPARE(numSeen, (int)std::distance(sequence.begin(), sequence.end()));
|
||||
QCOMPARE(containerIter, containerEnd);
|
||||
|
||||
containerIter = sequence.begin();
|
||||
numSeen = 0;
|
||||
Q_FOREACH (const QVariant &v, listIter) {
|
||||
QVERIFY(ContainerAPI<Container>::compare(v, *containerIter));
|
||||
QVERIFY(ContainerAPI<Container>::compare(v, varList.at(numSeen)));
|
||||
++containerIter;
|
||||
++numSeen;
|
||||
}
|
||||
QCOMPARE(numSeen, (int)std::distance(sequence.begin(), sequence.end()));
|
||||
|
||||
numSeen = 0;
|
||||
containerIter = sequence.begin();
|
||||
for (QVariant v : listIter) {
|
||||
QVERIFY(ContainerAPI<Container>::compare(v, *containerIter));
|
||||
QVERIFY(ContainerAPI<Container>::compare(v, varList.at(numSeen)));
|
||||
++containerIter;
|
||||
++numSeen;
|
||||
}
|
||||
QCOMPARE(numSeen, (int)std::distance(sequence.begin(), sequence.end()));
|
||||
|
||||
auto compareLists = [&]() {
|
||||
int numSeen = 0;
|
||||
auto varList = listVariant.value<QVariantList>();
|
||||
auto varIter = varList.begin();
|
||||
for (const QVariant &v : qAsConst(listIter)) {
|
||||
QVERIFY(ContainerAPI<Container>::compare(v, *varIter));
|
||||
++varIter;
|
||||
++numSeen;
|
||||
}
|
||||
QCOMPARE(varIter, varList.end());
|
||||
numSeen = 0;
|
||||
auto constVarIter = varList.constBegin();
|
||||
for (QVariant v : listIter) {
|
||||
QVERIFY(ContainerAPI<Container>::compare(v, *constVarIter));
|
||||
++constVarIter;
|
||||
++numSeen;
|
||||
}
|
||||
QCOMPARE(numSeen, (int)std::distance(varList.begin(), varList.end()));
|
||||
};
|
||||
compareLists();
|
||||
|
||||
QVariant first = listIter.at(0);
|
||||
QVariant second = listIter.at(1);
|
||||
QVariant third = listIter.at(2);
|
||||
compareLists();
|
||||
listIter.addValue(third);
|
||||
compareLists();
|
||||
listIter.addValue(second);
|
||||
compareLists();
|
||||
listIter.addValue(first);
|
||||
compareLists();
|
||||
|
||||
QCOMPARE(listIter.size(), 6);
|
||||
|
||||
if (listIter.canRandomAccessIterate())
|
||||
sortIterable<QSequentialIterable::RandomAccessIterator>(&listIter);
|
||||
else if (listIter.canReverseIterate())
|
||||
sortIterable<QSequentialIterable::BidirectionalIterator>(&listIter);
|
||||
else if (listIter.canForwardIterate())
|
||||
return; // std::sort cannot sort with only forward iterators.
|
||||
else
|
||||
QFAIL("The container has no meaningful iterators");
|
||||
|
||||
compareLists();
|
||||
QCOMPARE(listIter.size(), 6);
|
||||
QCOMPARE(listIter.at(0), first);
|
||||
QCOMPARE(listIter.at(1), first);
|
||||
QCOMPARE(listIter.at(2), second);
|
||||
QCOMPARE(listIter.at(3), second);
|
||||
QCOMPARE(listIter.at(4), third);
|
||||
QCOMPARE(listIter.at(5), third);
|
||||
|
||||
listIter.removeValue();
|
||||
compareLists();
|
||||
QCOMPARE(listIter.size(), 5);
|
||||
QCOMPARE(listIter.at(0), first);
|
||||
QCOMPARE(listIter.at(1), first);
|
||||
QCOMPARE(listIter.at(2), second);
|
||||
QCOMPARE(listIter.at(3), second);
|
||||
QCOMPARE(listIter.at(4), third);
|
||||
}
|
||||
|
||||
void tst_QVariant::iterateContainerElements()
|
||||
{
|
||||
#ifdef Q_COMPILER_RANGE_FOR
|
||||
|
||||
#define TEST_RANGE_FOR(CONTAINER) \
|
||||
numSeen = 0; \
|
||||
containerIter = intList.begin(); \
|
||||
for (QVariant v : listIter) { \
|
||||
QVERIFY(ContainerAPI<CONTAINER >::compare(v, *containerIter)); \
|
||||
QVERIFY(ContainerAPI<CONTAINER >::compare(v, varList.at(numSeen))); \
|
||||
++containerIter; \
|
||||
++numSeen; \
|
||||
} \
|
||||
QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end()));
|
||||
|
||||
#else
|
||||
|
||||
#define TEST_RANGE_FOR(CONTAINER)
|
||||
|
||||
#endif
|
||||
|
||||
#define TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(CONTAINER) \
|
||||
{ \
|
||||
int numSeen = 0; \
|
||||
CONTAINER intList; \
|
||||
ContainerAPI<CONTAINER >::insert(intList, 1); \
|
||||
ContainerAPI<CONTAINER >::insert(intList, 2); \
|
||||
ContainerAPI<CONTAINER >::insert(intList, 3); \
|
||||
\
|
||||
QVariant listVariant = QVariant::fromValue(intList); \
|
||||
QVERIFY(listVariant.canConvert<QVariantList>()); \
|
||||
QVariantList varList = listVariant.value<QVariantList>(); \
|
||||
QCOMPARE(varList.size(), (int)std::distance(intList.begin(), intList.end())); \
|
||||
QSequentialIterable listIter = listVariant.value<QSequentialIterable>(); \
|
||||
QCOMPARE(varList.size(), listIter.size()); \
|
||||
\
|
||||
CONTAINER::iterator containerIter = intList.begin(); \
|
||||
const CONTAINER::iterator containerEnd = intList.end(); \
|
||||
for (int i = 0; i < listIter.size(); ++i, ++containerIter, ++numSeen) \
|
||||
{ \
|
||||
QVERIFY(ContainerAPI<CONTAINER >::compare(listIter.at(i), *containerIter)); \
|
||||
QVERIFY(ContainerAPI<CONTAINER >::compare(listIter.at(i), varList.at(i))); \
|
||||
} \
|
||||
QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end())); \
|
||||
QCOMPARE(containerIter, containerEnd); \
|
||||
\
|
||||
containerIter = intList.begin(); \
|
||||
numSeen = 0; \
|
||||
Q_FOREACH (const QVariant &v, listIter) { \
|
||||
QVERIFY(ContainerAPI<CONTAINER >::compare(v, *containerIter)); \
|
||||
QVERIFY(ContainerAPI<CONTAINER >::compare(v, varList.at(numSeen))); \
|
||||
++containerIter; \
|
||||
++numSeen; \
|
||||
} \
|
||||
QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end())); \
|
||||
TEST_RANGE_FOR(CONTAINER) \
|
||||
}
|
||||
|
||||
#define TEST_SEQUENTIAL_ITERATION(CONTAINER, VALUE_TYPE) \
|
||||
TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(CONTAINER<VALUE_TYPE > )
|
||||
|
||||
|
||||
TEST_SEQUENTIAL_ITERATION(QQueue, int)
|
||||
TEST_SEQUENTIAL_ITERATION(QQueue, QVariant)
|
||||
TEST_SEQUENTIAL_ITERATION(QQueue, QString)
|
||||
TEST_SEQUENTIAL_ITERATION(QList, int)
|
||||
TEST_SEQUENTIAL_ITERATION(QList, QVariant)
|
||||
TEST_SEQUENTIAL_ITERATION(QList, QString)
|
||||
TEST_SEQUENTIAL_ITERATION(QList, QByteArray)
|
||||
TEST_SEQUENTIAL_ITERATION(QStack, int)
|
||||
TEST_SEQUENTIAL_ITERATION(QStack, QVariant)
|
||||
TEST_SEQUENTIAL_ITERATION(QStack, QString)
|
||||
TEST_SEQUENTIAL_ITERATION(std::vector, int)
|
||||
TEST_SEQUENTIAL_ITERATION(std::vector, QVariant)
|
||||
TEST_SEQUENTIAL_ITERATION(std::vector, QString)
|
||||
TEST_SEQUENTIAL_ITERATION(std::list, int)
|
||||
TEST_SEQUENTIAL_ITERATION(std::list, QVariant)
|
||||
TEST_SEQUENTIAL_ITERATION(std::list, QString)
|
||||
TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(QStringList)
|
||||
TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(QByteArrayList)
|
||||
testSequentialIteration<QQueue<int>>();
|
||||
testSequentialIteration<QQueue<QVariant>>();
|
||||
testSequentialIteration<QQueue<QString>>();
|
||||
testSequentialIteration<QList<int>>();
|
||||
testSequentialIteration<QList<QVariant>>();
|
||||
testSequentialIteration<QList<QString>>();
|
||||
testSequentialIteration<QList<QByteArray>>();
|
||||
testSequentialIteration<QStack<int>>();
|
||||
testSequentialIteration<QStack<QVariant>>();
|
||||
testSequentialIteration<QStack<QString>>();
|
||||
testSequentialIteration<std::vector<int>>();
|
||||
testSequentialIteration<std::vector<QVariant>>();
|
||||
testSequentialIteration<std::vector<QString>>();
|
||||
testSequentialIteration<std::list<int>>();
|
||||
testSequentialIteration<std::list<QVariant>>();
|
||||
testSequentialIteration<std::list<QString>>();
|
||||
testSequentialIteration<QStringList>();
|
||||
testSequentialIteration<QByteArrayList>();
|
||||
|
||||
#ifdef TEST_FORWARD_LIST
|
||||
TEST_SEQUENTIAL_ITERATION(std::forward_list, int)
|
||||
TEST_SEQUENTIAL_ITERATION(std::forward_list, QVariant)
|
||||
TEST_SEQUENTIAL_ITERATION(std::forward_list, QString)
|
||||
testSequentialIteration<std::forward_list<int>>();
|
||||
testSequentialIteration<std::forward_list<QVariant>>();
|
||||
testSequentialIteration<std::forward_list<QString>>();
|
||||
#endif
|
||||
|
||||
{
|
||||
|
|
@ -4575,37 +4632,42 @@ void tst_QVariant::shouldDeleteVariantDataWorksForAssociative()
|
|||
{
|
||||
QCOMPARE(instanceCount, 0);
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl iterator {};
|
||||
QtMetaContainerPrivate::QMetaAssociationInterface iterator {};
|
||||
|
||||
iterator._size = [](const void *) {return 1;};
|
||||
iterator._metaType_value = QMetaType::fromType<MyType>();
|
||||
iterator._metaType_key = QMetaType::fromType<MyType>();
|
||||
iterator._begin = [](const void *, void **) {};
|
||||
iterator._end = [](const void *, void **) {};
|
||||
iterator._advance = [](void **, int) {};
|
||||
iterator._destroyIter = [](void **){};
|
||||
iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
|
||||
iterator._destroyIter = [](void **){};
|
||||
iterator._find = [](const void *, const void *, void **iterator ) -> void {
|
||||
(*iterator) = reinterpret_cast<void *>(quintptr(42));
|
||||
iterator.sizeFn = [](const void *) -> qsizetype {return 1;};
|
||||
iterator.mappedMetaType = QtPrivate::qMetaTypeInterfaceForType<MyType>();
|
||||
iterator.keyMetaType = QtPrivate::qMetaTypeInterfaceForType<MyType>();
|
||||
iterator.createConstIteratorFn = [](
|
||||
const void *, QtMetaContainerPrivate::QMetaContainerInterface::Position) -> void * {
|
||||
return nullptr;
|
||||
};
|
||||
iterator._getKey = [](void * const *iterator, void *dataPtr) -> void {
|
||||
iterator.advanceConstIteratorFn = [](void *, qsizetype) {};
|
||||
iterator.destroyConstIteratorFn = [](const void *){};
|
||||
iterator.compareConstIteratorFn = [](const void *, const void *) {
|
||||
return true; /*all iterators are nullptr*/
|
||||
};
|
||||
iterator.createConstIteratorAtKeyFn = [](const void *, const void *) -> void * {
|
||||
return reinterpret_cast<void *>(quintptr(42));
|
||||
};
|
||||
iterator.copyConstIteratorFn = [](void *, const void *) {};
|
||||
iterator.diffConstIteratorFn = [](const void *, const void *) -> qsizetype { return 0; };
|
||||
iterator.keyAtConstIteratorFn = [](const void *iterator, void *dataPtr) -> void {
|
||||
MyType mytype {1, "key"};
|
||||
if (reinterpret_cast<quintptr>(*iterator) == 42) {
|
||||
if (reinterpret_cast<quintptr>(iterator) == 42) {
|
||||
mytype.number = 42;
|
||||
mytype.text = "find_key";
|
||||
}
|
||||
*static_cast<MyType *>(dataPtr) = mytype;
|
||||
};
|
||||
iterator._getValue = [](void * const *iterator, void *dataPtr) -> void {
|
||||
iterator.mappedAtConstIteratorFn = [](const void *iterator, void *dataPtr) -> void {
|
||||
MyType mytype {2, "value"};
|
||||
if (reinterpret_cast<quintptr>(*iterator) == 42) {
|
||||
if (reinterpret_cast<quintptr>(iterator) == 42) {
|
||||
mytype.number = 42;
|
||||
mytype.text = "find_value";
|
||||
}
|
||||
*static_cast<MyType *>(dataPtr) = mytype;
|
||||
};
|
||||
QAssociativeIterable iterable {iterator};
|
||||
QAssociativeIterable iterable(QMetaAssociation(&iterator), nullptr);
|
||||
auto it = iterable.begin();
|
||||
QVariant value1 = it.key();
|
||||
QVERIFY(value1.canConvert<MyType>());
|
||||
|
|
@ -4695,37 +4757,37 @@ void tst_QVariant::sequentialIterableAppend()
|
|||
{
|
||||
QList<int> container { 1, 2 };
|
||||
auto variant = QVariant::fromValue(container);
|
||||
QVERIFY(variant.canConvert<QSequentialIterable>());
|
||||
auto asIterable = variant.value<QSequentialIterable>();
|
||||
QVERIFY(variant.canConvert<QIterable<QMetaSequence>>());
|
||||
QSequentialIterable asIterable = variant.value<QIterable<QMetaSequence>>();
|
||||
const int i = 3, j = 4;
|
||||
void *mutableIterable = asIterable.mutableIterable();
|
||||
asIterable.metaSequence().addValueAtEnd(mutableIterable, &i);
|
||||
asIterable.metaSequence().addValueAtEnd(mutableIterable, &j);
|
||||
asIterable.metaContainer().addValueAtEnd(mutableIterable, &i);
|
||||
asIterable.metaContainer().addValueAtEnd(mutableIterable, &j);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 1, 2, 3, 4 }));
|
||||
|
||||
asIterable.metaSequence().addValueAtBegin(mutableIterable, &i);
|
||||
asIterable.metaSequence().addValueAtBegin(mutableIterable, &j);
|
||||
asIterable.metaContainer().addValueAtBegin(mutableIterable, &i);
|
||||
asIterable.metaContainer().addValueAtBegin(mutableIterable, &j);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 4, 3, 1, 2, 3, 4 }));
|
||||
|
||||
asIterable.metaSequence().removeValueAtBegin(mutableIterable);
|
||||
asIterable.metaContainer().removeValueAtBegin(mutableIterable);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 3, 1, 2, 3, 4 }));
|
||||
asIterable.metaSequence().removeValueAtEnd(mutableIterable);
|
||||
asIterable.metaContainer().removeValueAtEnd(mutableIterable);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 3, 1, 2, 3 }));
|
||||
}
|
||||
{
|
||||
QSet<QByteArray> container { QByteArray{"hello"}, QByteArray{"world"} };
|
||||
auto variant = QVariant::fromValue(std::move(container));
|
||||
QVERIFY(variant.canConvert<QSequentialIterable>());
|
||||
auto asIterable = variant.value<QSequentialIterable>();
|
||||
QVERIFY(variant.canConvert<QIterable<QMetaSequence>>());
|
||||
QSequentialIterable asIterable = variant.value<QIterable<QMetaSequence>>();
|
||||
QByteArray qba1 {"goodbye"};
|
||||
QByteArray qba2 { "moon" };
|
||||
void *mutableIterable = asIterable.mutableIterable();
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba1);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba2);
|
||||
asIterable.metaContainer().addValue(mutableIterable, &qba1);
|
||||
asIterable.metaContainer().addValue(mutableIterable, &qba2);
|
||||
QSet<QByteArray> reference { "hello", "world", "goodbye", "moon" };
|
||||
QCOMPARE(variant.value<QSet<QByteArray>>(), reference);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba1);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba2);
|
||||
asIterable.metaContainer().addValue(mutableIterable, &qba1);
|
||||
asIterable.metaContainer().addValue(mutableIterable, &qba2);
|
||||
QCOMPARE(variant.value<QSet<QByteArray>>(), reference);
|
||||
}
|
||||
}
|
||||
|
|
@ -4741,8 +4803,8 @@ void tst_QVariant::preferDirectConversionOverInterfaces()
|
|||
calledCorrectConverter = true;
|
||||
return QVariantList {};
|
||||
});
|
||||
QMetaType::registerConverter<MyType, QAssociativeIterableImpl>([](const MyType &) {
|
||||
return QAssociativeIterableImpl {};
|
||||
QMetaType::registerConverter<MyType, QAssociativeIterable>([](const MyType &) {
|
||||
return QAssociativeIterable {};
|
||||
});
|
||||
QMetaType::registerConverter<MyType, QVariantHash>([&calledCorrectConverter](const MyType &) {
|
||||
calledCorrectConverter = true;
|
||||
|
|
@ -4756,7 +4818,7 @@ void tst_QVariant::preferDirectConversionOverInterfaces()
|
|||
|
||||
QVERIFY(holder.canConvert<QSequentialIterable>());
|
||||
QVERIFY(holder.canConvert<QVariantList>());
|
||||
QVERIFY(holder.canConvert<QAssociativeIterableImpl>());
|
||||
QVERIFY(holder.canConvert<QAssociativeIterable>());
|
||||
QVERIFY(holder.canConvert<QVariantHash>());
|
||||
QVERIFY(holder.canConvert<QVariantMap>());
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ struct ForwardDeclaredParam;
|
|||
template <typename T> class ForwardDeclaredContainer;
|
||||
|
||||
struct FullyDefined {};
|
||||
inline size_t qHash(const FullyDefined &, size_t seed = 0) { return seed; }
|
||||
inline bool operator==(const FullyDefined &, const FullyDefined &) { return true; }
|
||||
Q_DECLARE_METATYPE(FullyDefined)
|
||||
|
||||
class ForwardDeclaredParamClass : public QObject
|
||||
|
|
|
|||
Loading…
Reference in New Issue