Revision control

Copy as Markdown

// 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
// Qt-Security score:significant reason:default
#ifndef QMETAASSOCIATION_H
#define QMETAASSOCIATION_H
#if 0
#pragma qt_class(QMetaAssociation)
#endif
#include <QtCore/qiterable.h>
#include <QtCore/qiterable_impl.h>
#include <QtCore/qmetacontainer.h>
#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
namespace QtMetaContainerPrivate {
class AssociativeIterator : public QIterator<QMetaAssociation>
{
public:
using key_type = QVariant;
using mapped_type = QVariant;
using reference = QVariant::Reference<AssociativeIterator>;
using pointer = QVariant::Pointer<AssociativeIterator>;
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 QtIterablePrivate::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<QMetaAssociation>
{
public:
using key_type = QVariant;
using mapped_type = QVariant;
using reference = QVariant::ConstReference<AssociativeConstIterator>;
using pointer = QVariant::ConstPointer<AssociativeConstIterator>;
static constexpr bool CanNoexceptConvertToQVariant = false;
AssociativeConstIterator(QConstIterator &&it) : QConstIterator(std::move(it)) {}
key_type key() const
{
const QMetaAssociation meta = metaContainer();
return QtIterablePrivate::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<typename Indirect>
QVariant associativeIteratorToVariant(const Indirect &referred)
{
const auto metaAssociation = referred.metaContainer();
const QMetaType metaType(metaAssociation.mappedMetaType());
if (metaType.isValid(QT6_CALL_NEW_OVERLOAD)) {
return QtIterablePrivate::retrieveElement(metaType, [&](void *dataPtr) {
metaAssociation.mappedAtConstIterator(referred.constIterator(), dataPtr);
});
}
return QtIterablePrivate::retrieveElement(metaType, [&](void *dataPtr) {
metaAssociation.keyAtConstIterator(referred.constIterator(), dataPtr);
});
}
} // namespace QtPrivate
template<>
inline QVariant::Reference<QtMetaContainerPrivate::AssociativeIterator>::operator QVariant() const
{
return QtPrivate::associativeIteratorToVariant(m_referred);
}
template<>
inline QVariant::Reference<QtMetaContainerPrivate::AssociativeIterator> &
QVariant::Reference<QtMetaContainerPrivate::AssociativeIterator>::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<QtMetaContainerPrivate::AssociativeConstIterator>::operator QVariant() const
{
return QtPrivate::associativeIteratorToVariant(m_referred);
}
namespace QtMetaContainerPrivate {
inline AssociativeConstIterator::mapped_type AssociativeConstIterator::operator*() const
{
return reference(*this);
}
class Association : public QIterable<QMetaAssociation>
{
public:
using Iterator
= QTaggedIterator<AssociativeIterator, void>;
using RandomAccessIterator
= QTaggedIterator<AssociativeIterator, std::random_access_iterator_tag>;
using BidirectionalIterator
= QTaggedIterator<AssociativeIterator, std::bidirectional_iterator_tag>;
using ForwardIterator
= QTaggedIterator<AssociativeIterator, std::forward_iterator_tag>;
using InputIterator
= QTaggedIterator<AssociativeIterator, std::input_iterator_tag>;
using ConstIterator
= QTaggedIterator<AssociativeConstIterator, void>;
using RandomAccessConstIterator
= QTaggedIterator<AssociativeConstIterator, std::random_access_iterator_tag>;
using BidirectionalConstIterator
= QTaggedIterator<AssociativeConstIterator, std::bidirectional_iterator_tag>;
using ForwardConstIterator
= QTaggedIterator<AssociativeConstIterator, std::forward_iterator_tag>;
using InputConstIterator
= QTaggedIterator<AssociativeConstIterator, std::input_iterator_tag>;
using iterator = Iterator;
using const_iterator = ConstIterator;
template<class T>
Association(const T *p) : QIterable(QMetaAssociation::fromContainer<T>(), p) {}
template<class T>
Association(T *p) : QIterable(QMetaAssociation::fromContainer<T>(), p) {}
Association() : QIterable(QMetaAssociation(), nullptr) {}
template<typename Pointer>
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<QMetaAssociation> &&other)
: QIterable(std::move(other))
{}
Association &operator=(QIterable<QMetaAssociation> &&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<QMetaAssociation>(
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 QtIterablePrivate::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