From 53fde3c573737592a02c5e15ad4fe253ac3304a4 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 25 Aug 2020 17:41:42 +0200 Subject: Reimplement QSequentialIterable using QMetaSequence Change-Id: Ie721a5f0caa697c4bf15a81f3762cf79d3c54f5a Reviewed-by: Fabian Kosmale --- qmake/.prev_CMakeLists.txt | 1 + qmake/CMakeLists.txt | 1 + qmake/Makefile.unix | 6 +- qmake/Makefile.win32 | 2 + qmake/qmake.pro | 2 + src/corelib/.prev_CMakeLists.txt | 1 + src/corelib/CMakeLists.txt | 1 + src/corelib/kernel/kernel.pri | 2 + src/corelib/kernel/qiterable.cpp | 368 +++++++++++++++++++++ src/corelib/kernel/qiterable.h | 149 +++++++++ src/corelib/kernel/qmetatype.cpp | 21 +- src/corelib/kernel/qmetatype.h | 230 ------------- src/corelib/kernel/qvariant.cpp | 306 ----------------- src/corelib/kernel/qvariant.h | 49 --- src/tools/bootstrap/.prev_CMakeLists.txt | 1 + src/tools/bootstrap/CMakeLists.txt | 1 + src/tools/bootstrap/bootstrap.pro | 1 + .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 5 + .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 78 +++-- 19 files changed, 593 insertions(+), 632 deletions(-) create mode 100644 src/corelib/kernel/qiterable.cpp create mode 100644 src/corelib/kernel/qiterable.h diff --git a/qmake/.prev_CMakeLists.txt b/qmake/.prev_CMakeLists.txt index 8719a3eb54..8284e9a1ad 100644 --- a/qmake/.prev_CMakeLists.txt +++ b/qmake/.prev_CMakeLists.txt @@ -58,6 +58,7 @@ qt_add_tool(${target_name} ../src/corelib/io/qiodevice.cpp ../src/corelib/io/qiodevice.h ../src/corelib/io/qsettings.cpp ../src/corelib/io/qtemporaryfile.cpp ../src/corelib/io/qtemporaryfile.h + ../src/corelib/kernel/qiterable.cpp ../src/corelib/kernel/qiterable.h ../src/corelib/kernel/qmetacontainer.cpp ../src/corelib/kernel/qmetacontainer.h ../src/corelib/kernel/qmetatype.cpp ../src/corelib/kernel/qmetatype.h ../src/corelib/kernel/qsystemerror.cpp ../src/corelib/kernel/qsystemerror_p.h diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt index fc5d488c49..863ac746c6 100644 --- a/qmake/CMakeLists.txt +++ b/qmake/CMakeLists.txt @@ -66,6 +66,7 @@ qt_add_tool(${target_name} ../src/corelib/io/qiodevice.cpp ../src/corelib/io/qiodevice.h ../src/corelib/io/qsettings.cpp ../src/corelib/io/qtemporaryfile.cpp ../src/corelib/io/qtemporaryfile.h + ../src/corelib/kernel/qiterable.cpp ../src/corelib/kernel/qiterable.h ../src/corelib/kernel/qmetacontainer.cpp ../src/corelib/kernel/qmetacontainer.h ../src/corelib/kernel/qmetatype.cpp ../src/corelib/kernel/qmetatype.h ../src/corelib/kernel/qsystemerror.cpp ../src/corelib/kernel/qsystemerror_p.h diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 822150f246..ea792a7c43 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -25,7 +25,7 @@ QOBJS = \ qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o \ qcborstreamwriter.o qcborvalue.o \ qjsoncbor.o qjsonarray.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \ - qmetacontainer.o qmetatype.o qsystemerror.o qvariant.o \ + qiterable.o qmetacontainer.o qmetatype.o qsystemerror.o qvariant.o \ quuid.o \ qarraydata.o qbitarray.o qbytearray.o qbytearraylist.o qbytearraymatcher.o \ qcalendar.o qgregoriancalendar.o qromancalendar.o \ @@ -96,6 +96,7 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \ $(SOURCE_PATH)/src/corelib/io/qsettings.cpp \ $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp \ + $(SOURCE_PATH)/src/corelib/kernel/qiterable.cpp \ $(SOURCE_PATH)/src/corelib/kernel/qmetacontainer.cpp \ $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \ $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \ @@ -355,6 +356,9 @@ qvsnprintf.o: $(SOURCE_PATH)/src/corelib/text/qvsnprintf.cpp qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/text/qbytearraymatcher.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qiterable.o: $(SOURCE_PATH)/src/corelib/kernel/qiterable.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + qmetacontainer.o: $(SOURCE_PATH)/src/corelib/kernel/qmetacontainer.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 1cd439556f..9f3891bad7 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -114,6 +114,8 @@ QTOBJS= \ qsettings.obj \ qvariant.obj \ qsettings_win.obj \ + qiterable.obj \ + qmetacontainer.obj \ qmetatype.obj \ qnumeric.obj \ qlogging.obj \ diff --git a/qmake/qmake.pro b/qmake/qmake.pro index 9decc10edc..4ff467f5ca 100644 --- a/qmake/qmake.pro +++ b/qmake/qmake.pro @@ -137,6 +137,7 @@ SOURCES += \ qgregoriancalendar.cpp \ qhash.cpp \ qiodevice.cpp \ + qiterable.cpp \ qjsonarray.cpp \ qjsoncbor.cpp \ qjsondocument.cpp \ @@ -195,6 +196,7 @@ HEADERS += \ qgregoriancalendar_p.h \ qhash.h \ qiodevice.h \ + qiterable.h \ qjson_p.h \ qjsonarray.h \ qjsondocument.h \ diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt index 91e73b6c5d..fd88e38a31 100644 --- a/src/corelib/.prev_CMakeLists.txt +++ b/src/corelib/.prev_CMakeLists.txt @@ -80,6 +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/qmath.cpp kernel/qmath.h kernel/qmetacontainer.cpp kernel/qmetacontainer.h kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 8952b3ddcf..15f83ee637 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -103,6 +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/qmath.cpp kernel/qmath.h kernel/qmetacontainer.cpp kernel/qmetacontainer.h kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 420f0222e4..0f158ba981 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -35,6 +35,7 @@ HEADERS += \ kernel/qmetaobjectbuilder_p.h \ kernel/qobject_p.h \ kernel/qcoreglobaldata_p.h \ + kernel/qiterable.h \ kernel/qsharedmemory.h \ kernel/qsharedmemory_p.h \ kernel/qsystemsemaphore.h \ @@ -70,6 +71,7 @@ SOURCES += \ kernel/qtranslator.cpp \ kernel/qvariant.cpp \ kernel/qcoreglobaldata.cpp \ + kernel/qiterable.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ kernel/qpointer.cpp \ diff --git a/src/corelib/kernel/qiterable.cpp b/src/corelib/kernel/qiterable.cpp new file mode 100644 index 0000000000..f1c2512f36 --- /dev/null +++ b/src/corelib/kernel/qiterable.cpp @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +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 elements 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 +*/ + +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)); +} + +/*! + Returns a QSequentialIterable::const_iterator for the end of the container. This + can be used in stl-style iteration. + + \sa begin() +*/ +QSequentialIterable::const_iterator QSequentialIterable::end() const +{ + return const_iterator(this, m_metaSequence.constEnd(m_iterable)); +} + +/*! + Returns the element 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()) + dataPtr = &v; + else + dataPtr = v.data(); + + const QMetaSequence metaSequence = m_metaSequence; + if (metaSequence.canGetElementAtIndex()) { + metaSequence.elementAtIndex(m_iterable, idx, dataPtr); + } else if (metaSequence.canGetElementAtConstIterator()) { + void *iterator = metaSequence.constBegin(m_iterable); + metaSequence.advanceConstIterator(iterator, idx); + metaSequence.elementAtConstIterator(iterator, dataPtr); + metaSequence.destroyConstIterator(iterator); + } + + return v; +} + +/*! + Returns the number of elements in the container. +*/ +qsizetype QSequentialIterable::size() const +{ + const QMetaSequence metaSequence = m_metaSequence; + const void *container = m_iterable; + 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; +} + +/*! + Returns whether it is possible to iterate over the container in reverse. This + corresponds to the std::bidirectional_iterator_tag iterator trait of the + const_iterator of the container. +*/ +bool QSequentialIterable::canReverseIterate() const +{ + return m_metaSequence.hasBidirectionalIterator(); +} + +/*! + \class QSequentialIterable::const_iterator + \since 5.2 + \inmodule QtCore + \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant. + + 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 +*/ + + +/*! + Destroys the QSequentialIterable::const_iterator. +*/ +QSequentialIterable::const_iterator::~const_iterator() { + if (!m_ref->deref()) { + m_iterable->m_metaSequence.destroyConstIterator(m_iterator); + delete m_ref; + } +} + +/*! + Creates a copy of \a other. +*/ +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()) + dataPtr = &v; + else + dataPtr = v.data(); + m_iterable->m_metaSequence.elementAtConstIterator(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); +} + +/*! + 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); +} + +/*! + The prefix ++ operator (\c{++it}) advances the iterator to the + next item in the container and returns an iterator to the new current + item. + + Calling this function on QSequentialIterable::end() leads to undefined results. + + \sa operator--() +*/ +QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++() +{ + m_iterable->m_metaSequence.advanceConstIterator(m_iterator, 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. +*/ +QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int) +{ + const_iterator result( + m_iterable, + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); + m_iterable->m_metaSequence.advanceConstIterator(m_iterator, 1); + return result; +} + +/*! + 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() +*/ +QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--() +{ + m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -1); + return *this; +} + +/*! + \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() +*/ +QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int) +{ + const_iterator result( + m_iterable, + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); + m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -1); + return result; +} + +/*! + 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; +} + +/*! + 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() +*/ +QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j) +{ + m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -j); + return *this; +} + +/*! + 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)); + m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); + m_iterable->m_metaSequence.advanceConstIterator(result.m_iterator, j); + return result; +} + +/*! + 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() +*/ +QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const +{ + const_iterator result( + m_iterable, + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); + m_iterable->m_metaSequence.advanceConstIterator(result.m_iterator, -j); + return result; +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qiterable.h b/src/corelib/kernel/qiterable.h new file mode 100644 index 0000000000..9498dbde79 --- /dev/null +++ b/src/corelib/kernel/qiterable.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** 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_H +#define QITERABLE_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QSequentialIterable +{ + uint m_revision = 0; + const void *m_iterable = nullptr; + QMetaSequence m_metaSequence; + +public: + struct Q_CORE_EXPORT const_iterator + { + private: + const QSequentialIterable *m_iterable = nullptr; + void *m_iterator = nullptr; + QAtomicInt *m_ref = nullptr; + + friend class QSequentialIterable; + explicit const_iterator(const QSequentialIterable *iterable, void *iterator); + + public: + ~const_iterator(); + + const_iterator(const const_iterator &other); + + const_iterator& operator=(const const_iterator &other); + + const QVariant operator*() const; + bool operator==(const const_iterator &o) const; + bool operator!=(const const_iterator &o) const; + const_iterator &operator++(); + const_iterator operator++(int); + const_iterator &operator--(); + const_iterator operator--(int); + const_iterator &operator+=(int j); + const_iterator &operator-=(int j); + const_iterator operator+(int j) const; + const_iterator operator-(int j) const; + friend inline const_iterator operator+(int j, const const_iterator &k) { return k + j; } + }; + + friend struct const_iterator; + + template + QSequentialIterable(const T *p) + : m_iterable(p) + , m_metaSequence(QMetaSequence::fromContainer()) + { + } + + QSequentialIterable() = default; + + QSequentialIterable(const QMetaSequence &metaSequence, const void *iterable) + : m_iterable(iterable) + , m_metaSequence(metaSequence) + { + } + + const_iterator begin() const; + const_iterator end() const; + + QVariant at(qsizetype idx) const; + qsizetype size() const; + + bool canReverseIterate() const; + + const void *constIterable() const { return m_iterable; } + QMetaSequence metaSequence() const { return m_metaSequence; } +}; + +namespace QtPrivate { + +template +struct QSequentialIterableConvertFunctor +{ + QSequentialIterable operator()(const From &f) const + { + return QSequentialIterable(&f); + } +}; + +template +struct SequentialValueTypeIsMetaType +{ + static bool registerConverter(int id) + { + const int toId = qMetaTypeId(); + if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { + QSequentialIterableConvertFunctor o; + return QMetaType::registerConverter(o); + } + return true; + } +}; + +} + +Q_DECLARE_TYPEINFO(QSequentialIterable, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif // QITERABLE_H diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 95557bf021..964901fc48 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -54,6 +54,7 @@ #include "quuid.h" #include "qvariant.h" #include "qdatastream.h" +#include "qiterable.h" #if QT_CONFIG(regularexpression) # include "qregularexpression.h" @@ -1832,13 +1833,12 @@ static bool convertIterableToVariantList(QMetaType fromType, const void *from, v { const QMetaType::ConverterFunction * const f = customTypesConversionRegistry()->function(qMakePair(fromType.id(), - qMetaTypeId())); + qMetaTypeId())); if (!f) return false; - QtMetaTypePrivate::QSequentialIterableImpl iter; - (*f)(from, &iter); - QSequentialIterable list(iter); + QSequentialIterable list; + (*f)(from, &list); QVariantList &l = *static_cast(to); l.clear(); l.reserve(list.size()); @@ -1924,20 +1924,15 @@ static bool convertToSequentialIterable(QMetaType fromType, const void *from, vo QSequentialIterable &i = *static_cast(to); if (fromTypeId == QMetaType::QVariantList) { - i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast(from))); + i = QSequentialIterable(reinterpret_cast(from)); return true; } if (fromTypeId == QMetaType::QStringList) { - i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast(from))); + i = QSequentialIterable(reinterpret_cast(from)); return true; } else if (fromTypeId == QMetaType::QByteArrayList) { - i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast(from))); - return true; - } - QSequentialIterableImpl impl; - if (QMetaType::convert(fromType, from, QMetaType::fromType(), &impl)) { - i = QSequentialIterable(impl); + i = QSequentialIterable(reinterpret_cast(from)); return true; } return false; @@ -2159,7 +2154,7 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType) return true; if (toTypeId == QVariantList && hasRegisteredConverterFunction( - fromTypeId, qMetaTypeId())) + fromTypeId, qMetaTypeId())) return true; if ((toTypeId == QVariantHash || toTypeId == QVariantMap) && hasRegisteredConverterFunction( diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 06a3241062..4ad2885bed 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -694,221 +694,6 @@ public: } }; -enum IteratorCapability -{ - ForwardCapability = 1, - BiDirectionalCapability = 2, - RandomAccessCapability = 4 -}; - -enum ContainerCapability -{ - ContainerIsAppendable = 1 -}; - -template -struct ContainerCapabilitiesImpl -{ - enum {ContainerCapabilities = 0}; - using appendFunction = void(*)(const void *container, const void *newElement); - static constexpr const appendFunction appendImpl = nullptr; -}; - -template -struct ContainerCapabilitiesImpl().push_back(std::declval()))> -{ - enum {ContainerCapabilities = ContainerIsAppendable}; - - // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl - // pointed to a const object to begin with - static void appendImpl(const void *container, const void *value) - { static_cast(const_cast(container))->push_back(*static_cast(value)); } -}; - -template -struct ContainerCapabilitiesImpl().insert(std::declval())), - decltype(std::declval() == std::declval())>> -{ - enum {ContainerCapabilities = ContainerIsAppendable}; - - // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl - // pointed to a const object to begin with - static void appendImpl(const void *container, const void *value) - { static_cast(const_cast(container))->insert(*static_cast(value)); } -}; - -template::iterator_category> -struct CapabilitiesImpl; - -template -struct CapabilitiesImpl -{ enum { IteratorCapabilities = ForwardCapability }; }; -template -struct CapabilitiesImpl -{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; }; -template -struct CapabilitiesImpl -{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; }; - -template -struct ContainerAPI : CapabilitiesImpl -{ - static int size(const T *t) { return int(std::distance(t->begin(), t->end())); } -}; - -template -struct ContainerAPI> : CapabilitiesImpl> -{ static int size(const QList *t) { return t->size(); } }; - -template -struct ContainerAPI > : CapabilitiesImpl > -{ static int size(const std::vector *t) { return int(t->size()); } }; - -template -struct ContainerAPI > : CapabilitiesImpl > -{ static int size(const std::list *t) { return int(t->size()); } }; - -/* - revision 0: _iteratorCapabilties is treated as a bitfield, the remaining bits are used to introduce - _revision, _containerCapabilities and _unused. The latter contains 21 bits that are - not used yet -*/ -class QSequentialIterableImpl -{ -public: - const void * _iterable; - void *_iterator; - QMetaType _metaType; - uint _iteratorCapabilities; - // Iterator capabilities looks actually like - // uint _iteratorCapabilities:4; - // uint _revision:3; - // uint _containerCapabilities:4; - // uint _unused:21; - typedef int(*sizeFunc)(const void *p); - typedef void (*atFunc)(const void *p, int, void *); - enum Position { ToBegin, ToEnd }; - typedef void (*moveIteratorFunc)(const void *p, void **, Position position); - 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 *); - typedef void(*appendFunction)(const void *container, const void *newElement); - - IteratorCapability iteratorCapabilities() {return static_cast(_iteratorCapabilities & 0xF);} - uint revision() {return _iteratorCapabilities >> 4 & 0x7;} - uint containerCapabilities() {return _iteratorCapabilities >> 7 & 0xF;} - - sizeFunc _size; - atFunc _at; - moveIteratorFunc _moveTo; - appendFunction _append; - advanceFunc _advance; - getFunc _get; - destroyIterFunc _destroyIter; - equalIterFunc _equalIter; - copyIterFunc _copyIter; - - template - static int sizeImpl(const void *p) - { return ContainerAPI::size(static_cast(p)); } - - template - static void atImpl(const void *p, int idx, void *dataPtr) - { - typename T::const_iterator i = static_cast(p)->begin(); - std::advance(i, idx); - IteratorOwner::getData(i, dataPtr); - } - - template - static void moveToImpl(const void *container, void **iterator, Position position) - { - auto it = (position == ToBegin) ? - static_cast(container)->begin() : - static_cast(container)->end(); - IteratorOwner::assign(iterator, it); - } - -public: - template QSequentialIterableImpl(const T*p) - : _iterable(p) - , _iterator(nullptr) - , _metaType(QMetaType::fromType()) - , _iteratorCapabilities(ContainerAPI::IteratorCapabilities | (0 << 4) | (ContainerCapabilitiesImpl::ContainerCapabilities << (4+3))) - , _size(sizeImpl) - , _at(atImpl) - , _moveTo(moveToImpl) - , _append(ContainerCapabilitiesImpl::appendImpl) - , _advance(IteratorOwner::advance) - , _get(IteratorOwner::getData) - , _destroyIter(IteratorOwner::destroy) - , _equalIter(IteratorOwner::equal) - , _copyIter(IteratorOwner::assign) - { - } - - QSequentialIterableImpl() - : _iterable(nullptr) - , _iterator(nullptr) - , _iteratorCapabilities(0 | (0 << 4) ) // no iterator capabilities, revision 0 - , _size(nullptr) - , _at(nullptr) - , _moveTo(nullptr) - , _append(nullptr) - , _advance(nullptr) - , _get(nullptr) - , _destroyIter(nullptr) - , _equalIter(nullptr) - , _copyIter(nullptr) - { - } - - inline void moveToBegin() { - _moveTo(_iterable, &_iterator, ToBegin); - } - inline void moveToEnd() { - _moveTo(_iterable, &_iterator, ToEnd); - } - inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); } - inline QSequentialIterableImpl &advance(int i) { - Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability); - _advance(&_iterator, i); - return *this; - } - - inline void append(const void *newElement) { - if (containerCapabilities() & ContainerIsAppendable) - _append(_iterable, newElement); - } - - inline void getCurrent(void *dataPtr) const { _get(&_iterator, dataPtr); } - - void at(int idx, void *dataPtr) const - { return _at(_iterable, idx, dataPtr); } - - int size() const { Q_ASSERT(_iterable); return _size(_iterable); } - - inline void destroyIter() { _destroyIter(&_iterator); } - - void copy(const QSequentialIterableImpl &other) - { - *this = other; - _copyIter(&_iterator, &other._iterator); - } -}; -QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QSequentialIterableImpl, Q_MOVABLE_TYPE) - -template -struct QSequentialIterableConvertFunctor -{ - QSequentialIterableImpl operator()(const From &f) const - { - return QSequentialIterableImpl(&f); - } -}; } namespace QtMetaTypePrivate { @@ -1890,7 +1675,6 @@ QT_END_NAMESPACE QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE) -Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl) Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl) Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl) @@ -1908,20 +1692,6 @@ inline bool QtPrivate::IsMetaTypePair::registerConverter(int id) } namespace QtPrivate { - template - struct SequentialValueTypeIsMetaType - { - static bool registerConverter(int id) - { - const int toId = qMetaTypeId(); - if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { - QtMetaTypePrivate::QSequentialIterableConvertFunctor o; - return QMetaType::registerConverter(o); - } - return true; - } - }; - template struct AssociativeValueTypeIsMetaType { diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 0805456e26..e052e3bd34 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2580,312 +2580,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \internal */ -/*! - \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 elements 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 -*/ - -/*! - \internal -*/ -QSequentialIterable::QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl) - : m_impl(impl) -{ -} - -QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable &iter, QAtomicInt *ref) - : m_impl(iter.m_impl), m_ref(ref) -{ - m_ref->ref(); -} - -QSequentialIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref) - : m_impl(impl), m_ref(ref) -{ - 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 -{ - const_iterator it(*this, new QAtomicInt(0)); - it.m_impl.moveToBegin(); - return it; -} - -/*! - Returns a QSequentialIterable::const_iterator for the end of the container. This - can be used in stl-style iteration. - - \sa begin() -*/ -QSequentialIterable::const_iterator QSequentialIterable::end() const -{ - const_iterator it(*this, new QAtomicInt(0)); - it.m_impl.moveToEnd(); - return it; -} - -/*! - Returns the element at position \a idx in the container. -*/ -QVariant QSequentialIterable::at(int idx) const -{ - QVariant v(m_impl._metaType); - void *dataPtr; - if (m_impl._metaType == QMetaType::fromType()) - dataPtr = &v; - else - dataPtr = v.data(); - m_impl.at(idx, dataPtr); - return v; -} - -/*! - Returns the number of elements in the container. -*/ -int QSequentialIterable::size() const -{ - return m_impl.size(); -} - -/*! - 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_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability; -} - -/*! - \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 -*/ - - -/*! - Destroys the QSequentialIterable::const_iterator. -*/ -QSequentialIterable::const_iterator::~const_iterator() { - if (!m_ref->deref()) { - m_impl.destroyIter(); - delete m_ref; - } -} - -/*! - Creates a copy of \a other. -*/ -QSequentialIterable::const_iterator::const_iterator(const const_iterator &other) - : m_impl(other.m_impl), m_ref(other.m_ref) -{ - m_ref->ref(); -} - -/*! - Assigns \a other to this. -*/ -QSequentialIterable::const_iterator& -QSequentialIterable::const_iterator::operator=(const const_iterator &other) -{ - other.m_ref->ref(); - if (!m_ref->deref()) { - m_impl.destroyIter(); - delete m_ref; - } - m_impl = other.m_impl; - 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_impl._metaType); - void *dataPtr; - if (m_impl._metaType == QMetaType::fromType()) - dataPtr = &v; - else - dataPtr = v.data(); - m_impl.getCurrent(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_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 QSequentialIterable::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 QSequentialIterable::end() leads to undefined results. - - \sa operator--() -*/ -QSequentialIterable::const_iterator &QSequentialIterable::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. -*/ -QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int) -{ - QtMetaTypePrivate::QSequentialIterableImpl 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 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() -*/ -QSequentialIterable::const_iterator &QSequentialIterable::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. - - If the container in the QVariant does not support bi-directional iteration, calling this function - leads to undefined results. - - \sa canReverseIterate() -*/ -QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int) -{ - QtMetaTypePrivate::QSequentialIterableImpl 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+() -*/ -QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j) -{ - m_impl.advance(j); - return *this; -} - -/*! - 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() -*/ -QSequentialIterable::const_iterator &QSequentialIterable::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+=() -*/ -QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const -{ - QtMetaTypePrivate::QSequentialIterableImpl 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. - - If the container in the QVariant does not support bi-directional iteration, calling this function - leads to undefined results. - - \sa operator+(), operator-=(), canReverseIterate() -*/ -QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const -{ - QtMetaTypePrivate::QSequentialIterableImpl impl; - impl.copy(m_impl); - impl.advance(-j); - return const_iterator(impl, new QAtomicInt(0)); -} - /*! \class QAssociativeIterable \since 5.2 diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 6080c25f0d..7d01911333 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -581,55 +581,6 @@ inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) #endif Q_DECLARE_SHARED(QVariant) -class Q_CORE_EXPORT QSequentialIterable -{ - QtMetaTypePrivate::QSequentialIterableImpl m_impl; -public: - struct Q_CORE_EXPORT const_iterator - { - private: - QtMetaTypePrivate::QSequentialIterableImpl m_impl; - QAtomicInt *m_ref; - friend class QSequentialIterable; - explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref); - - explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref); - - public: - ~const_iterator(); - - const_iterator(const const_iterator &other); - - const_iterator& operator=(const const_iterator &other); - - const QVariant operator*() const; - bool operator==(const const_iterator &o) const; - bool operator!=(const const_iterator &o) const; - const_iterator &operator++(); - const_iterator operator++(int); - const_iterator &operator--(); - const_iterator operator--(int); - const_iterator &operator+=(int j); - const_iterator &operator-=(int j); - const_iterator operator+(int j) const; - const_iterator operator-(int j) const; - friend inline const_iterator operator+(int j, const const_iterator &k) { return k + j; } - }; - - friend struct const_iterator; - - explicit QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl); - QSequentialIterable() {} - - const_iterator begin() const; - const_iterator end() const; - - QVariant at(int idx) const; - int size() const; - - bool canReverseIterate() const; -}; - class Q_CORE_EXPORT QAssociativeIterable { QtMetaTypePrivate::QAssociativeIterableImpl m_impl; diff --git a/src/tools/bootstrap/.prev_CMakeLists.txt b/src/tools/bootstrap/.prev_CMakeLists.txt index a4bb4f6aac..d66ef7a6a1 100644 --- a/src/tools/bootstrap/.prev_CMakeLists.txt +++ b/src/tools/bootstrap/.prev_CMakeLists.txt @@ -75,6 +75,7 @@ qt_add_module(Bootstrap ../../corelib/io/qurlrecode.cpp ../../corelib/kernel/qcoreapplication.cpp ../../corelib/kernel/qcoreglobaldata.cpp + ../../corelib/kernel/qiterable.cpp ../../corelib/kernel/qmetacontainer.cpp ../../corelib/kernel/qmetatype.cpp ../../corelib/kernel/qsharedmemory.cpp diff --git a/src/tools/bootstrap/CMakeLists.txt b/src/tools/bootstrap/CMakeLists.txt index f5b1c38c39..272cd92128 100644 --- a/src/tools/bootstrap/CMakeLists.txt +++ b/src/tools/bootstrap/CMakeLists.txt @@ -76,6 +76,7 @@ qt_extend_target(Bootstrap ../../corelib/io/qurlrecode.cpp ../../corelib/kernel/qcoreapplication.cpp ../../corelib/kernel/qcoreglobaldata.cpp + ../../corelib/kernel/qiterable.cpp ../../corelib/kernel/qmetacontainer.cpp ../../corelib/kernel/qmetatype.cpp ../../corelib/kernel/qsharedmemory.cpp diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 1853ab74b4..c9277735c8 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -62,6 +62,7 @@ SOURCES += \ ../../corelib/io/qurlrecode.cpp \ ../../corelib/kernel/qcoreapplication.cpp \ ../../corelib/kernel/qcoreglobaldata.cpp \ + ../../corelib/kernel/qiterable.cpp \ ../../corelib/kernel/qmetacontainer.cpp \ ../../corelib/kernel/qmetatype.cpp \ ../../corelib/kernel/qvariant.cpp \ diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index ba8c42f22f..05fffd928a 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -1000,6 +1000,11 @@ void tst_QMetaType::alignOf() } struct CustomMovable { CustomMovable() {} }; + +// needed for QSet. We actually check that it makes sense. +bool operator==(const CustomMovable &, const CustomMovable &) { return true; } +qsizetype qHash(const CustomMovable &, qsizetype seed = 0) { return seed; } + #if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501 QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(CustomMovable, Q_MOVABLE_TYPE); diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 8796589df3..75a72f0c92 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -4528,28 +4528,37 @@ void tst_QVariant::shouldDeleteVariantDataWorksForSequential() { QCOMPARE(instanceCount, 0); { - QtMetaTypePrivate::QSequentialIterableImpl iterator {}; - iterator._iteratorCapabilities = QtMetaTypePrivate::RandomAccessCapability | - QtMetaTypePrivate::BiDirectionalCapability | - QtMetaTypePrivate::ForwardCapability; - - iterator._size = [](const void *) {return 1;}; - iterator._metaType = QMetaType::fromType(); - iterator._moveTo = [](const void *, void **, QtMetaTypePrivate::QSequentialIterableImpl::Position) {}; - iterator._append = [](const void *, const void *) {}; - iterator._advance = [](void **, int) {}; - iterator._destroyIter = [](void **){}; - iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/}; - iterator._destroyIter = [](void **){}; - iterator._at = [](const void *, int, void *dataPtr) -> void { + QtMetaContainerPrivate::QMetaSequenceInterface metaSequence {}; + metaSequence.iteratorCapabilities = QtMetaContainerPrivate::RandomAccessCapability + | QtMetaContainerPrivate::BiDirectionalCapability + | QtMetaContainerPrivate::ForwardCapability; + + metaSequence.sizeFn = [](const void *) { return qsizetype(1); }; + metaSequence.createConstIteratorFn = + [](const void *, QtMetaContainerPrivate::QMetaSequenceInterface::Position) -> void* { + return nullptr; + }; + metaSequence.addElementFn = [](void *, const void *) {}; + metaSequence.advanceConstIteratorFn = [](void *, qsizetype) {}; + metaSequence.destroyConstIteratorFn = [](const void *){}; + metaSequence.compareConstIteratorFn = [](const void *, const void *) { + return true; // all iterators are nullptr + }; + metaSequence.copyConstIteratorFn = [](void *, const void *){}; + metaSequence.diffConstIteratorFn = [](const void *, const void *) -> qsizetype { + return 0; + }; + metaSequence.elementAtIndexFn = [](const void *, qsizetype, void *dataPtr) -> void { MyType mytype {1, "eins"}; *static_cast(dataPtr) = mytype; }; - iterator._get = [](void * const *, void *dataPtr) -> void { + metaSequence.elementAtConstIteratorFn = [](const void *, void *dataPtr) -> void { MyType mytype {2, "zwei"}; *static_cast(dataPtr) = mytype; }; - QSequentialIterable iterable {iterator}; + metaSequence.valueMetaType = QMetaType::fromType(); + + QSequentialIterable iterable(QMetaSequence(&metaSequence), nullptr); QVariant value1 = iterable.at(0); QVERIFY(value1.canConvert()); QCOMPARE(value1.value().number, 1); @@ -4669,12 +4678,13 @@ void tst_QVariant::qt4UuidDataStream() void tst_QVariant::sequentialIterableEndianessSanityCheck() { - namespace QMTP = QtMetaTypePrivate; - uint oldIteratorCaps = QMTP::ForwardCapability | QMTP::BiDirectionalCapability | QMTP::RandomAccessCapability; - QMTP::QSequentialIterableImpl seqImpl {}; - QCOMPARE(seqImpl.revision(), 0u); - memcpy(&seqImpl._iteratorCapabilities, &oldIteratorCaps, sizeof(oldIteratorCaps)); - QCOMPARE(seqImpl.revision(), 0u); + namespace QMTP = QtMetaContainerPrivate; + QMTP::IteratorCapabilities oldIteratorCaps + = QMTP::ForwardCapability | QMTP::BiDirectionalCapability | QMTP::RandomAccessCapability; + QMTP::QMetaSequenceInterface seqImpl {}; + QCOMPARE(seqImpl.revision, 0u); + memcpy(&seqImpl.iteratorCapabilities, &oldIteratorCaps, sizeof(oldIteratorCaps)); + QCOMPARE(seqImpl.revision, 0u); } void tst_QVariant::sequentialIterableAppend() @@ -4682,22 +4692,24 @@ void tst_QVariant::sequentialIterableAppend() { QList container { 1, 2 }; auto variant = QVariant::fromValue(container); - QVERIFY(variant.canConvert()); - auto asIterable = variant.value(); + QVERIFY(variant.canConvert()); + auto asIterable = variant.value(); const int i = 3, j = 4; - asIterable.append(&i); - asIterable.append(&j); + void *mutableIterable = const_cast(asIterable.constIterable()); + asIterable.metaSequence().addElement(mutableIterable, &i); + asIterable.metaSequence().addElement(mutableIterable, &j); QCOMPARE(variant.value>(), QList ({ 1, 2, 3, 4 })); } { QSet container { QByteArray{"hello"}, QByteArray{"world"} }; auto variant = QVariant::fromValue(std::move(container)); - QVERIFY(variant.canConvert()); - auto asIterable = variant.value(); + QVERIFY(variant.canConvert()); + auto asIterable = variant.value(); QByteArray qba1 {"goodbye"}; QByteArray qba2 { "moon" }; - asIterable.append( &qba1 ); - asIterable.append( &qba2); + void *mutableIterable = const_cast(asIterable.constIterable()); + asIterable.metaSequence().addElement(mutableIterable, &qba1); + asIterable.metaSequence().addElement(mutableIterable, &qba2); QSet reference { "hello", "world", "goodbye", "moon" }; QCOMPARE(variant.value>(), reference); } @@ -4707,8 +4719,8 @@ void tst_QVariant::preferDirectConversionOverInterfaces() { using namespace QtMetaTypePrivate; bool calledCorrectConverter = false; - QMetaType::registerConverter([](const MyType &) { - return QSequentialIterableImpl {}; + QMetaType::registerConverter([](const MyType &) { + return QSequentialIterable {}; }); QMetaType::registerConverter([&calledCorrectConverter](const MyType &) { calledCorrectConverter = true; @@ -4727,7 +4739,7 @@ void tst_QVariant::preferDirectConversionOverInterfaces() }); auto holder = QVariant::fromValue(MyType {}); - QVERIFY(holder.canConvert()); + QVERIFY(holder.canConvert()); QVERIFY(holder.canConvert()); QVERIFY(holder.canConvert()); QVERIFY(holder.canConvert()); -- cgit v1.2.3