summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-08-25 17:41:42 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-03 08:27:44 +0200
commit53fde3c573737592a02c5e15ad4fe253ac3304a4 (patch)
tree9cac35896e789c908c9f4099e5edafc3bcc663ab
parent0e0149c64dc9b4cf46f4e8f01e5680e7ea5372c4 (diff)
Reimplement QSequentialIterable using QMetaSequence
Change-Id: Ie721a5f0caa697c4bf15a81f3762cf79d3c54f5a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--qmake/.prev_CMakeLists.txt1
-rw-r--r--qmake/CMakeLists.txt1
-rw-r--r--qmake/Makefile.unix6
-rw-r--r--qmake/Makefile.win322
-rw-r--r--qmake/qmake.pro2
-rw-r--r--src/corelib/.prev_CMakeLists.txt1
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/kernel/kernel.pri2
-rw-r--r--src/corelib/kernel/qiterable.cpp368
-rw-r--r--src/corelib/kernel/qiterable.h149
-rw-r--r--src/corelib/kernel/qmetatype.cpp21
-rw-r--r--src/corelib/kernel/qmetatype.h230
-rw-r--r--src/corelib/kernel/qvariant.cpp306
-rw-r--r--src/corelib/kernel/qvariant.h49
-rw-r--r--src/tools/bootstrap/.prev_CMakeLists.txt1
-rw-r--r--src/tools/bootstrap/CMakeLists.txt1
-rw-r--r--src/tools/bootstrap/bootstrap.pro1
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp5
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp78
19 files changed, 593 insertions, 632 deletions
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 <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.
+
+ 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<QVariant>())
+ 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<QVariant>())
+ 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 <QtCore/qglobal.h>
+#include <QtCore/qtypeinfo.h>
+#include <QtCore/qmetacontainer.h>
+#include <QtCore/qmetatype.h>
+
+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<class T>
+ QSequentialIterable(const T *p)
+ : m_iterable(p)
+ , m_metaSequence(QMetaSequence::fromContainer<T>())
+ {
+ }
+
+ 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<typename From>
+struct QSequentialIterableConvertFunctor
+{
+ QSequentialIterable operator()(const From &f) const
+ {
+ return QSequentialIterable(&f);
+ }
+};
+
+template<typename T>
+struct SequentialValueTypeIsMetaType<T, true>
+{
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QSequentialIterable>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ QSequentialIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QSequentialIterable>(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<QtMetaTypePrivate::QSequentialIterableImpl>()));
+ qMetaTypeId<QSequentialIterable>()));
if (!f)
return false;
- QtMetaTypePrivate::QSequentialIterableImpl iter;
- (*f)(from, &iter);
- QSequentialIterable list(iter);
+ QSequentialIterable list;
+ (*f)(from, &list);
QVariantList &l = *static_cast<QVariantList *>(to);
l.clear();
l.reserve(list.size());
@@ -1924,20 +1924,15 @@ static bool convertToSequentialIterable(QMetaType fromType, const void *from, vo
QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
if (fromTypeId == QMetaType::QVariantList) {
- i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast<const QVariantList *>(from)));
+ i = QSequentialIterable(reinterpret_cast<const QVariantList *>(from));
return true;
}
if (fromTypeId == QMetaType::QStringList) {
- i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast<const QStringList *>(from)));
+ i = QSequentialIterable(reinterpret_cast<const QStringList *>(from));
return true;
}
else if (fromTypeId == QMetaType::QByteArrayList) {
- i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast<const QByteArrayList *>(from)));
- return true;
- }
- QSequentialIterableImpl impl;
- if (QMetaType::convert(fromType, from, QMetaType::fromType<QtMetaTypePrivate::QSequentialIterableImpl>(), &impl)) {
- i = QSequentialIterable(impl);
+ i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
return true;
}
return false;
@@ -2159,7 +2154,7 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
return true;
if (toTypeId == QVariantList && hasRegisteredConverterFunction(
- fromTypeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))
+ fromTypeId, qMetaTypeId<QSequentialIterable>()))
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<typename Container, typename T = void>
-struct ContainerCapabilitiesImpl
-{
- enum {ContainerCapabilities = 0};
- using appendFunction = void(*)(const void *container, const void *newElement);
- static constexpr const appendFunction appendImpl = nullptr;
-};
-
-template<typename Container>
-struct ContainerCapabilitiesImpl<Container, decltype(std::declval<Container>().push_back(std::declval<typename Container::value_type>()))>
-{
- 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<Container *>(const_cast<void *>(container))->push_back(*static_cast<const typename Container::value_type *>(value)); }
-};
-
-template<typename Container>
-struct ContainerCapabilitiesImpl<Container,
- std::void_t<decltype(std::declval<Container>().insert(std::declval<typename Container::value_type>())),
- decltype(std::declval<typename Container::value_type>() == std::declval<typename Container::value_type>())>>
-{
- 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<Container *>(const_cast<void *>(container))->insert(*static_cast<const typename Container::value_type *>(value)); }
-};
-
-template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
-struct CapabilitiesImpl;
-
-template<typename T>
-struct CapabilitiesImpl<T, std::forward_iterator_tag>
-{ enum { IteratorCapabilities = ForwardCapability }; };
-template<typename T>
-struct CapabilitiesImpl<T, std::bidirectional_iterator_tag>
-{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; };
-template<typename T>
-struct CapabilitiesImpl<T, std::random_access_iterator_tag>
-{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; };
-
-template<typename T>
-struct ContainerAPI : CapabilitiesImpl<T>
-{
- static int size(const T *t) { return int(std::distance(t->begin(), t->end())); }
-};
-
-template<typename T>
-struct ContainerAPI<QList<T>> : CapabilitiesImpl<QList<T>>
-{ static int size(const QList<T> *t) { return t->size(); } };
-
-template<typename T>
-struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
-{ static int size(const std::vector<T> *t) { return int(t->size()); } };
-
-template<typename T>
-struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
-{ static int size(const std::list<T> *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<IteratorCapability>(_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<class T>
- static int sizeImpl(const void *p)
- { return ContainerAPI<T>::size(static_cast<const T*>(p)); }
-
- template<class T>
- static void atImpl(const void *p, int idx, void *dataPtr)
- {
- typename T::const_iterator i = static_cast<const T*>(p)->begin();
- std::advance(i, idx);
- IteratorOwner<typename T::const_iterator>::getData(i, dataPtr);
- }
-
- template<class Container>
- static void moveToImpl(const void *container, void **iterator, Position position)
- {
- auto it = (position == ToBegin) ?
- static_cast<const Container *>(container)->begin() :
- static_cast<const Container *>(container)->end();
- IteratorOwner<typename Container::const_iterator>::assign(iterator, it);
- }
-
-public:
- template<class T> QSequentialIterableImpl(const T*p)
- : _iterable(p)
- , _iterator(nullptr)
- , _metaType(QMetaType::fromType<typename T::value_type>())
- , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities | (0 << 4) | (ContainerCapabilitiesImpl<T>::ContainerCapabilities << (4+3)))
- , _size(sizeImpl<T>)
- , _at(atImpl<T>)
- , _moveTo(moveToImpl<T>)
- , _append(ContainerCapabilitiesImpl<T>::appendImpl)
- , _advance(IteratorOwner<typename T::const_iterator>::advance)
- , _get(IteratorOwner<typename T::const_iterator>::getData)
- , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
- , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
- , _copyIter(IteratorOwner<typename T::const_iterator>::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<typename From>
-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)
@@ -1909,20 +1693,6 @@ inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
namespace QtPrivate {
template<typename T>
- struct SequentialValueTypeIsMetaType<T, true>
- {
- static bool registerConverter(int id)
- {
- const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
- return QMetaType::registerConverter<T, QtMetaTypePrivate::QSequentialIterableImpl>(o);
- }
- return true;
- }
- };
-
- template<typename T>
struct AssociativeValueTypeIsMetaType<T, true>
{
static bool registerConverter(int id)
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
@@ -2581,312 +2581,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
*/
/*!
- \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<QVariant>())
- 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<QVariant>())
- 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
\inmodule QtCore
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<CustomMovable>. 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<MyType>();
- 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<MyType *>(dataPtr) = mytype;
};
- iterator._get = [](void * const *, void *dataPtr) -> void {
+ metaSequence.elementAtConstIteratorFn = [](const void *, void *dataPtr) -> void {
MyType mytype {2, "zwei"};
*static_cast<MyType *>(dataPtr) = mytype;
};
- QSequentialIterable iterable {iterator};
+ metaSequence.valueMetaType = QMetaType::fromType<MyType>();
+
+ QSequentialIterable iterable(QMetaSequence(&metaSequence), nullptr);
QVariant value1 = iterable.at(0);
QVERIFY(value1.canConvert<MyType>());
QCOMPARE(value1.value<MyType>().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<int> container { 1, 2 };
auto variant = QVariant::fromValue(container);
- QVERIFY(variant.canConvert<QtMetaTypePrivate::QSequentialIterableImpl>());
- auto asIterable = variant.value<QtMetaTypePrivate::QSequentialIterableImpl>();
+ QVERIFY(variant.canConvert<QSequentialIterable>());
+ auto asIterable = variant.value<QSequentialIterable>();
const int i = 3, j = 4;
- asIterable.append(&i);
- asIterable.append(&j);
+ void *mutableIterable = const_cast<void *>(asIterable.constIterable());
+ asIterable.metaSequence().addElement(mutableIterable, &i);
+ asIterable.metaSequence().addElement(mutableIterable, &j);
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 1, 2, 3, 4 }));
}
{
QSet<QByteArray> container { QByteArray{"hello"}, QByteArray{"world"} };
auto variant = QVariant::fromValue(std::move(container));
- QVERIFY(variant.canConvert<QtMetaTypePrivate::QSequentialIterableImpl>());
- auto asIterable = variant.value<QtMetaTypePrivate::QSequentialIterableImpl>();
+ QVERIFY(variant.canConvert<QSequentialIterable>());
+ auto asIterable = variant.value<QSequentialIterable>();
QByteArray qba1 {"goodbye"};
QByteArray qba2 { "moon" };
- asIterable.append( &qba1 );
- asIterable.append( &qba2);
+ void *mutableIterable = const_cast<void *>(asIterable.constIterable());
+ asIterable.metaSequence().addElement(mutableIterable, &qba1);
+ asIterable.metaSequence().addElement(mutableIterable, &qba2);
QSet<QByteArray> reference { "hello", "world", "goodbye", "moon" };
QCOMPARE(variant.value<QSet<QByteArray>>(), reference);
}
@@ -4707,8 +4719,8 @@ void tst_QVariant::preferDirectConversionOverInterfaces()
{
using namespace QtMetaTypePrivate;
bool calledCorrectConverter = false;
- QMetaType::registerConverter<MyType, QSequentialIterableImpl>([](const MyType &) {
- return QSequentialIterableImpl {};
+ QMetaType::registerConverter<MyType, QSequentialIterable>([](const MyType &) {
+ return QSequentialIterable {};
});
QMetaType::registerConverter<MyType, QVariantList>([&calledCorrectConverter](const MyType &) {
calledCorrectConverter = true;
@@ -4727,7 +4739,7 @@ void tst_QVariant::preferDirectConversionOverInterfaces()
});
auto holder = QVariant::fromValue(MyType {});
- QVERIFY(holder.canConvert<QSequentialIterableImpl>());
+ QVERIFY(holder.canConvert<QSequentialIterable>());
QVERIFY(holder.canConvert<QVariantList>());
QVERIFY(holder.canConvert<QAssociativeIterableImpl>());
QVERIFY(holder.canConvert<QVariantHash>());