// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QMETAASSOCIATION_H #define QMETAASSOCIATION_H #if 0 #pragma qt_class(QMetaAssociation) #endif #include #include #include #include QT_BEGIN_NAMESPACE namespace QtMetaContainerPrivate { class AssociativeIterator : public QIterator { public: using key_type = QVariant; using mapped_type = QVariant; using reference = QVariant::Reference; using pointer = QVariant::Pointer; static constexpr bool CanNoexceptAssignQVariant = false; static constexpr bool CanNoexceptConvertToQVariant = false; AssociativeIterator(QIterator &&it) : QIterator(std::move(it)) {} key_type key() const { const QMetaAssociation meta = metaContainer(); return QIterablePrivate::retrieveElement(meta.keyMetaType(), [&](void *dataPtr) { meta.keyAtIterator(constIterator(), dataPtr); }); } reference value() const { return operator*(); } reference operator*() const { return reference(*this); } pointer operator->() const { return pointer(*this); } }; class AssociativeConstIterator : public QConstIterator { public: using key_type = QVariant; using mapped_type = QVariant; using reference = QVariant::ConstReference; using pointer = QVariant::ConstPointer; static constexpr bool CanNoexceptConvertToQVariant = false; AssociativeConstIterator(QConstIterator &&it) : QConstIterator(std::move(it)) {} key_type key() const { const QMetaAssociation meta = metaContainer(); return QIterablePrivate::retrieveElement(meta.keyMetaType(), [&](void *dataPtr) { meta.keyAtConstIterator(constIterator(), dataPtr); }); } mapped_type value() const { return operator*(); } mapped_type operator*() const; pointer operator->() const { return pointer(*this); } }; } // namespace QtMetaContainerPrivate namespace QtPrivate { template QVariant associativeIteratorToVariant(const Referred &referred) { const auto metaAssociation = referred.metaContainer(); const QMetaType metaType(metaAssociation.mappedMetaType()); if (metaType.isValid(QT6_CALL_NEW_OVERLOAD)) { return QIterablePrivate::retrieveElement(metaType, [&](void *dataPtr) { metaAssociation.mappedAtConstIterator(referred.constIterator(), dataPtr); }); } return QIterablePrivate::retrieveElement(metaType, [&](void *dataPtr) { metaAssociation.keyAtConstIterator(referred.constIterator(), dataPtr); }); } } // namespace QtPrivate template<> inline QVariant::Reference::operator QVariant() const { return QtPrivate::associativeIteratorToVariant(m_referred); } template<> inline QVariant::Reference & QVariant::Reference::operator=(const QVariant &value) { const auto metaAssociation = m_referred.metaContainer(); const QMetaType metaType(metaAssociation.mappedMetaType()); if (!metaType.isValid(QT6_CALL_NEW_OVERLOAD)) return *this; QtPrivate::QVariantTypeCoercer coercer; metaAssociation.setMappedAtIterator( m_referred.constIterator(), coercer.coerce(value, metaType)); return *this; } template<> inline QVariant::ConstReference::operator QVariant() const { return QtPrivate::associativeIteratorToVariant(m_referred); } namespace QtMetaContainerPrivate { inline AssociativeConstIterator::mapped_type AssociativeConstIterator::operator*() const { return reference(*this); } class Association : public QIterable { public: using Iterator = QTaggedIterator; using RandomAccessIterator = QTaggedIterator; using BidirectionalIterator = QTaggedIterator; using ForwardIterator = QTaggedIterator; using InputIterator = QTaggedIterator; using ConstIterator = QTaggedIterator; using RandomAccessConstIterator = QTaggedIterator; using BidirectionalConstIterator = QTaggedIterator; using ForwardConstIterator = QTaggedIterator; using InputConstIterator = QTaggedIterator; using iterator = Iterator; using const_iterator = ConstIterator; template Association(const T *p) : QIterable(QMetaAssociation::fromContainer(), p) {} template Association(T *p) : QIterable(QMetaAssociation::fromContainer(), p) {} Association() : QIterable(QMetaAssociation(), nullptr) {} template Association(const QMetaAssociation &metaAssociation, Pointer iterable) : QIterable(metaAssociation, iterable) { } Association(const QMetaAssociation &metaAssociation, QMetaType metaType, void *iterable) : QIterable(metaAssociation, metaType.alignOf(), iterable) { } Association(const QMetaAssociation &metaAssociation, QMetaType metaType, const void *iterable) : QIterable(metaAssociation, metaType.alignOf(), iterable) { } Association(QIterable &&other) : QIterable(std::move(other)) {} Association &operator=(QIterable &&other) { QIterable::operator=(std::move(other)); return *this; } ConstIterator begin() const { return constBegin(); } ConstIterator end() const { return constEnd(); } ConstIterator constBegin() const { return ConstIterator(QIterable::constBegin()); } ConstIterator constEnd() const { return ConstIterator(QIterable::constEnd()); } Iterator mutableBegin() { return Iterator(QIterable::mutableBegin()); } Iterator mutableEnd() { return Iterator(QIterable::mutableEnd()); } ConstIterator find(const QVariant &key) const { const QMetaAssociation meta = metaContainer(); QtPrivate::QVariantTypeCoercer coercer; if (const void *keyData = coercer.convert(key, meta.keyMetaType())) { return ConstIterator(QConstIterator( this, meta.createConstIteratorAtKey(constIterable(), keyData))); } return constEnd(); } ConstIterator constFind(const QVariant &key) const { return find(key); } Iterator mutableFind(const QVariant &key) { const QMetaAssociation meta = metaContainer(); QtPrivate::QVariantTypeCoercer coercer; if (const void *keyData = coercer.convert(key, meta.keyMetaType())) return Iterator(QIterator(this, meta.createIteratorAtKey(mutableIterable(), keyData))); return mutableEnd(); } bool containsKey(const QVariant &key) const { const QMetaAssociation meta = metaContainer(); QtPrivate::QVariantTypeCoercer keyCoercer; if (const void *keyData = keyCoercer.convert(key, meta.keyMetaType())) return meta.containsKey(constIterable(), keyData); return false; } void insertKey(const QVariant &key) { const QMetaAssociation meta = metaContainer(); QtPrivate::QVariantTypeCoercer keyCoercer; meta.insertKey(mutableIterable(), keyCoercer.coerce(key, meta.keyMetaType())); } void removeKey(const QVariant &key) { const QMetaAssociation meta = metaContainer(); QtPrivate::QVariantTypeCoercer keyCoercer; meta.removeKey(mutableIterable(), keyCoercer.coerce(key, meta.keyMetaType())); } QVariant value(const QVariant &key) const { const QMetaAssociation meta = metaContainer(); return QIterablePrivate::retrieveElement(meta.mappedMetaType(), [&](void *dataPtr) { QtPrivate::QVariantTypeCoercer coercer; meta.mappedAtKey(constIterable(), coercer.coerce(key, meta.keyMetaType()), dataPtr); }); } void setValue(const QVariant &key, const QVariant &mapped) { const QMetaAssociation meta = metaContainer(); QtPrivate::QVariantTypeCoercer keyCoercer; QtPrivate::QVariantTypeCoercer mappedCoercer; meta.setMappedAtKey(mutableIterable(), keyCoercer.coerce(key, meta.keyMetaType()), mappedCoercer.coerce(mapped, meta.mappedMetaType())); } }; } // namespace QtMetaContainerPrivate QT_END_NAMESPACE #endif // QMETAASSOCIATION_H