Add a QMetaSequence interface
This is in line with QMetaType and will be used to implement a mutable QSequentialIterable. Later on, a QMetaAssociation will be added as well, to implement a mutable QAssociativeIterable. The code here represents the minimal set of functionality needed to have a practical sequential container. The functionality is not completely orthogonal. In particular, the index based operations could be implemented in terms of iterator-based operations. Task-number: QTBUG-81716 Change-Id: Ibd41eb7db248a774673c701549d9a03cbf2e48b6 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
83ad54c124
commit
4fbb2f66d6
@ -38,6 +38,7 @@ qt_add_tool(${target_name}
|
||||
../src/3rdparty/pcre2/src/pcre2_ucp.h
|
||||
../src/3rdparty/pcre2/src/pcre2_valid_utf.c
|
||||
../src/3rdparty/pcre2/src/pcre2_xclass.c
|
||||
../src/corelib/global/qcontainerinfo.h
|
||||
../src/corelib/global/qglobal.cpp ../src/corelib/global/qglobal.h
|
||||
../src/corelib/global/qlibraryinfo.cpp
|
||||
../src/corelib/global/qlogging.cpp
|
||||
@ -57,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/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
|
||||
../src/corelib/kernel/qvariant.cpp
|
||||
|
@ -41,6 +41,7 @@ qt_add_tool(${target_name}
|
||||
../src/3rdparty/pcre2/src/pcre2_ucp.h
|
||||
../src/3rdparty/pcre2/src/pcre2_valid_utf.c
|
||||
../src/3rdparty/pcre2/src/pcre2_xclass.c
|
||||
../src/corelib/global/qcontainerinfo.h
|
||||
../src/corelib/global/qendian.cpp # special case
|
||||
../src/corelib/global/qglobal.cpp ../src/corelib/global/qglobal.h
|
||||
../src/corelib/global/qlibraryinfo.cpp
|
||||
@ -65,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/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
|
||||
../src/corelib/kernel/qvariant.cpp
|
||||
|
@ -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 \
|
||||
qmetatype.o qsystemerror.o qvariant.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/qmetacontainer.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
|
||||
@ -354,6 +355,9 @@ qvsnprintf.o: $(SOURCE_PATH)/src/corelib/text/qvsnprintf.cpp
|
||||
qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/text/qbytearraymatcher.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qmetacontainer.o: $(SOURCE_PATH)/src/corelib/kernel/qmetacontainer.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
|
@ -148,6 +148,7 @@ SOURCES += \
|
||||
qlocale_tools.cpp \
|
||||
qlogging.cpp \
|
||||
qmalloc.cpp \
|
||||
qmetacontainer.cpp \
|
||||
qmetatype.cpp \
|
||||
qnumeric.cpp \
|
||||
qregularexpression.cpp \
|
||||
@ -181,6 +182,7 @@ HEADERS += \
|
||||
qcborvalue.h \
|
||||
qcborvalue_p.h \
|
||||
qchar.h \
|
||||
qcontainerinfo.h \
|
||||
qcryptographichash.h \
|
||||
qdatetime.h \
|
||||
qdatetime_p.h \
|
||||
@ -204,6 +206,7 @@ HEADERS += \
|
||||
qlocale.h \
|
||||
qlocale_tools_p.h \
|
||||
qmap.h \
|
||||
qmetacontainer.h \
|
||||
qmetatype.h \
|
||||
qnumeric.h \
|
||||
qregularexpression.h \
|
||||
|
@ -11,6 +11,7 @@ qt_add_module(Core
|
||||
SOURCES
|
||||
global/archdetect.cpp
|
||||
global/qcompilerdetection.h
|
||||
global/qcontainerinfo.h
|
||||
global/qendian.cpp global/qendian.h global/qendian_p.h
|
||||
global/qflags.h
|
||||
global/qfloat16.cpp global/qfloat16.h
|
||||
@ -80,6 +81,7 @@ qt_add_module(Core
|
||||
kernel/qeventloop.cpp kernel/qeventloop.h
|
||||
kernel/qfunctions_p.h
|
||||
kernel/qmath.cpp kernel/qmath.h
|
||||
kernel/qmetacontainer.cpp kernel/qmetacontainer.h
|
||||
kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h
|
||||
kernel/qmetaobject_moc_p.h
|
||||
kernel/qmetaobjectbuilder.cpp kernel/qmetaobjectbuilder_p.h
|
||||
|
@ -33,6 +33,7 @@ qt_add_module(Core
|
||||
SOURCES
|
||||
global/archdetect.cpp
|
||||
global/qcompilerdetection.h
|
||||
global/qcontainerinfo.h
|
||||
global/qendian.cpp global/qendian.h global/qendian_p.h
|
||||
global/qflags.h
|
||||
global/qfloat16.cpp global/qfloat16.h
|
||||
@ -103,6 +104,7 @@ qt_add_module(Core
|
||||
kernel/qeventloop.cpp kernel/qeventloop.h
|
||||
kernel/qfunctions_p.h
|
||||
kernel/qmath.cpp kernel/qmath.h
|
||||
kernel/qmetacontainer.cpp kernel/qmetacontainer.h
|
||||
kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h
|
||||
kernel/qmetaobject_moc_p.h
|
||||
kernel/qmetaobjectbuilder.cpp kernel/qmetaobjectbuilder_p.h
|
||||
|
@ -6,6 +6,7 @@ HEADERS += \
|
||||
global/qoperatingsystemversion_p.h \
|
||||
global/qsystemdetection.h \
|
||||
global/qcompilerdetection.h \
|
||||
global/qcontainerinfo.h \
|
||||
global/qprocessordetection.h \
|
||||
global/qmemory_p.h \
|
||||
global/qnamespace.h \
|
||||
|
150
src/corelib/global/qcontainerinfo.h
Normal file
150
src/corelib/global/qcontainerinfo.h
Normal file
@ -0,0 +1,150 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 QCONTAINERINFO_H
|
||||
#define QCONTAINERINFO_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <type_traits>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QContainerTraits
|
||||
{
|
||||
|
||||
template<typename C>
|
||||
using value_type = typename C::value_type;
|
||||
|
||||
template<typename C>
|
||||
using iterator = typename C::iterator;
|
||||
|
||||
template<typename C>
|
||||
using const_iterator = typename C::const_iterator;
|
||||
|
||||
// Some versions of Apple clang warn about the constexpr variables below being unused.
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_CLANG("-Wunused-const-variable")
|
||||
|
||||
template<typename C, typename = void>
|
||||
constexpr bool has_size_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_size_v<C, std::void_t<decltype(C().size())>> = true;
|
||||
|
||||
template<typename C, typename = void>
|
||||
constexpr bool has_clear_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_clear_v<C, std::void_t<decltype(C().clear())>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_at_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_at_v<C, std::void_t<decltype(C().at(0))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool can_get_at_index_v = false;
|
||||
template<typename C>
|
||||
constexpr bool can_get_at_index_v<C, std::void_t<value_type<C>(decltype(C()[0]))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool can_set_at_index_v = false;
|
||||
template<typename C>
|
||||
constexpr bool can_set_at_index_v<C, std::void_t<decltype(C()[0] = value_type<C>())>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_push_front_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_push_front_v<C, std::void_t<decltype(C().push_front(value_type<C>()))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_push_back_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_push_back_v<C, std::void_t<decltype(C().push_back(value_type<C>()))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_insert_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_insert_v<C, std::void_t<decltype(C().insert(value_type<C>()))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_pop_front_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_pop_front_v<C, std::void_t<decltype(C().pop_front())>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_pop_back_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_pop_back_v<C, std::void_t<decltype(C().pop_back())>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_iterator_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_iterator_v<C, std::void_t<iterator<C>>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool has_const_iterator_v = false;
|
||||
template<typename C>
|
||||
constexpr bool has_const_iterator_v<C, std::void_t<const_iterator<C>>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool can_get_at_iterator_v = false;
|
||||
template<typename C>
|
||||
constexpr bool can_get_at_iterator_v<C, std::void_t<value_type<C>(decltype(*C().begin()))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool can_set_at_iterator_v = false;
|
||||
template<typename C>
|
||||
constexpr bool can_set_at_iterator_v<C, std::void_t<decltype(*C().begin() = value_type<C>())>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool can_insert_at_iterator_v = false;
|
||||
template<typename C>
|
||||
constexpr bool can_insert_at_iterator_v<C, std::void_t<decltype(C().insert(C().begin(), value_type<C>()))>> = true;
|
||||
|
||||
template<typename, typename = void>
|
||||
constexpr bool can_erase_at_iterator_v = false;
|
||||
template<typename C>
|
||||
constexpr bool can_erase_at_iterator_v<C, std::void_t<decltype(C().erase(C().begin()))>> = true;
|
||||
|
||||
QT_WARNING_POP
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCONTAINERINFO_H
|
@ -12,6 +12,7 @@ HEADERS += \
|
||||
kernel/qcorecmdlineargs_p.h \
|
||||
kernel/qcoreapplication.h \
|
||||
kernel/qcoreevent.h \
|
||||
kernel/qmetacontainer.h \
|
||||
kernel/qmetaobject.h \
|
||||
kernel/qmetatype.h \
|
||||
kernel/qmimedata.h \
|
||||
@ -56,6 +57,7 @@ SOURCES += \
|
||||
kernel/qeventloop.cpp \
|
||||
kernel/qcoreapplication.cpp \
|
||||
kernel/qcoreevent.cpp \
|
||||
kernel/qmetacontainer.cpp \
|
||||
kernel/qmetaobject.cpp \
|
||||
kernel/qmetatype.cpp \
|
||||
kernel/qmetaobjectbuilder.cpp \
|
||||
|
697
src/corelib/kernel/qmetacontainer.cpp
Normal file
697
src/corelib/kernel/qmetacontainer.cpp
Normal file
@ -0,0 +1,697 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 "qmetacontainer.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QMetaSequence
|
||||
\inmodule QtCore
|
||||
\since 6.0
|
||||
\brief The QMetaSequence class allows type erased access to sequential containers.
|
||||
|
||||
\ingroup objectmodel
|
||||
|
||||
The class provides a number of primitive container operations, using void*
|
||||
as operands. This way, you can manipulate a generic container retrieved from
|
||||
a Variant without knowing its type.
|
||||
|
||||
The void* arguments to the various methods are typically created by using
|
||||
a \l QVariant of the respective container or element type, and calling
|
||||
its \l QVariant::data() or \l QVariant::constData() methods. However, you
|
||||
can also pass plain pointers to objects of the container or element type.
|
||||
|
||||
Iterator invalidation follows the rules given by the underlying containers
|
||||
and is not expressed in the API. Therefore, for a truly generic container,
|
||||
any iterators should be considered invalid after any write operation.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template<typename C> QMetaSequence QMetaSequence::fromContainer()
|
||||
\since 6.0
|
||||
|
||||
Returns the QMetaSequence corresponding to the type given as template parameter.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container provides at least a forward
|
||||
iterator as defined by std::forward_iterator_tag, otherwise returns
|
||||
\c false. Bi-directional iterators and random access iterators are
|
||||
specializations of forward iterators. This method will also return
|
||||
\c true if the container provides one of those.
|
||||
|
||||
QMetaSequence assumes that const and non-const iterators for the same
|
||||
container have the same iterator traits.
|
||||
*/
|
||||
bool QMetaSequence::hasForwardIterator() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::ForwardCapability;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container provides a bi-directional
|
||||
iterator or a random access iterator as defined by
|
||||
std::bidirectional_iterator_tag and std::random_access_iterator_tag,
|
||||
respectively. Otherwise returns \c false.
|
||||
|
||||
QMetaSequence assumes that const and non-const iterators for the same
|
||||
container have the same iterator traits.
|
||||
*/
|
||||
bool QMetaSequence::hasBidirectionalIterator() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::BiDirectionalCapability;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container provides a random access
|
||||
iterator as defined by std::random_access_iterator_tag, otherwise returns
|
||||
\c false.
|
||||
|
||||
QMetaSequence assumes that const and non-const iterators for the same
|
||||
container have the same iterator traits.
|
||||
*/
|
||||
bool QMetaSequence::hasRandomAccessIterator() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::RandomAccessCapability;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the meta type for values stored in the container.
|
||||
*/
|
||||
QMetaType QMetaSequence::valueMetaType() const
|
||||
{
|
||||
return d_ptr ? d_ptr->valueMetaType : QMetaType();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container is ordered, otherwise returns
|
||||
\c false. A container is considered ordered if elements added to it are
|
||||
placed in a defined location. Inserting into or adding to an ordered
|
||||
container will always succeed. Inserting into or adding to an unordered
|
||||
container may not succeed, for example if the container is a QSet that
|
||||
already contains the value being inserted.
|
||||
|
||||
\sa addElement(), insertElementAtIterator(), addsAndRemovesElementsAtBegin(),
|
||||
addsAndRemovesElementsAtEnd()
|
||||
*/
|
||||
bool QMetaSequence::isOrdered() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->addRemovePosition != QtMetaContainerPrivate::QMetaSequenceInterface::Random;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if elements added using \l addElement() are placed at the
|
||||
beginning of the container, otherwise returns \c false. Likewise
|
||||
\l removeElement() removes an element from the beginning of the container
|
||||
if this method returns \c true.
|
||||
|
||||
\sa addElement(), removeElement(), addsAndRemovesElementsAtEnd()
|
||||
*/
|
||||
bool QMetaSequence::addsAndRemovesElementsAtBegin() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->addRemovePosition == QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if elements added using \l addElement() are placed at the
|
||||
end of the container, otherwise returns \c false. Likewise
|
||||
\l removeElement() removes an element from the end of the container
|
||||
if this method returns \c true.
|
||||
|
||||
\sa addElement(), removeElement(), addsAndRemovesElementsAtBegin()
|
||||
*/
|
||||
bool QMetaSequence::addsAndRemovesElementsAtEnd() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->addRemovePosition == QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the container can be queried for its size, \c false
|
||||
otherwise.
|
||||
|
||||
\sa size()
|
||||
*/
|
||||
bool QMetaSequence::hasSize() const
|
||||
{
|
||||
return d_ptr && d_ptr->sizeFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of elements in the given \a container if it can be
|
||||
queried for its size. Otherwise returns \c -1.
|
||||
|
||||
\sa hasSize()
|
||||
*/
|
||||
qsizetype QMetaSequence::size(const void *container) const
|
||||
{
|
||||
return hasSize() ? d_ptr->sizeFn(container) : -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the container can be cleared, \c false otherwise.
|
||||
|
||||
\sa clear()
|
||||
*/
|
||||
bool QMetaSequence::canClear() const
|
||||
{
|
||||
return d_ptr && d_ptr->clearFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Clears the given \a container if it can be cleared.
|
||||
|
||||
\sa canClear()
|
||||
*/
|
||||
void QMetaSequence::clear(void *container) const
|
||||
{
|
||||
if (canClear())
|
||||
d_ptr->clearFn(container);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if elements can be retrieved from the container by index,
|
||||
otherwise \c false.
|
||||
|
||||
\sa elementAtIndex()
|
||||
*/
|
||||
bool QMetaSequence::canGetElementAtIndex() const
|
||||
{
|
||||
return d_ptr && d_ptr->elementAtIndexFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Retrieves the element at \a index in the \a container and places it in the
|
||||
memory location pointed to by \a result, if that is possible.
|
||||
|
||||
\sa canGetElementAtIndex()
|
||||
*/
|
||||
void QMetaSequence::elementAtIndex(const void *container, qsizetype index, void *result) const
|
||||
{
|
||||
if (canGetElementAtIndex())
|
||||
d_ptr->elementAtIndexFn(container, index, result);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if an element can be written to the container by index,
|
||||
otherwise \c false.
|
||||
|
||||
\sa setElementAtIndex()
|
||||
*/
|
||||
bool QMetaSequence::canSetElementAtIndex() const
|
||||
{
|
||||
return d_ptr && d_ptr->setElementAtIndexFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Overwrites the element at \a index in the \a container using the \a element
|
||||
passed as parameter if that is possible.
|
||||
|
||||
\sa canSetElementAtIndex()
|
||||
*/
|
||||
void QMetaSequence::setElementAtIndex(void *container, qsizetype index, const void *element) const
|
||||
{
|
||||
if (canSetElementAtIndex())
|
||||
d_ptr->setElementAtIndexFn(container, index, element);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if elements can be added to the container, \c false
|
||||
otherwise.
|
||||
|
||||
\sa addElement(), isOrdered()
|
||||
*/
|
||||
bool QMetaSequence::canAddElement() const
|
||||
{
|
||||
return d_ptr && d_ptr->addElementFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds \a element to the \a container if possible. If \l canAddElement()
|
||||
returns \c false, the \a element is not added. Else, if
|
||||
\l addsAndRemovesElementsAtBegin() returns \c true, the \a element is added
|
||||
to the beginning of the \a container. Else, if
|
||||
\l addsAndRemovesElementsAtEnd() returns \c true, the \a element is added to
|
||||
the end of the container. Else, the element is added in an unspecified
|
||||
place or not at all. The latter is the case for adding elements to an
|
||||
unordered container, for example \l QSet.
|
||||
|
||||
\sa canAddElement(), addsAndRemovesElementsAtBegin(),
|
||||
addsAndRemovesElementsAtEnd(), isOrdered(), removeElement()
|
||||
*/
|
||||
void QMetaSequence::addElement(void *container, const void *element) const
|
||||
{
|
||||
if (canAddElement())
|
||||
d_ptr->addElementFn(container, element);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if elements can be removed from the container, \c false
|
||||
otherwise.
|
||||
|
||||
\sa removeElement(), isOrdered()
|
||||
*/
|
||||
bool QMetaSequence::canRemoveElement() const
|
||||
{
|
||||
return d_ptr && d_ptr->removeElementFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes an element from the \a container if possible. If
|
||||
\l canRemoveElement() returns \c false, no element is removed. Else, if
|
||||
\l addsAndRemovesElementsAtBegin() returns \c true, the first element in
|
||||
the \a container is removed. Else, if \l addsAndRemovesElementsAtEnd()
|
||||
returns \c true, the last element in the \a container is removed. Else,
|
||||
an unspecified element or nothing is removed.
|
||||
|
||||
\sa canRemoveElement(), addsAndRemovesElementsAtBegin(),
|
||||
addsAndRemovesElementsAtEnd(), isOrdered(), addElement()
|
||||
*/
|
||||
void QMetaSequence::removeElement(void *container) const
|
||||
{
|
||||
if (canRemoveElement())
|
||||
d_ptr->removeElementFn(container);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container offers a non-const iterator,
|
||||
\c false otherwise.
|
||||
|
||||
\sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
|
||||
advanceIterator(), copyIterator()
|
||||
*/
|
||||
bool QMetaSequence::hasIterator() const
|
||||
{
|
||||
if (!d_ptr || !d_ptr->createIteratorFn)
|
||||
return false;
|
||||
Q_ASSERT(d_ptr->destroyIteratorFn);
|
||||
Q_ASSERT(d_ptr->compareIteratorFn);
|
||||
Q_ASSERT(d_ptr->copyIteratorFn);
|
||||
Q_ASSERT(d_ptr->advanceIteratorFn);
|
||||
Q_ASSERT(d_ptr->diffIteratorFn);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and returns a non-const iterator pointing to the beginning of
|
||||
\a container. The iterator is allocated on the heap using new. It has to be
|
||||
destroyed using \l destroyIterator eventually, to reclaim the memory.
|
||||
|
||||
Returns \c nullptr if the container doesn't offer any non-const iterators.
|
||||
|
||||
\sa end(), constBegin(), constEnd(), destroyIterator()
|
||||
*/
|
||||
void *QMetaSequence::begin(void *container) const
|
||||
{
|
||||
return hasIterator()
|
||||
? d_ptr->createIteratorFn(
|
||||
container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and returns a non-const iterator pointing to the end of
|
||||
\a container. The iterator is allocated on the heap using new. It has to be
|
||||
destroyed using \l destroyIterator eventually, to reclaim the memory.
|
||||
|
||||
Returns \c nullptr if the container doesn't offer any non-const iterators.
|
||||
|
||||
\sa hasIterator(), end(), constBegin(), constEnd(), destroyIterator()
|
||||
*/
|
||||
void *QMetaSequence::end(void *container) const
|
||||
{
|
||||
return hasIterator()
|
||||
? d_ptr->createIteratorFn(
|
||||
container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys a non-const \a iterator previously created using \l begin() or
|
||||
\l end().
|
||||
|
||||
\sa begin(), end(), destroyConstIterator()
|
||||
*/
|
||||
void QMetaSequence::destroyIterator(const void *iterator) const
|
||||
{
|
||||
if (hasIterator())
|
||||
d_ptr->destroyIteratorFn(iterator);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the non-const iterators \a i and \a j point to the same
|
||||
element in the container they are iterating over, otherwise returns \c
|
||||
false.
|
||||
|
||||
\sa begin(), end()
|
||||
*/
|
||||
bool QMetaSequence::compareIterator(const void *i, const void *j) const
|
||||
{
|
||||
return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Copies the non-const iterator \a source into the non-const iterator
|
||||
\a target. Afterwards compareIterator(target, source) returns \c true.
|
||||
|
||||
\sa begin(), end()
|
||||
*/
|
||||
void QMetaSequence::copyIterator(void *target, const void *source) const
|
||||
{
|
||||
if (hasIterator())
|
||||
d_ptr->copyIteratorFn(target, source);
|
||||
}
|
||||
|
||||
/*!
|
||||
Advances the non-const \a iterator by \a step steps. If \a steps is negative
|
||||
the \a iterator is moved backwards, towards the beginning of the container.
|
||||
The behavior is unspecified for negative values of \a step if
|
||||
\l hasBidirectionalIterator() returns false.
|
||||
|
||||
\sa begin(), end()
|
||||
*/
|
||||
void QMetaSequence::advanceIterator(void *iterator, qsizetype step) const
|
||||
{
|
||||
if (hasIterator())
|
||||
d_ptr->advanceIteratorFn(iterator, step);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the distance between the non-const iterators \a i and \a j, the
|
||||
equivalent of \a i \c - \a j. If \a j is closer to the end of the container
|
||||
than \a i, the returned value is negative. The behavior is unspecified in
|
||||
this case if \l hasBidirectionalIterator() returns false.
|
||||
|
||||
\sa begin(), end()
|
||||
*/
|
||||
qsizetype QMetaSequence::diffIterator(const void *i, const void *j) const
|
||||
{
|
||||
return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container can retrieve the value pointed
|
||||
to by a non-const iterator, \c false otherwise.
|
||||
|
||||
\sa hasIterator(), elementAtIterator()
|
||||
*/
|
||||
bool QMetaSequence::canGetElementAtIterator() const
|
||||
{
|
||||
return d_ptr && d_ptr->elementAtIteratorFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Retrieves the element pointed to by the non-const \a iterator and stores it
|
||||
in the memory location pointed to by \a result, if possible.
|
||||
|
||||
\sa canGetElementAtIterator(), begin(), end()
|
||||
*/
|
||||
void QMetaSequence::elementAtIterator(const void *iterator, void *result) const
|
||||
{
|
||||
if (canGetElementAtIterator())
|
||||
d_ptr->elementAtIteratorFn(iterator, result);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container can write to the value pointed
|
||||
to by a non-const iterator, \c false otherwise.
|
||||
|
||||
\sa hasIterator(), setElementAtIterator()
|
||||
*/
|
||||
bool QMetaSequence::canSetElementAtIterator() const
|
||||
{
|
||||
return d_ptr && d_ptr->setElementAtIteratorFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Writes \a element to the value pointed to by the non-const \a iterator, if
|
||||
possible.
|
||||
|
||||
\sa canSetElementAtIterator(), begin(), end()
|
||||
*/
|
||||
void QMetaSequence::setElementAtIterator(const void *iterator, const void *element) const
|
||||
{
|
||||
if (canSetElementAtIterator())
|
||||
d_ptr->setElementAtIteratorFn(iterator, element);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container can insert a new element, taking
|
||||
the location pointed to by a non-const iterator into account.
|
||||
|
||||
\sa hasIterator(), insertElementAtIterator()
|
||||
*/
|
||||
bool QMetaSequence::canInsertElementAtIterator() const
|
||||
{
|
||||
return d_ptr && d_ptr->insertElementAtIteratorFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Inserts \a element into the \a container, if possible, taking the non-const
|
||||
\a iterator into account. If \l canInsertElementAtIterator() returns
|
||||
\c false, the \a element is not inserted. Else if \l isOrdered() returns
|
||||
\c true, the element is inserted before the element pointed to by
|
||||
\a iterator. Else, the \a element is inserted at an unspecified place or not
|
||||
at all. In the latter case, the \a iterator is taken as a hint. If it points
|
||||
to the correct place for the \a element, the operation may be faster than a
|
||||
\l addElement() without iterator.
|
||||
|
||||
\sa canInsertElementAtIterator(), isOrdered(), begin(), end()
|
||||
*/
|
||||
void QMetaSequence::insertElementAtIterator(void *container, const void *iterator,
|
||||
const void *element) const
|
||||
{
|
||||
if (canInsertElementAtIterator())
|
||||
d_ptr->insertElementAtIteratorFn(container, iterator, element);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the element pointed to by a non-const iterator can be
|
||||
erased, \c false otherwise.
|
||||
|
||||
\sa hasIterator(), eraseElementAtIterator()
|
||||
*/
|
||||
bool QMetaSequence::canEraseElementAtIterator() const
|
||||
{
|
||||
return d_ptr && d_ptr->eraseElementAtIteratorFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Erases the element pointed to by the non-const \a iterator from the
|
||||
\a container, if possible.
|
||||
|
||||
\sa canEraseElementAtIterator(), begin(), end()
|
||||
*/
|
||||
void QMetaSequence::eraseElementAtIterator(void *container, const void *iterator) const
|
||||
{
|
||||
if (canEraseElementAtIterator())
|
||||
d_ptr->eraseElementAtIteratorFn(container, iterator);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container offers a const iterator,
|
||||
\c false otherwise.
|
||||
|
||||
\sa constBegin(), constEnd(), destroyConstIterator(),
|
||||
compareConstIterator(), diffConstIterator(), advanceConstIterator(),
|
||||
copyConstIterator()
|
||||
*/
|
||||
bool QMetaSequence::hasConstIterator() const
|
||||
{
|
||||
if (!d_ptr || !d_ptr->createConstIteratorFn)
|
||||
return false;
|
||||
Q_ASSERT(d_ptr->destroyConstIteratorFn);
|
||||
Q_ASSERT(d_ptr->compareConstIteratorFn);
|
||||
Q_ASSERT(d_ptr->copyConstIteratorFn);
|
||||
Q_ASSERT(d_ptr->advanceConstIteratorFn);
|
||||
Q_ASSERT(d_ptr->diffConstIteratorFn);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and returns a const iterator pointing to the beginning of
|
||||
\a container. The iterator is allocated on the heap using new. It has to be
|
||||
destroyed using \l destroyConstIterator eventually, to reclaim the memory.
|
||||
|
||||
Returns \c nullptr if the container doesn't offer any const iterators.
|
||||
|
||||
\sa constEnd(), begin(), end(), destroyConstIterator()
|
||||
*/
|
||||
void *QMetaSequence::constBegin(const void *container) const
|
||||
{
|
||||
return hasConstIterator()
|
||||
? d_ptr->createConstIteratorFn(
|
||||
container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and returns a const iterator pointing to the end of
|
||||
\a container. The iterator is allocated on the heap using new. It has to be
|
||||
destroyed using \l destroyConstIterator eventually, to reclaim the memory.
|
||||
|
||||
Returns \c nullptr if the container doesn't offer any const iterators.
|
||||
|
||||
\sa constBegin(), begin(), end(), destroyConstIterator()
|
||||
*/
|
||||
void *QMetaSequence::constEnd(const void *container) const
|
||||
{
|
||||
return hasConstIterator()
|
||||
? d_ptr->createConstIteratorFn(
|
||||
container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys a const \a iterator previously created using \l constBegin() or
|
||||
\l constEnd().
|
||||
|
||||
\sa constBegin(), constEnd(), destroyIterator()
|
||||
*/
|
||||
void QMetaSequence::destroyConstIterator(const void *iterator) const
|
||||
{
|
||||
if (hasConstIterator())
|
||||
d_ptr->destroyConstIteratorFn(iterator);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the const iterators \a i and \a j point to the same
|
||||
element in the container they are iterating over, otherwise returns \c
|
||||
false.
|
||||
|
||||
\sa constBegin(), constEnd()
|
||||
*/
|
||||
bool QMetaSequence::compareConstIterator(const void *i, const void *j) const
|
||||
{
|
||||
return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Copies the const iterator \a source into the const iterator
|
||||
\a target. Afterwards compareConstIterator(target, source) returns \c true.
|
||||
|
||||
\sa constBegin(), constEnd()
|
||||
*/
|
||||
void QMetaSequence::copyConstIterator(void *target, const void *source) const
|
||||
{
|
||||
if (hasConstIterator())
|
||||
d_ptr->copyConstIteratorFn(target, source);
|
||||
}
|
||||
|
||||
/*!
|
||||
Advances the const \a iterator by \a step steps. If \a steps is negative
|
||||
the \a iterator is moved backwards, towards the beginning of the container.
|
||||
The behavior is unspecified for negative values of \a step if
|
||||
\l hasBidirectionalIterator() returns false.
|
||||
|
||||
\sa constBegin(), constEnd()
|
||||
*/
|
||||
void QMetaSequence::advanceConstIterator(void *iterator, qsizetype step) const
|
||||
{
|
||||
if (hasConstIterator())
|
||||
d_ptr->advanceConstIteratorFn(iterator, step);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the distance between the const iterators \a i and \a j, the
|
||||
equivalent of \a i \c - \a j. If \a j is closer to the end of the container
|
||||
than \a i, the returned value is negative. The behavior is unspecified in
|
||||
this case if \l hasBidirectionalIterator() returns false.
|
||||
|
||||
\sa constBegin(), constEnd()
|
||||
*/
|
||||
qsizetype QMetaSequence::diffConstIterator(const void *i, const void *j) const
|
||||
{
|
||||
return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container can retrieve the value pointed
|
||||
to by a const iterator, \c false otherwise.
|
||||
|
||||
\sa hasConstIterator(), elementAtConstIterator()
|
||||
*/
|
||||
bool QMetaSequence::canGetElementAtConstIterator() const
|
||||
{
|
||||
return d_ptr && d_ptr->elementAtConstIteratorFn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Retrieves the element pointed to by the const \a iterator and stores it
|
||||
in the memory location pointed to by \a result, if possible.
|
||||
|
||||
\sa canGetElementAtConstIterator(), constBegin(), constEnd()
|
||||
*/
|
||||
void QMetaSequence::elementAtConstIterator(const void *iterator, void *result) const
|
||||
{
|
||||
if (canGetElementAtConstIterator())
|
||||
d_ptr->elementAtConstIteratorFn(iterator, result);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool operator==(QMetaSequence a, QMetaSequence b)
|
||||
\since 6.0
|
||||
\relates QMetaSequence
|
||||
|
||||
Returns \c true if the QMetaSequence \a a represents the same container type
|
||||
as the QMetaSequence \a b, otherwise returns \c false.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool operator!=(QMetaSequence a, QMetaSequence b)
|
||||
\since 6.0
|
||||
\relates QMetaSequence
|
||||
|
||||
Returns \c true if the QMetaSequence \a a represents a different container
|
||||
type than the QMetaSequence \a b, otherwise returns \c false.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
594
src/corelib/kernel/qmetacontainer.h
Normal file
594
src/corelib/kernel/qmetacontainer.h
Normal file
@ -0,0 +1,594 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 QMETACONTAINER_H
|
||||
#define QMETACONTAINER_H
|
||||
|
||||
#include <QtCore/qcontainerinfo.h>
|
||||
#include <QtCore/qflags.h>
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtMetaContainerPrivate {
|
||||
|
||||
enum IteratorCapability : quint8 {
|
||||
ForwardCapability = 1 << 0,
|
||||
BiDirectionalCapability = 1 << 1,
|
||||
RandomAccessCapability = 1 << 2,
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
|
||||
|
||||
class QMetaSequenceInterface
|
||||
{
|
||||
public:
|
||||
enum Position : quint8 { AtBegin, AtEnd, Random };
|
||||
|
||||
ushort revision;
|
||||
IteratorCapabilities iteratorCapabilities;
|
||||
Position addRemovePosition;
|
||||
QMetaType valueMetaType;
|
||||
|
||||
using SizeFn = qsizetype(*)(const void *);
|
||||
SizeFn sizeFn;
|
||||
using ClearFn = void(*)(void *);
|
||||
ClearFn clearFn;
|
||||
|
||||
using ElementAtIndexFn = void(*)(const void *, qsizetype, void *);
|
||||
ElementAtIndexFn elementAtIndexFn;
|
||||
using SetElementAtIndexFn = void(*)(void *, qsizetype, const void *);
|
||||
SetElementAtIndexFn setElementAtIndexFn;
|
||||
|
||||
using AddElementFn = void(*)(void *, const void *);
|
||||
AddElementFn addElementFn;
|
||||
using RemoveElementFn = void(*)(void *);
|
||||
RemoveElementFn removeElementFn;
|
||||
|
||||
using CreateIteratorFn = void *(*)(void *, Position);
|
||||
CreateIteratorFn createIteratorFn;
|
||||
using DestroyIteratorFn = void(*)(const void *);
|
||||
DestroyIteratorFn destroyIteratorFn;
|
||||
using CompareIteratorFn = bool(*)(const void *, const void *);
|
||||
CompareIteratorFn compareIteratorFn;
|
||||
using CopyIteratorFn = void(*)(void *, const void *);
|
||||
CopyIteratorFn copyIteratorFn;
|
||||
using AdvanceIteratorFn = void(*)(void *, qsizetype);
|
||||
AdvanceIteratorFn advanceIteratorFn;
|
||||
using DiffIteratorFn = qsizetype(*)(const void *, const void *);
|
||||
DiffIteratorFn diffIteratorFn;
|
||||
using ElementAtIteratorFn = void(*)(const void *, void *);
|
||||
ElementAtIteratorFn elementAtIteratorFn;
|
||||
using SetElementAtIteratorFn = void(*)(const void *, const void *);
|
||||
SetElementAtIteratorFn setElementAtIteratorFn;
|
||||
using InsertElementAtIteratorFn = void(*)(void *, const void *, const void *);
|
||||
InsertElementAtIteratorFn insertElementAtIteratorFn;
|
||||
using EraseElementAtIteratorFn = void(*)(void *, const void *);
|
||||
EraseElementAtIteratorFn eraseElementAtIteratorFn;
|
||||
|
||||
using CreateConstIteratorFn = void *(*)(const void *, Position);
|
||||
CreateConstIteratorFn createConstIteratorFn;
|
||||
DestroyIteratorFn destroyConstIteratorFn;
|
||||
CompareIteratorFn compareConstIteratorFn;
|
||||
CopyIteratorFn copyConstIteratorFn;
|
||||
AdvanceIteratorFn advanceConstIteratorFn;
|
||||
DiffIteratorFn diffConstIteratorFn;
|
||||
ElementAtIteratorFn elementAtConstIteratorFn;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
class QMetaSequenceForContainer
|
||||
{
|
||||
template <typename Iterator>
|
||||
static constexpr IteratorCapabilities capabilitiesForIterator()
|
||||
{
|
||||
using Tag = typename std::iterator_traits<Iterator>::iterator_category;
|
||||
IteratorCapabilities caps {};
|
||||
if constexpr (std::is_base_of_v<std::forward_iterator_tag, Tag>)
|
||||
caps |= ForwardCapability;
|
||||
if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, Tag>)
|
||||
caps |= BiDirectionalCapability;
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, Tag>)
|
||||
caps |= RandomAccessCapability;
|
||||
return caps;
|
||||
}
|
||||
|
||||
static constexpr IteratorCapabilities getIteratorCapabilities()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>)
|
||||
return capabilitiesForIterator<QContainerTraits::iterator<C>>();
|
||||
else if constexpr (QContainerTraits::has_const_iterator_v<C>)
|
||||
return capabilitiesForIterator<QContainerTraits::const_iterator<C>>();
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::Position getAddRemovePosition()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_push_back_v<C> && QContainerTraits::has_pop_back_v<C>)
|
||||
return QMetaSequenceInterface::AtEnd;
|
||||
if constexpr (QContainerTraits::has_push_front_v<C> && QContainerTraits::has_pop_front_v<C>)
|
||||
return QMetaSequenceInterface::AtBegin;
|
||||
return QMetaSequenceInterface::Random;
|
||||
}
|
||||
|
||||
static constexpr QMetaType getValueMetaType()
|
||||
{
|
||||
return QMetaType::fromType<typename C::value_type>();
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::SizeFn getSizeFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_size_v<C>) {
|
||||
return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::ClearFn getClearFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_clear_v<C>) {
|
||||
return [](void *c) { return static_cast<C *>(c)->clear(); };
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::ElementAtIndexFn getElementAtIndexFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_at_v<C>) {
|
||||
return [](const void *c, qsizetype i, void *r) {
|
||||
*static_cast<QContainerTraits::value_type<C> *>(r)
|
||||
= static_cast<const C *>(c)->at(i);
|
||||
};
|
||||
} else if constexpr (QContainerTraits::can_get_at_index_v<C>) {
|
||||
return [](const void *c, qsizetype i, void *r) {
|
||||
*static_cast<QContainerTraits::value_type<C> *>(r)
|
||||
= (*static_cast<const C *>(c))[i];
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::SetElementAtIndexFn getSetElementAtIndexFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::can_set_at_index_v<C>) {
|
||||
return [](void *c, qsizetype i, const void *e) {
|
||||
(*static_cast<C *>(c))[i]
|
||||
= *static_cast<const QContainerTraits::value_type<C> *>(e);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::AddElementFn getAddElementFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_push_back_v<C>) {
|
||||
return [](void *c, const void *v) {
|
||||
static_cast<C *>(c)->push_back(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
};
|
||||
} else if constexpr (QContainerTraits::has_push_front_v<C>) {
|
||||
return [](void *c, const void *v) {
|
||||
static_cast<C *>(c)->push_front(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
};
|
||||
} else if constexpr (QContainerTraits::has_insert_v<C>) {
|
||||
return [](void *c, const void *v) {
|
||||
static_cast<C *>(c)->insert(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::RemoveElementFn getRemoveElementFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_pop_back_v<C>) {
|
||||
return [](void *c) { static_cast<C *>(c)->pop_back(); };
|
||||
} else if constexpr (QContainerTraits::has_pop_front_v<C>) {
|
||||
return [](void *c) { static_cast<C *>(c)->pop_front(); };
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::CreateIteratorFn getCreateIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](void *c, QMetaSequenceInterface::Position p) -> void* {
|
||||
using Iterator = QContainerTraits::iterator<C>;
|
||||
switch (p) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
case QMetaSequenceInterface::Random:
|
||||
return new Iterator(static_cast<C *>(c)->begin());
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
return new Iterator(static_cast<C *>(c)->end());
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](const void *i) {
|
||||
using Iterator = QContainerTraits::iterator<C>;
|
||||
delete static_cast<const Iterator *>(i);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](const void *i, const void *j) {
|
||||
using Iterator = QContainerTraits::iterator<C>;
|
||||
return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](void *i, const void *j) {
|
||||
using Iterator = QContainerTraits::iterator<C>;
|
||||
*static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](void *i, qsizetype step) {
|
||||
std::advance(*static_cast<QContainerTraits::iterator<C> *>(i), step);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](const void *i, const void *j) -> qsizetype {
|
||||
return std::distance(*static_cast<const QContainerTraits::iterator<C> *>(j),
|
||||
*static_cast<const QContainerTraits::iterator<C> *>(i));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::ElementAtIteratorFn getElementAtIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C>
|
||||
&& QContainerTraits::can_get_at_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](const void *i, void *r) {
|
||||
*static_cast<QContainerTraits::value_type<C> *>(r) =
|
||||
*(*static_cast<const QContainerTraits::iterator<C> *>(i));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::SetElementAtIteratorFn getSetElementAtIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C>
|
||||
&& QContainerTraits::can_set_at_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](const void *i, const void *e) {
|
||||
*(*static_cast<const QContainerTraits::iterator<C> *>(i))
|
||||
= *static_cast<const QContainerTraits::value_type<C> *>(e);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::InsertElementAtIteratorFn getInsertElementAtIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C>
|
||||
&& QContainerTraits::can_insert_at_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](void *c, const void *i, const void *e) {
|
||||
static_cast<C *>(c)->insert(
|
||||
*static_cast<const QContainerTraits::iterator<C> *>(i),
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(e));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::EraseElementAtIteratorFn getEraseElementAtIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_iterator_v<C>
|
||||
&& QContainerTraits::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
|
||||
return [](void *c, const void *i) {
|
||||
static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::CreateConstIteratorFn getCreateConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>) {
|
||||
return [](const void *c, QMetaSequenceInterface::Position p) -> void* {
|
||||
using Iterator = QContainerTraits::const_iterator<C>;
|
||||
switch (p) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
case QMetaSequenceInterface::Random:
|
||||
return new Iterator(static_cast<const C *>(c)->begin());
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
return new Iterator(static_cast<const C *>(c)->end());
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>) {
|
||||
return [](const void *i) {
|
||||
using Iterator = QContainerTraits::const_iterator<C>;
|
||||
delete static_cast<const Iterator *>(i);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>) {
|
||||
return [](const void *i, const void *j) {
|
||||
using Iterator = QContainerTraits::const_iterator<C>;
|
||||
return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>) {
|
||||
return [](void *i, const void *j) {
|
||||
using Iterator = QContainerTraits::const_iterator<C>;
|
||||
*static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>) {
|
||||
return [](void *i, qsizetype step) {
|
||||
std::advance(*static_cast<QContainerTraits::const_iterator<C> *>(i), step);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>) {
|
||||
return [](const void *i, const void *j) -> qsizetype {
|
||||
return std::distance(*static_cast<const QContainerTraits::const_iterator<C> *>(j),
|
||||
*static_cast<const QContainerTraits::const_iterator<C> *>(i));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::ElementAtIteratorFn getElementAtConstIteratorFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_const_iterator_v<C>
|
||||
&& QContainerTraits::can_get_at_iterator_v<C>) {
|
||||
return [](const void *i, void *r) {
|
||||
*static_cast<QContainerTraits::value_type<C> *>(r) =
|
||||
*(*static_cast<const QContainerTraits::const_iterator<C> *>(i));
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static QMetaSequenceInterface metaSequence;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
QMetaSequenceInterface QMetaSequenceForContainer<C>::metaSequence = {
|
||||
/*.revision=*/ 0,
|
||||
/*.iteratorCapabilities=*/ getIteratorCapabilities(),
|
||||
/*.addRemovePosition=*/ getAddRemovePosition(),
|
||||
/*.valueMetaType=*/ getValueMetaType(),
|
||||
/*.sizeFn=*/ getSizeFn(),
|
||||
/*.clearFn=*/ getClearFn(),
|
||||
/*.elementAtIndexFn=*/ getElementAtIndexFn(),
|
||||
/*.setElementAtIndexFn=*/ getSetElementAtIndexFn(),
|
||||
/*.addElementFn=*/ getAddElementFn(),
|
||||
/*.removeLastElementFn=*/ getRemoveElementFn(),
|
||||
/*.createIteratorFn=*/ getCreateIteratorFn(),
|
||||
/*.destroyIteratorFn=*/ getDestroyIteratorFn(),
|
||||
/*.equalIteratorFn=*/ getCompareIteratorFn(),
|
||||
/*.copyIteratorFn=*/ getCopyIteratorFn(),
|
||||
/*.advanceIteratorFn=*/ getAdvanceIteratorFn(),
|
||||
/*.diffIteratorFn=*/ getDiffIteratorFn(),
|
||||
/*.elementAtIteratorFn=*/ getElementAtIteratorFn(),
|
||||
/*.setElementAtIteratorFn=*/ getSetElementAtIteratorFn(),
|
||||
/*.insertElementAtIteratorFn=*/ getInsertElementAtIteratorFn(),
|
||||
/*.eraseElementAtIteratorFn=*/ getEraseElementAtIteratorFn(),
|
||||
/*.createConstIteratorFn=*/ getCreateConstIteratorFn(),
|
||||
/*.destroyConstIteratorFn=*/ getDestroyConstIteratorFn(),
|
||||
/*.equalConstIteratorFn=*/ getCompareConstIteratorFn(),
|
||||
/*.copyConstIteratorFn=*/ getCopyConstIteratorFn(),
|
||||
/*.advanceConstIteratorFn=*/ getAdvanceConstIteratorFn(),
|
||||
/*.diffConstIteratorFn=*/ getDiffConstIteratorFn(),
|
||||
/*.elementAtConstIteratorFn=*/ getElementAtConstIteratorFn(),
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
constexpr QMetaSequenceInterface *qMetaSequenceInterfaceForContainer()
|
||||
{
|
||||
return &QMetaSequenceForContainer<C>::metaSequence;
|
||||
}
|
||||
|
||||
} // namespace QtMetaContainerPrivate
|
||||
|
||||
class Q_CORE_EXPORT QMetaSequence
|
||||
{
|
||||
public:
|
||||
QMetaSequence() = default;
|
||||
explicit QMetaSequence(QtMetaContainerPrivate::QMetaSequenceInterface *d) : d_ptr(d) {}
|
||||
|
||||
template<typename T>
|
||||
static constexpr QMetaSequence fromContainer()
|
||||
{
|
||||
return QMetaSequence(QtMetaContainerPrivate::qMetaSequenceInterfaceForContainer<T>());
|
||||
}
|
||||
|
||||
bool hasForwardIterator() const;
|
||||
bool hasBidirectionalIterator() const;
|
||||
bool hasRandomAccessIterator() const;
|
||||
|
||||
QMetaType valueMetaType() const;
|
||||
|
||||
bool isOrdered() const;
|
||||
bool addsAndRemovesElementsAtBegin() const;
|
||||
bool addsAndRemovesElementsAtEnd() const;
|
||||
|
||||
bool hasSize() const;
|
||||
qsizetype size(const void *container) const;
|
||||
|
||||
bool canClear() const;
|
||||
void clear(void *container) const;
|
||||
|
||||
bool canGetElementAtIndex() const;
|
||||
void elementAtIndex(const void *container, qsizetype index, void *result) const;
|
||||
|
||||
bool canSetElementAtIndex() const;
|
||||
void setElementAtIndex(void *container, qsizetype index, const void *element) const;
|
||||
|
||||
bool canAddElement() const;
|
||||
void addElement(void *container, const void *element) const;
|
||||
|
||||
bool canRemoveElement() const;
|
||||
void removeElement(void *container) const;
|
||||
|
||||
bool hasIterator() const;
|
||||
void *begin(void *container) const;
|
||||
void *end(void *container) const;
|
||||
void destroyIterator(const void *iterator) const;
|
||||
bool compareIterator(const void *i, const void *j) const;
|
||||
void copyIterator(void *target, const void *source) const;
|
||||
void advanceIterator(void *iterator, qsizetype step) const;
|
||||
qsizetype diffIterator(const void *i, const void *j) const;
|
||||
|
||||
bool canGetElementAtIterator() const;
|
||||
void elementAtIterator(const void *iterator, void *result) const;
|
||||
|
||||
bool canSetElementAtIterator() const;
|
||||
void setElementAtIterator(const void *iterator, const void *element) const;
|
||||
|
||||
bool canInsertElementAtIterator() const;
|
||||
void insertElementAtIterator(void *container, const void *iterator, const void *element) const;
|
||||
|
||||
bool canEraseElementAtIterator() const;
|
||||
void eraseElementAtIterator(void *container, const void *iterator) const;
|
||||
|
||||
bool hasConstIterator() const;
|
||||
void *constBegin(const void *container) const;
|
||||
void *constEnd(const void *container) const;
|
||||
void destroyConstIterator(const void *iterator) const;
|
||||
bool compareConstIterator(const void *i, const void *j) const;
|
||||
void copyConstIterator(void *target, const void *source) const;
|
||||
void advanceConstIterator(void *iterator, qsizetype step) const;
|
||||
qsizetype diffConstIterator(const void *i, const void *j) const;
|
||||
|
||||
bool canGetElementAtConstIterator() const;
|
||||
void elementAtConstIterator(const void *iterator, void *result) const;
|
||||
|
||||
friend bool operator==(const QMetaSequence &a, const QMetaSequence &b)
|
||||
{
|
||||
return a.d_ptr == b.d_ptr;
|
||||
}
|
||||
friend bool operator!=(const QMetaSequence &a, const QMetaSequence &b)
|
||||
{
|
||||
return a.d_ptr != b.d_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
QtMetaContainerPrivate::QMetaSequenceInterface *d_ptr = nullptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QMETACONTAINER_H
|
@ -75,6 +75,7 @@ qt_add_module(Bootstrap
|
||||
../../corelib/io/qurlrecode.cpp
|
||||
../../corelib/kernel/qcoreapplication.cpp
|
||||
../../corelib/kernel/qcoreglobaldata.cpp
|
||||
../../corelib/kernel/qmetacontainer.cpp
|
||||
../../corelib/kernel/qmetatype.cpp
|
||||
../../corelib/kernel/qsharedmemory.cpp
|
||||
../../corelib/kernel/qsystemerror.cpp
|
||||
|
@ -76,6 +76,7 @@ qt_extend_target(Bootstrap
|
||||
../../corelib/io/qurlrecode.cpp
|
||||
../../corelib/kernel/qcoreapplication.cpp
|
||||
../../corelib/kernel/qcoreglobaldata.cpp
|
||||
../../corelib/kernel/qmetacontainer.cpp
|
||||
../../corelib/kernel/qmetatype.cpp
|
||||
../../corelib/kernel/qsharedmemory.cpp
|
||||
../../corelib/kernel/qsystemerror.cpp
|
||||
|
@ -62,6 +62,7 @@ SOURCES += \
|
||||
../../corelib/io/qurlrecode.cpp \
|
||||
../../corelib/kernel/qcoreapplication.cpp \
|
||||
../../corelib/kernel/qcoreglobaldata.cpp \
|
||||
../../corelib/kernel/qmetacontainer.cpp \
|
||||
../../corelib/kernel/qmetatype.cpp \
|
||||
../../corelib/kernel/qvariant.cpp \
|
||||
../../corelib/kernel/qsystemerror.cpp \
|
||||
|
@ -5,6 +5,7 @@ add_subdirectory(qdeadlinetimer)
|
||||
add_subdirectory(qelapsedtimer)
|
||||
add_subdirectory(qeventdispatcher)
|
||||
add_subdirectory(qmath)
|
||||
add_subdirectory(qmetacontainer)
|
||||
add_subdirectory(qmetaobject)
|
||||
add_subdirectory(qmetaobjectbuilder)
|
||||
add_subdirectory(qmetamethod)
|
||||
|
@ -5,6 +5,7 @@ add_subdirectory(qdeadlinetimer)
|
||||
add_subdirectory(qelapsedtimer)
|
||||
add_subdirectory(qeventdispatcher)
|
||||
add_subdirectory(qmath)
|
||||
add_subdirectory(qmetacontainer)
|
||||
add_subdirectory(qmetaobject)
|
||||
add_subdirectory(qmetaobjectbuilder)
|
||||
add_subdirectory(qmetamethod)
|
||||
|
@ -6,6 +6,7 @@ SUBDIRS=\
|
||||
qeventdispatcher \
|
||||
qeventloop \
|
||||
qmath \
|
||||
qmetacontainer \
|
||||
qmetaobject \
|
||||
qmetaobjectbuilder \
|
||||
qmetamethod \
|
||||
|
16
tests/auto/corelib/kernel/qmetacontainer/CMakeLists.txt
Normal file
16
tests/auto/corelib/kernel/qmetacontainer/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
# Generated from qmetacontainer.pro.
|
||||
|
||||
#####################################################################
|
||||
## tst_qmetacontainer Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "./typeFlags.bin")
|
||||
|
||||
qt_add_test(tst_qmetacontainer
|
||||
SOURCES
|
||||
tst_qmetacontainer.cpp
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::CorePrivate
|
||||
TESTDATA ${test_data}
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
CONFIG += testcase
|
||||
TARGET = tst_qmetacontainer
|
||||
QT = core-private testlib
|
||||
SOURCES = tst_qmetacontainer.cpp
|
||||
TESTDATA=./typeFlags.bin
|
||||
|
||||
|
490
tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp
Normal file
490
tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp
Normal file
@ -0,0 +1,490 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** 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 General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest/qtest.h>
|
||||
#include <QtCore/qcontainerinfo.h>
|
||||
#include <QtCore/qmetacontainer.h>
|
||||
|
||||
#include <QtCore/qvector.h>
|
||||
#include <QtCore/qset.h>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qbytearray.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <forward_list>
|
||||
|
||||
namespace CheckContainerTraits
|
||||
{
|
||||
struct NotAContainer {};
|
||||
|
||||
static_assert(QContainerTraits::has_size_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::has_size_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_size_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_size_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::has_size_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::has_size_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_clear_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::has_clear_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_clear_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_clear_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::has_clear_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::has_clear_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_at_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::has_at_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_at_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_at_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::has_at_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::has_at_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::can_get_at_index_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::can_get_at_index_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::can_get_at_index_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::can_get_at_index_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::can_get_at_index_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::can_get_at_index_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::can_set_at_index_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::can_set_at_index_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::can_set_at_index_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::can_set_at_index_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::can_set_at_index_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::can_set_at_index_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_push_back_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::has_push_back_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_push_back_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_push_back_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::has_push_back_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::has_push_back_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_push_front_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::has_push_front_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_push_front_v<NotAContainer>);
|
||||
static_assert(!QContainerTraits::has_push_front_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::has_push_front_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::has_push_front_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(!QContainerTraits::has_insert_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::has_insert_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_insert_v<NotAContainer>);
|
||||
static_assert(!QContainerTraits::has_insert_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::has_insert_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::has_insert_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_pop_back_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_back_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_back_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_pop_back_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_back_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_back_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_pop_front_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_front_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_front_v<NotAContainer>);
|
||||
static_assert(!QContainerTraits::has_pop_front_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::has_pop_front_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::has_pop_front_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_iterator_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::has_iterator_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_iterator_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_iterator_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::has_iterator_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::has_iterator_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::has_const_iterator_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::has_const_iterator_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::has_const_iterator_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::has_const_iterator_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::has_const_iterator_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::has_const_iterator_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::can_get_at_iterator_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::can_get_at_iterator_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::can_get_at_iterator_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::can_get_at_iterator_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::can_get_at_iterator_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::can_get_at_iterator_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::can_set_at_iterator_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::can_set_at_iterator_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::can_get_at_iterator_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::can_set_at_iterator_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::can_set_at_iterator_v<std::set<int>>);
|
||||
static_assert(QContainerTraits::can_set_at_iterator_v<std::forward_list<int>>);
|
||||
|
||||
static_assert(QContainerTraits::can_insert_at_iterator_v<QVector<int>>);
|
||||
static_assert(!QContainerTraits::can_insert_at_iterator_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::can_insert_at_iterator_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::can_insert_at_iterator_v<std::vector<int>>);
|
||||
static_assert(!QContainerTraits::can_insert_at_iterator_v<std::forward_list<int>>);
|
||||
|
||||
// The iterator is only a hint, but syntactically indistinguishable from others.
|
||||
// It's explicitly there to be signature compatible with std::vector::insert, though.
|
||||
// Also, inserting into a set is not guaranteed to actually do anything.
|
||||
static_assert(QContainerTraits::can_insert_at_iterator_v<std::set<int>>);
|
||||
|
||||
static_assert(QContainerTraits::can_erase_at_iterator_v<QVector<int>>);
|
||||
static_assert(QContainerTraits::can_erase_at_iterator_v<QSet<int>>);
|
||||
static_assert(!QContainerTraits::can_erase_at_iterator_v<NotAContainer>);
|
||||
static_assert(QContainerTraits::can_erase_at_iterator_v<std::vector<int>>);
|
||||
static_assert(QContainerTraits::can_erase_at_iterator_v<std::set<int>>);
|
||||
static_assert(!QContainerTraits::can_erase_at_iterator_v<std::forward_list<int>>);
|
||||
|
||||
}
|
||||
|
||||
class tst_QMetaContainer: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QVector<QMetaType> qvector;
|
||||
std::vector<QString> stdvector;
|
||||
QSet<QByteArray> qset;
|
||||
std::set<int> stdset;
|
||||
std::forward_list<QMetaSequence> forwardList;
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
void testSequence_data();
|
||||
void testSequence();
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
void tst_QMetaContainer::init()
|
||||
{
|
||||
qvector = { QMetaType(), QMetaType::fromType<QString>(), QMetaType::fromType<int>() };
|
||||
stdvector = { QStringLiteral("foo"), QStringLiteral("bar"), QStringLiteral("baz") };
|
||||
qset = { "aaa", "bbb", "ccc" };
|
||||
stdset = { 1, 2, 3, 42, 45, 11 };
|
||||
forwardList = {
|
||||
QMetaSequence::fromContainer<QVector<QMetaType>>(),
|
||||
QMetaSequence::fromContainer<std::vector<QString>>(),
|
||||
QMetaSequence::fromContainer<QSet<QByteArray>>(),
|
||||
QMetaSequence::fromContainer<std::set<int>>(),
|
||||
QMetaSequence::fromContainer<std::forward_list<QMetaSequence>>()
|
||||
};
|
||||
}
|
||||
|
||||
void tst_QMetaContainer::cleanup()
|
||||
{
|
||||
qvector.clear();
|
||||
stdvector.clear();
|
||||
qset.clear();
|
||||
stdset.clear();
|
||||
forwardList.clear();
|
||||
}
|
||||
|
||||
void tst_QMetaContainer::testSequence_data()
|
||||
{
|
||||
QTest::addColumn<void *>("container");
|
||||
QTest::addColumn<QMetaSequence>("metaSequence");
|
||||
QTest::addColumn<QMetaType>("metaType");
|
||||
QTest::addColumn<bool>("hasSize");
|
||||
QTest::addColumn<bool>("isIndexed");
|
||||
QTest::addColumn<bool>("canRemove");
|
||||
QTest::addColumn<bool>("hasBidirectionalIterator");
|
||||
QTest::addColumn<bool>("hasRandomAccessIterator");
|
||||
QTest::addColumn<bool>("canInsertAtIterator");
|
||||
QTest::addColumn<bool>("canEraseAtIterator");
|
||||
QTest::addColumn<bool>("isOrdered");
|
||||
|
||||
QTest::addRow("QVector")
|
||||
<< static_cast<void *>(&qvector)
|
||||
<< QMetaSequence::fromContainer<QVector<QMetaType>>()
|
||||
<< QMetaType::fromType<QMetaType>()
|
||||
<< true << true << true << true << true << true << true << true;
|
||||
QTest::addRow("std::vector")
|
||||
<< static_cast<void *>(&stdvector)
|
||||
<< QMetaSequence::fromContainer<std::vector<QString>>()
|
||||
<< QMetaType::fromType<QString>()
|
||||
<< true << true << true << true << true << true << true << true;
|
||||
QTest::addRow("QSet")
|
||||
<< static_cast<void *>(&qset)
|
||||
<< QMetaSequence::fromContainer<QSet<QByteArray>>()
|
||||
<< QMetaType::fromType<QByteArray>()
|
||||
<< true << false << false << false << false << false << true << false;
|
||||
QTest::addRow("std::set")
|
||||
<< static_cast<void *>(&stdset)
|
||||
<< QMetaSequence::fromContainer<std::set<int>>()
|
||||
<< QMetaType::fromType<int>()
|
||||
<< true << false << false << true << false << true << true << false;
|
||||
QTest::addRow("std::forward_list")
|
||||
<< static_cast<void *>(&forwardList)
|
||||
<< QMetaSequence::fromContainer<std::forward_list<QMetaSequence>>()
|
||||
<< QMetaType::fromType<QMetaSequence>()
|
||||
<< false << false << true << false << false << false << false << true;
|
||||
}
|
||||
|
||||
void tst_QMetaContainer::testSequence()
|
||||
{
|
||||
QFETCH(void *, container);
|
||||
QFETCH(QMetaSequence, metaSequence);
|
||||
QFETCH(QMetaType, metaType);
|
||||
QFETCH(bool, hasSize);
|
||||
QFETCH(bool, isIndexed);
|
||||
QFETCH(bool, canRemove);
|
||||
QFETCH(bool, hasBidirectionalIterator);
|
||||
QFETCH(bool, hasRandomAccessIterator);
|
||||
QFETCH(bool, canInsertAtIterator);
|
||||
QFETCH(bool, canEraseAtIterator);
|
||||
QFETCH(bool, isOrdered);
|
||||
|
||||
QVERIFY(metaSequence.canAddElement());
|
||||
QCOMPARE(metaSequence.hasSize(), hasSize);
|
||||
QCOMPARE(metaSequence.canGetElementAtIndex(), isIndexed);
|
||||
QCOMPARE(metaSequence.canSetElementAtIndex(), isIndexed);
|
||||
QCOMPARE(metaSequence.canRemoveElement(), canRemove);
|
||||
QCOMPARE(metaSequence.hasBidirectionalIterator(), hasBidirectionalIterator);
|
||||
QCOMPARE(metaSequence.hasRandomAccessIterator(), hasRandomAccessIterator);
|
||||
QCOMPARE(metaSequence.canInsertElementAtIterator(), canInsertAtIterator);
|
||||
QCOMPARE(metaSequence.canEraseElementAtIterator(), canEraseAtIterator);
|
||||
QCOMPARE(metaSequence.isOrdered(), isOrdered);
|
||||
|
||||
QVariant var1(metaType);
|
||||
QVariant var2(metaType);
|
||||
QVariant var3(metaType);
|
||||
|
||||
if (hasSize) {
|
||||
const qsizetype size = metaSequence.size(container);
|
||||
|
||||
// var1 is invalid, and our sets do not contain an invalid value so far.
|
||||
metaSequence.addElement(container, var1.constData());
|
||||
QCOMPARE(metaSequence.size(container), size + 1);
|
||||
if (canRemove) {
|
||||
metaSequence.removeElement(container);
|
||||
QCOMPARE(metaSequence.size(container), size);
|
||||
}
|
||||
} else {
|
||||
metaSequence.addElement(container, var1.constData());
|
||||
if (canRemove)
|
||||
metaSequence.removeElement(container);
|
||||
}
|
||||
|
||||
if (isIndexed) {
|
||||
QVERIFY(hasSize);
|
||||
const qsizetype size = metaSequence.size(container);
|
||||
for (qsizetype i = 0; i < size; ++i) {
|
||||
metaSequence.elementAtIndex(container, i, var1.data());
|
||||
metaSequence.elementAtIndex(container, size - i - 1, var2.data());
|
||||
|
||||
metaSequence.setElementAtIndex(container, i, var2.constData());
|
||||
metaSequence.setElementAtIndex(container, size - i - 1, var1.constData());
|
||||
|
||||
metaSequence.elementAtIndex(container, i, var3.data());
|
||||
QCOMPARE(var3, var2);
|
||||
|
||||
metaSequence.elementAtIndex(container, size - i - 1, var3.data());
|
||||
QCOMPARE(var3, var1);
|
||||
}
|
||||
}
|
||||
|
||||
QVERIFY(metaSequence.hasIterator());
|
||||
QVERIFY(metaSequence.hasConstIterator());
|
||||
QVERIFY(metaSequence.canGetElementAtIterator());
|
||||
QVERIFY(metaSequence.canGetElementAtConstIterator());
|
||||
|
||||
void *it = metaSequence.begin(container);
|
||||
void *end = metaSequence.end(container);
|
||||
QVERIFY(it);
|
||||
QVERIFY(end);
|
||||
|
||||
void *constIt = metaSequence.constBegin(container);
|
||||
void *constEnd = metaSequence.constEnd(container);
|
||||
QVERIFY(constIt);
|
||||
QVERIFY(constEnd);
|
||||
|
||||
const qsizetype size = metaSequence.diffIterator(end, it);
|
||||
QCOMPARE(size, metaSequence.diffConstIterator(constEnd, constIt));
|
||||
if (hasSize)
|
||||
QCOMPARE(size, metaSequence.size(container));
|
||||
|
||||
qsizetype count = 0;
|
||||
for (; !metaSequence.compareIterator(it, end);
|
||||
metaSequence.advanceIterator(it, 1), metaSequence.advanceConstIterator(constIt, 1)) {
|
||||
metaSequence.elementAtIterator(it, var1.data());
|
||||
if (isIndexed) {
|
||||
metaSequence.elementAtIndex(container, count, var2.data());
|
||||
QCOMPARE(var1, var2);
|
||||
}
|
||||
metaSequence.elementAtConstIterator(constIt, var3.data());
|
||||
QCOMPARE(var3, var1);
|
||||
++count;
|
||||
}
|
||||
|
||||
QCOMPARE(count, size);
|
||||
QVERIFY(metaSequence.compareConstIterator(constIt, constEnd));
|
||||
|
||||
metaSequence.destroyIterator(it);
|
||||
metaSequence.destroyIterator(end);
|
||||
metaSequence.destroyConstIterator(constIt);
|
||||
metaSequence.destroyConstIterator(constEnd);
|
||||
|
||||
if (metaSequence.canSetElementAtIterator()) {
|
||||
void *it = metaSequence.begin(container);
|
||||
void *end = metaSequence.end(container);
|
||||
QVERIFY(it);
|
||||
QVERIFY(end);
|
||||
|
||||
for (; !metaSequence.compareIterator(it, end); metaSequence.advanceIterator(it, 1)) {
|
||||
metaSequence.elementAtIterator(it, var1.data());
|
||||
metaSequence.setElementAtIterator(it, var2.constData());
|
||||
metaSequence.elementAtIterator(it, var3.data());
|
||||
QCOMPARE(var2, var3);
|
||||
var2 = var1;
|
||||
}
|
||||
|
||||
metaSequence.destroyIterator(it);
|
||||
metaSequence.destroyIterator(end);
|
||||
}
|
||||
|
||||
if (metaSequence.hasBidirectionalIterator()) {
|
||||
void *it = metaSequence.end(container);
|
||||
void *end = metaSequence.begin(container);
|
||||
QVERIFY(it);
|
||||
QVERIFY(end);
|
||||
|
||||
void *constIt = metaSequence.constEnd(container);
|
||||
void *constEnd = metaSequence.constBegin(container);
|
||||
QVERIFY(constIt);
|
||||
QVERIFY(constEnd);
|
||||
|
||||
qsizetype size = 0;
|
||||
if (metaSequence.hasRandomAccessIterator()) {
|
||||
size = metaSequence.diffIterator(end, it);
|
||||
QCOMPARE(size, metaSequence.diffConstIterator(constEnd, constIt));
|
||||
} else {
|
||||
size = -metaSequence.diffIterator(it, end);
|
||||
}
|
||||
|
||||
if (hasSize)
|
||||
QCOMPARE(size, -metaSequence.size(container));
|
||||
|
||||
qsizetype count = 0;
|
||||
do {
|
||||
metaSequence.advanceIterator(it, -1);
|
||||
metaSequence.advanceConstIterator(constIt, -1);
|
||||
--count;
|
||||
|
||||
metaSequence.elementAtIterator(it, var1.data());
|
||||
if (isIndexed) {
|
||||
metaSequence.elementAtIndex(container, count - size, var2.data());
|
||||
QCOMPARE(var1, var2);
|
||||
}
|
||||
metaSequence.elementAtConstIterator(constIt, var3.data());
|
||||
QCOMPARE(var3, var1);
|
||||
} while (!metaSequence.compareIterator(it, end));
|
||||
|
||||
QCOMPARE(count, size);
|
||||
QVERIFY(metaSequence.compareConstIterator(constIt, constEnd));
|
||||
|
||||
metaSequence.destroyIterator(it);
|
||||
metaSequence.destroyIterator(end);
|
||||
metaSequence.destroyConstIterator(constIt);
|
||||
metaSequence.destroyConstIterator(constEnd);
|
||||
}
|
||||
|
||||
if (canInsertAtIterator) {
|
||||
void *it = metaSequence.begin(container);
|
||||
void *end = metaSequence.end(container);
|
||||
|
||||
const qsizetype size = metaSequence.diffIterator(end, it);
|
||||
metaSequence.destroyIterator(end);
|
||||
|
||||
metaSequence.insertElementAtIterator(container, it, var1.constData());
|
||||
metaSequence.destroyIterator(it);
|
||||
it = metaSequence.begin(container);
|
||||
metaSequence.insertElementAtIterator(container, it, var2.constData());
|
||||
metaSequence.destroyIterator(it);
|
||||
it = metaSequence.begin(container);
|
||||
metaSequence.insertElementAtIterator(container, it, var3.constData());
|
||||
|
||||
metaSequence.destroyIterator(it);
|
||||
|
||||
it = metaSequence.begin(container);
|
||||
end = metaSequence.end(container);
|
||||
|
||||
const qsizetype newSize = metaSequence.diffIterator(end, it);
|
||||
|
||||
if (metaSequence.isOrdered()) {
|
||||
QCOMPARE(newSize, size + 3);
|
||||
QVariant var4(metaType);
|
||||
metaSequence.elementAtIterator(it, var4.data());
|
||||
QCOMPARE(var4, var3);
|
||||
metaSequence.advanceIterator(it, 1);
|
||||
metaSequence.elementAtIterator(it, var4.data());
|
||||
QCOMPARE(var4, var2);
|
||||
metaSequence.advanceIterator(it, 1);
|
||||
metaSequence.elementAtIterator(it, var4.data());
|
||||
QCOMPARE(var4, var1);
|
||||
} else {
|
||||
QVERIFY(newSize >= size);
|
||||
}
|
||||
|
||||
if (canEraseAtIterator) {
|
||||
for (int i = 0; i < newSize; ++i) {
|
||||
metaSequence.destroyIterator(it);
|
||||
it = metaSequence.begin(container);
|
||||
metaSequence.eraseElementAtIterator(container, it);
|
||||
}
|
||||
|
||||
metaSequence.destroyIterator(it);
|
||||
it = metaSequence.begin(container);
|
||||
metaSequence.destroyIterator(end);
|
||||
end = metaSequence.end(container);
|
||||
QVERIFY(metaSequence.compareIterator(it, end));
|
||||
|
||||
metaSequence.addElement(container, var1.constData());
|
||||
metaSequence.addElement(container, var2.constData());
|
||||
metaSequence.addElement(container, var3.constData());
|
||||
}
|
||||
|
||||
metaSequence.destroyIterator(end);
|
||||
metaSequence.destroyIterator(it);
|
||||
}
|
||||
|
||||
QVERIFY(metaSequence.canClear());
|
||||
constIt = metaSequence.constBegin(container);
|
||||
constEnd = metaSequence.constEnd(container);
|
||||
QVERIFY(!metaSequence.compareConstIterator(constIt, constEnd));
|
||||
metaSequence.destroyConstIterator(constIt);
|
||||
metaSequence.destroyConstIterator(constEnd);
|
||||
|
||||
metaSequence.clear(container);
|
||||
constIt = metaSequence.constBegin(container);
|
||||
constEnd = metaSequence.constEnd(container);
|
||||
QVERIFY(metaSequence.compareConstIterator(constIt, constEnd));
|
||||
metaSequence.destroyConstIterator(constIt);
|
||||
metaSequence.destroyConstIterator(constEnd);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QMetaContainer)
|
||||
#include "tst_qmetacontainer.moc"
|
Loading…
Reference in New Issue
Block a user