1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QASSOCIATIVEITERABLE_H
5#define QASSOCIATIVEITERABLE_H
6
7#include <QtCore/qiterable.h>
8#include <QtCore/qvariant.h>
9
10QT_BEGIN_NAMESPACE
11
12class Q_CORE_EXPORT QAssociativeIterator : public QIterator<QMetaAssociation>
13{
14public:
15 using key_type = QVariant;
16 using mapped_type = QVariant;
17 using reference = QVariantRef<QAssociativeIterator>;
18 using pointer = QVariantPointer<QAssociativeIterator>;
19
20 QAssociativeIterator(QIterator &&it)
21 : QIterator(std::move(it))
22 {}
23
24 QVariant key() const;
25 QVariantRef<QAssociativeIterator> value() const;
26
27 QVariantRef<QAssociativeIterator> operator*() const;
28 QVariantPointer<QAssociativeIterator> operator->() const;
29};
30
31class Q_CORE_EXPORT QAssociativeConstIterator : public QConstIterator<QMetaAssociation>
32{
33public:
34 using key_type = QVariant;
35 using mapped_type = QVariant;
36 using reference = const QVariant &;
37 using pointer = QVariantConstPointer;
38
39 QAssociativeConstIterator(QConstIterator &&it)
40 : QConstIterator(std::move(it))
41 {}
42
43 QVariant key() const;
44 QVariant value() const;
45
46 QVariant operator*() const;
47 QVariantConstPointer operator->() const;
48};
49
50class Q_CORE_EXPORT QAssociativeIterable : public QIterable<QMetaAssociation>
51{
52public:
53 using iterator = QTaggedIterator<QAssociativeIterator, void>;
54 using const_iterator = QTaggedIterator<QAssociativeConstIterator, void>;
55
56 using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
57 using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
58 using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
59 using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
60
61 using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
62 using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
63 using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
64 using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
65
66 template<class T>
67 QAssociativeIterable(const T *p)
68 : QIterable(QMetaAssociation::fromContainer<T>(), p)
69 {
70 }
71
72 template<class T>
73 QAssociativeIterable(T *p)
74 : QIterable(QMetaAssociation::fromContainer<T>(), p)
75 {
76 }
77
78 QAssociativeIterable()
79 : QIterable(QMetaAssociation(), nullptr)
80 {
81 }
82
83 template<typename Pointer>
84 QAssociativeIterable(const QMetaAssociation &metaAssociation, Pointer iterable)
85 : QIterable(metaAssociation, iterable)
86 {
87 }
88
89 // ### Qt7: Pass QMetaType as value rather than const ref.
90 QAssociativeIterable(const QMetaAssociation &metaAssociation, const QMetaType &metaType,
91 void *iterable)
92 : QIterable(metaAssociation, metaType.alignOf(), iterable)
93 {
94 }
95
96 // ### Qt7: Pass QMetaType as value rather than const ref.
97 QAssociativeIterable(const QMetaAssociation &metaAssociation, const QMetaType &metaType,
98 const void *iterable)
99 : QIterable(metaAssociation, metaType.alignOf(), iterable)
100 {
101 }
102
103 QAssociativeIterable(QIterable<QMetaAssociation> &&other) : QIterable(std::move(other)) {}
104
105 QAssociativeIterable &operator=(QIterable<QMetaAssociation> &&other)
106 {
107 QIterable::operator=(std::move(other));
108 return *this;
109 }
110
111 const_iterator begin() const { return constBegin(); }
112 const_iterator end() const { return constEnd(); }
113
114 const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
115 const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
116
117 iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
118 iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
119
120 const_iterator find(const QVariant &key) const;
121 const_iterator constFind(const QVariant &key) const { return find(key); }
122 iterator mutableFind(const QVariant &key);
123
124 bool containsKey(const QVariant &key);
125 void insertKey(const QVariant &key);
126 void removeKey(const QVariant &key);
127
128 QVariant value(const QVariant &key) const;
129 void setValue(const QVariant &key, const QVariant &mapped);
130};
131
132template<>
133inline QVariantRef<QAssociativeIterator>::operator QVariant() const
134{
135 if (m_pointer == nullptr)
136 return QVariant();
137
138 const auto metaAssociation = m_pointer->metaContainer();
139 const QMetaType metaType(metaAssociation.mappedMetaType());
140 if (!metaType.isValid())
141 return m_pointer->key();
142
143 QVariant v(metaType);
144 metaAssociation.mappedAtIterator(iterator: m_pointer->constIterator(),
145 mapped: metaType == QMetaType::fromType<QVariant>() ? &v : v.data());
146 return v;
147}
148
149template<>
150inline QVariantRef<QAssociativeIterator> &QVariantRef<QAssociativeIterator>::operator=(
151 const QVariant &value)
152{
153 if (m_pointer == nullptr)
154 return *this;
155
156 const auto metaAssociation = m_pointer->metaContainer();
157 const QMetaType metaType(metaAssociation.mappedMetaType());
158 if (metaType.isValid()) {
159 QtPrivate::QVariantTypeCoercer coercer;
160 metaAssociation.setMappedAtIterator(iterator: m_pointer->constIterator(),
161 mapped: coercer.coerce(value, type: metaType));
162 }
163
164 return *this;
165}
166
167Q_DECLARE_TYPEINFO(QAssociativeIterable, Q_RELOCATABLE_TYPE);
168Q_DECLARE_TYPEINFO(QAssociativeIterable::iterator, Q_RELOCATABLE_TYPE);
169Q_DECLARE_TYPEINFO(QAssociativeIterable::const_iterator, Q_RELOCATABLE_TYPE);
170
171QT_END_NAMESPACE
172
173#endif // QASSOCIATIVEITERABLE_H
174

source code of qtbase/src/corelib/kernel/qassociativeiterable.h