Reimplement QSequentialIterable using QMetaSequence
Change-Id: Ie721a5f0caa697c4bf15a81f3762cf79d3c54f5a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>bb10
parent
0e0149c64d
commit
53fde3c573
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) $<
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ QTOBJS= \
|
|||
qsettings.obj \
|
||||
qvariant.obj \
|
||||
qsettings_win.obj \
|
||||
qiterable.obj \
|
||||
qmetacontainer.obj \
|
||||
qmetatype.obj \
|
||||
qnumeric.obj \
|
||||
qlogging.obj \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
@ -1908,20 +1692,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>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -4528,28 +4528,37 @@ void tst_QVariant::shouldDeleteVariantDataWorksForSequential()
|
|||
{
|
||||
QCOMPARE(instanceCount, 0);
|
||||
{
|
||||
QtMetaTypePrivate::QSequentialIterableImpl iterator {};
|
||||
iterator._iteratorCapabilities = QtMetaTypePrivate::RandomAccessCapability |
|
||||
QtMetaTypePrivate::BiDirectionalCapability |
|
||||
QtMetaTypePrivate::ForwardCapability;
|
||||
QtMetaContainerPrivate::QMetaSequenceInterface metaSequence {};
|
||||
metaSequence.iteratorCapabilities = QtMetaContainerPrivate::RandomAccessCapability
|
||||
| QtMetaContainerPrivate::BiDirectionalCapability
|
||||
| QtMetaContainerPrivate::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 {
|
||||
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>());
|
||||
|
|
|
|||
Loading…
Reference in New Issue