/**************************************************************************** ** ** 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