From 4fbb2f66d6144953837361e808845edb181b124e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 25 Aug 2020 11:58:09 +0200 Subject: 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 --- src/corelib/.prev_CMakeLists.txt | 2 + src/corelib/CMakeLists.txt | 2 + src/corelib/global/global.pri | 1 + src/corelib/global/qcontainerinfo.h | 150 +++++++ src/corelib/kernel/kernel.pri | 2 + src/corelib/kernel/qmetacontainer.cpp | 697 +++++++++++++++++++++++++++++++ src/corelib/kernel/qmetacontainer.h | 594 ++++++++++++++++++++++++++ src/tools/bootstrap/.prev_CMakeLists.txt | 1 + src/tools/bootstrap/CMakeLists.txt | 1 + src/tools/bootstrap/bootstrap.pro | 1 + 10 files changed, 1451 insertions(+) create mode 100644 src/corelib/global/qcontainerinfo.h create mode 100644 src/corelib/kernel/qmetacontainer.cpp create mode 100644 src/corelib/kernel/qmetacontainer.h (limited to 'src') diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt index 747a0d75df..91e73b6c5d 100644 --- a/src/corelib/.prev_CMakeLists.txt +++ b/src/corelib/.prev_CMakeLists.txt @@ -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 diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 8181250692..04021c8d29 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -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 diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 6ba39d41bd..e799e13e4c 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -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 \ diff --git a/src/corelib/global/qcontainerinfo.h b/src/corelib/global/qcontainerinfo.h new file mode 100644 index 0000000000..ad3ef301e4 --- /dev/null +++ b/src/corelib/global/qcontainerinfo.h @@ -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 +#include + +QT_BEGIN_NAMESPACE + +namespace QContainerTraits +{ + +template +using value_type = typename C::value_type; + +template +using iterator = typename C::iterator; + +template +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 +constexpr bool has_size_v = false; +template +constexpr bool has_size_v> = true; + +template +constexpr bool has_clear_v = false; +template +constexpr bool has_clear_v> = true; + +template +constexpr bool has_at_v = false; +template +constexpr bool has_at_v> = true; + +template +constexpr bool can_get_at_index_v = false; +template +constexpr bool can_get_at_index_v(decltype(C()[0]))>> = true; + +template +constexpr bool can_set_at_index_v = false; +template +constexpr bool can_set_at_index_v())>> = true; + +template +constexpr bool has_push_front_v = false; +template +constexpr bool has_push_front_v()))>> = true; + +template +constexpr bool has_push_back_v = false; +template +constexpr bool has_push_back_v()))>> = true; + +template +constexpr bool has_insert_v = false; +template +constexpr bool has_insert_v()))>> = true; + +template +constexpr bool has_pop_front_v = false; +template +constexpr bool has_pop_front_v> = true; + +template +constexpr bool has_pop_back_v = false; +template +constexpr bool has_pop_back_v> = true; + +template +constexpr bool has_iterator_v = false; +template +constexpr bool has_iterator_v>> = true; + +template +constexpr bool has_const_iterator_v = false; +template +constexpr bool has_const_iterator_v>> = true; + +template +constexpr bool can_get_at_iterator_v = false; +template +constexpr bool can_get_at_iterator_v(decltype(*C().begin()))>> = true; + +template +constexpr bool can_set_at_iterator_v = false; +template +constexpr bool can_set_at_iterator_v())>> = true; + +template +constexpr bool can_insert_at_iterator_v = false; +template +constexpr bool can_insert_at_iterator_v()))>> = true; + +template +constexpr bool can_erase_at_iterator_v = false; +template +constexpr bool can_erase_at_iterator_v> = true; + +QT_WARNING_POP + +} + +QT_END_NAMESPACE + +#endif // QCONTAINERINFO_H diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 036230e11f..420f0222e4 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -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 \ diff --git a/src/corelib/kernel/qmetacontainer.cpp b/src/corelib/kernel/qmetacontainer.cpp new file mode 100644 index 0000000000..cfe837bef8 --- /dev/null +++ b/src/corelib/kernel/qmetacontainer.cpp @@ -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 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 diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h new file mode 100644 index 0000000000..c663d1ce24 --- /dev/null +++ b/src/corelib/kernel/qmetacontainer.h @@ -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 +#include +#include +#include + +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 +class QMetaSequenceForContainer +{ + template + static constexpr IteratorCapabilities capabilitiesForIterator() + { + using Tag = typename std::iterator_traits::iterator_category; + IteratorCapabilities caps {}; + if constexpr (std::is_base_of_v) + caps |= ForwardCapability; + if constexpr (std::is_base_of_v) + caps |= BiDirectionalCapability; + if constexpr (std::is_base_of_v) + caps |= RandomAccessCapability; + return caps; + } + + static constexpr IteratorCapabilities getIteratorCapabilities() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) + return capabilitiesForIterator>(); + else if constexpr (QContainerTraits::has_const_iterator_v) + return capabilitiesForIterator>(); + else + return {}; + } + + static constexpr QMetaSequenceInterface::Position getAddRemovePosition() + { + if constexpr (QContainerTraits::has_push_back_v && QContainerTraits::has_pop_back_v) + return QMetaSequenceInterface::AtEnd; + if constexpr (QContainerTraits::has_push_front_v && QContainerTraits::has_pop_front_v) + return QMetaSequenceInterface::AtBegin; + return QMetaSequenceInterface::Random; + } + + static constexpr QMetaType getValueMetaType() + { + return QMetaType::fromType(); + } + + static constexpr QMetaSequenceInterface::SizeFn getSizeFn() + { + if constexpr (QContainerTraits::has_size_v) { + return [](const void *c) -> qsizetype { return static_cast(c)->size(); }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::ClearFn getClearFn() + { + if constexpr (QContainerTraits::has_clear_v) { + return [](void *c) { return static_cast(c)->clear(); }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::ElementAtIndexFn getElementAtIndexFn() + { + if constexpr (QContainerTraits::has_at_v) { + return [](const void *c, qsizetype i, void *r) { + *static_cast *>(r) + = static_cast(c)->at(i); + }; + } else if constexpr (QContainerTraits::can_get_at_index_v) { + return [](const void *c, qsizetype i, void *r) { + *static_cast *>(r) + = (*static_cast(c))[i]; + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::SetElementAtIndexFn getSetElementAtIndexFn() + { + if constexpr (QContainerTraits::can_set_at_index_v) { + return [](void *c, qsizetype i, const void *e) { + (*static_cast(c))[i] + = *static_cast *>(e); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::AddElementFn getAddElementFn() + { + if constexpr (QContainerTraits::has_push_back_v) { + return [](void *c, const void *v) { + static_cast(c)->push_back( + *static_cast *>(v)); + }; + } else if constexpr (QContainerTraits::has_push_front_v) { + return [](void *c, const void *v) { + static_cast(c)->push_front( + *static_cast *>(v)); + }; + } else if constexpr (QContainerTraits::has_insert_v) { + return [](void *c, const void *v) { + static_cast(c)->insert( + *static_cast *>(v)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::RemoveElementFn getRemoveElementFn() + { + if constexpr (QContainerTraits::has_pop_back_v) { + return [](void *c) { static_cast(c)->pop_back(); }; + } else if constexpr (QContainerTraits::has_pop_front_v) { + return [](void *c) { static_cast(c)->pop_front(); }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::CreateIteratorFn getCreateIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](void *c, QMetaSequenceInterface::Position p) -> void* { + using Iterator = QContainerTraits::iterator; + switch (p) { + case QMetaSequenceInterface::AtBegin: + case QMetaSequenceInterface::Random: + return new Iterator(static_cast(c)->begin()); + break; + case QMetaSequenceInterface::AtEnd: + return new Iterator(static_cast(c)->end()); + break; + } + return nullptr; + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](const void *i) { + using Iterator = QContainerTraits::iterator; + delete static_cast(i); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](const void *i, const void *j) { + using Iterator = QContainerTraits::iterator; + return *static_cast(i) == *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](void *i, const void *j) { + using Iterator = QContainerTraits::iterator; + *static_cast(i) = *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](void *i, qsizetype step) { + std::advance(*static_cast *>(i), step); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](const void *i, const void *j) -> qsizetype { + return std::distance(*static_cast *>(j), + *static_cast *>(i)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::ElementAtIteratorFn getElementAtIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v + && QContainerTraits::can_get_at_iterator_v && !std::is_const_v) { + return [](const void *i, void *r) { + *static_cast *>(r) = + *(*static_cast *>(i)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::SetElementAtIteratorFn getSetElementAtIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v + && QContainerTraits::can_set_at_iterator_v && !std::is_const_v) { + return [](const void *i, const void *e) { + *(*static_cast *>(i)) + = *static_cast *>(e); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::InsertElementAtIteratorFn getInsertElementAtIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v + && QContainerTraits::can_insert_at_iterator_v && !std::is_const_v) { + return [](void *c, const void *i, const void *e) { + static_cast(c)->insert( + *static_cast *>(i), + *static_cast *>(e)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::EraseElementAtIteratorFn getEraseElementAtIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v + && QContainerTraits::can_erase_at_iterator_v && !std::is_const_v) { + return [](void *c, const void *i) { + static_cast(c)->erase(*static_cast *>(i)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::CreateConstIteratorFn getCreateConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *c, QMetaSequenceInterface::Position p) -> void* { + using Iterator = QContainerTraits::const_iterator; + switch (p) { + case QMetaSequenceInterface::AtBegin: + case QMetaSequenceInterface::Random: + return new Iterator(static_cast(c)->begin()); + break; + case QMetaSequenceInterface::AtEnd: + return new Iterator(static_cast(c)->end()); + break; + } + return nullptr; + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *i) { + using Iterator = QContainerTraits::const_iterator; + delete static_cast(i); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *i, const void *j) { + using Iterator = QContainerTraits::const_iterator; + return *static_cast(i) == *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](void *i, const void *j) { + using Iterator = QContainerTraits::const_iterator; + *static_cast(i) = *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](void *i, qsizetype step) { + std::advance(*static_cast *>(i), step); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *i, const void *j) -> qsizetype { + return std::distance(*static_cast *>(j), + *static_cast *>(i)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaSequenceInterface::ElementAtIteratorFn getElementAtConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v + && QContainerTraits::can_get_at_iterator_v) { + return [](const void *i, void *r) { + *static_cast *>(r) = + *(*static_cast *>(i)); + }; + } else { + return nullptr; + } + } + +public: + static QMetaSequenceInterface metaSequence; +}; + +template +QMetaSequenceInterface QMetaSequenceForContainer::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 +constexpr QMetaSequenceInterface *qMetaSequenceInterfaceForContainer() +{ + return &QMetaSequenceForContainer::metaSequence; +} + +} // namespace QtMetaContainerPrivate + +class Q_CORE_EXPORT QMetaSequence +{ +public: + QMetaSequence() = default; + explicit QMetaSequence(QtMetaContainerPrivate::QMetaSequenceInterface *d) : d_ptr(d) {} + + template + static constexpr QMetaSequence fromContainer() + { + return QMetaSequence(QtMetaContainerPrivate::qMetaSequenceInterfaceForContainer()); + } + + 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 diff --git a/src/tools/bootstrap/.prev_CMakeLists.txt b/src/tools/bootstrap/.prev_CMakeLists.txt index a69351a167..a4bb4f6aac 100644 --- a/src/tools/bootstrap/.prev_CMakeLists.txt +++ b/src/tools/bootstrap/.prev_CMakeLists.txt @@ -75,6 +75,7 @@ qt_add_module(Bootstrap ../../corelib/io/qurlrecode.cpp ../../corelib/kernel/qcoreapplication.cpp ../../corelib/kernel/qcoreglobaldata.cpp + ../../corelib/kernel/qmetacontainer.cpp ../../corelib/kernel/qmetatype.cpp ../../corelib/kernel/qsharedmemory.cpp ../../corelib/kernel/qsystemerror.cpp diff --git a/src/tools/bootstrap/CMakeLists.txt b/src/tools/bootstrap/CMakeLists.txt index 56b1bcbbcf..f5b1c38c39 100644 --- a/src/tools/bootstrap/CMakeLists.txt +++ b/src/tools/bootstrap/CMakeLists.txt @@ -76,6 +76,7 @@ qt_extend_target(Bootstrap ../../corelib/io/qurlrecode.cpp ../../corelib/kernel/qcoreapplication.cpp ../../corelib/kernel/qcoreglobaldata.cpp + ../../corelib/kernel/qmetacontainer.cpp ../../corelib/kernel/qmetatype.cpp ../../corelib/kernel/qsharedmemory.cpp ../../corelib/kernel/qsystemerror.cpp diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 999ceea840..1853ab74b4 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -62,6 +62,7 @@ SOURCES += \ ../../corelib/io/qurlrecode.cpp \ ../../corelib/kernel/qcoreapplication.cpp \ ../../corelib/kernel/qcoreglobaldata.cpp \ + ../../corelib/kernel/qmetacontainer.cpp \ ../../corelib/kernel/qmetatype.cpp \ ../../corelib/kernel/qvariant.cpp \ ../../corelib/kernel/qsystemerror.cpp \ -- cgit v1.2.3