1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include <QtCore/qsequentialiterable.h> |
41 | #include <QtCore/qvariant.h> |
42 | |
43 | #include <QtCore/private/qiterable_p.h> |
44 | |
45 | QT_BEGIN_NAMESPACE |
46 | |
47 | /*! |
48 | \class QSequentialIterable |
49 | \since 5.2 |
50 | \inmodule QtCore |
51 | \brief The QSequentialIterable class is an iterable interface for a container in a QVariant. |
52 | |
53 | This class allows several methods of accessing the values of a container held within |
54 | a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can |
55 | be converted to a QVariantList. |
56 | |
57 | \snippet code/src_corelib_kernel_qvariant.cpp 9 |
58 | |
59 | The container itself is not copied before iterating over it. |
60 | |
61 | \sa QVariant |
62 | */ |
63 | |
64 | /*! |
65 | \typedef QSequentialIterable::RandomAccessIterator |
66 | Exposes an iterator using std::random_access_iterator_tag. |
67 | */ |
68 | |
69 | /*! |
70 | \typedef QSequentialIterable::BidirectionalIterator |
71 | Exposes an iterator using std::bidirectional_iterator_tag. |
72 | */ |
73 | |
74 | /*! |
75 | \typedef QSequentialIterable::ForwardIterator |
76 | Exposes an iterator using std::forward_iterator_tag. |
77 | */ |
78 | |
79 | /*! |
80 | \typedef QSequentialIterable::InputIterator |
81 | Exposes an iterator using std::input_iterator_tag. |
82 | */ |
83 | |
84 | /*! |
85 | \typedef QSequentialIterable::RandomAccessConstIterator |
86 | Exposes a const_iterator using std::random_access_iterator_tag. |
87 | */ |
88 | |
89 | /*! |
90 | \typedef QSequentialIterable::BidirectionalConstIterator |
91 | Exposes a const_iterator using std::bidirectional_iterator_tag. |
92 | */ |
93 | |
94 | /*! |
95 | \typedef QSequentialIterable::ForwardConstIterator |
96 | Exposes a const_iterator using std::forward_iterator_tag. |
97 | */ |
98 | |
99 | /*! |
100 | \typedef QSequentialIterable::InputConstIterator |
101 | Exposes a const_iterator using std::input_iterator_tag. |
102 | */ |
103 | |
104 | /*! |
105 | Adds \a value to the container, at \a position, if possible. |
106 | */ |
107 | void QSequentialIterable::addValue(const QVariant &value, Position position) |
108 | { |
109 | QtPrivate::QVariantTypeCoercer coercer; |
110 | const void *valuePtr = coercer.coerce(value, metaContainer().valueMetaType()); |
111 | |
112 | switch (position) { |
113 | case AtBegin: |
114 | if (metaContainer().canAddValueAtBegin()) |
115 | metaContainer().addValueAtBegin(mutableIterable(), valuePtr); |
116 | break; |
117 | case AtEnd: |
118 | if (metaContainer().canAddValueAtEnd()) |
119 | metaContainer().addValueAtEnd(mutableIterable(), valuePtr); |
120 | break; |
121 | case Unspecified: |
122 | if (metaContainer().canAddValue()) |
123 | metaContainer().addValue(mutableIterable(), valuePtr); |
124 | break; |
125 | } |
126 | } |
127 | |
128 | /*! |
129 | Removes a value from the container, at \a position, if possible. |
130 | */ |
131 | void QSequentialIterable::removeValue(Position position) |
132 | { |
133 | switch (position) { |
134 | case AtBegin: |
135 | if (metaContainer().canRemoveValueAtBegin()) |
136 | metaContainer().removeValueAtBegin(mutableIterable()); |
137 | break; |
138 | case AtEnd: |
139 | if (metaContainer().canRemoveValueAtEnd()) |
140 | metaContainer().removeValueAtEnd(mutableIterable()); |
141 | break; |
142 | case Unspecified: |
143 | if (metaContainer().canRemoveValue()) |
144 | metaContainer().removeValue(mutableIterable()); |
145 | break; |
146 | } |
147 | } |
148 | |
149 | QMetaType QSequentialIterable::valueMetaType() const |
150 | { |
151 | return QMetaType(metaContainer().valueMetaType()); |
152 | } |
153 | |
154 | /*! |
155 | Returns the value at position \a idx in the container. |
156 | */ |
157 | QVariant QSequentialIterable::at(qsizetype idx) const |
158 | { |
159 | QVariant v(valueMetaType()); |
160 | void *dataPtr; |
161 | if (valueMetaType() == QMetaType::fromType<QVariant>()) |
162 | dataPtr = &v; |
163 | else |
164 | dataPtr = v.data(); |
165 | |
166 | const QMetaSequence meta = metaContainer(); |
167 | if (meta.canGetValueAtIndex()) { |
168 | meta.valueAtIndex(m_iterable.constPointer(), idx, dataPtr); |
169 | } else if (meta.canGetValueAtConstIterator()) { |
170 | void *iterator = meta.constBegin(m_iterable.constPointer()); |
171 | meta.advanceConstIterator(iterator, idx); |
172 | meta.valueAtConstIterator(iterator, dataPtr); |
173 | meta.destroyConstIterator(iterator); |
174 | } |
175 | |
176 | return v; |
177 | } |
178 | |
179 | /*! |
180 | Sets the element at position \a idx in the container to \a value. |
181 | */ |
182 | void QSequentialIterable::set(qsizetype idx, const QVariant &value) |
183 | { |
184 | QtPrivate::QVariantTypeCoercer coercer; |
185 | const void *dataPtr = coercer.coerce(value, metaContainer().valueMetaType()); |
186 | |
187 | const QMetaSequence meta = metaContainer(); |
188 | if (meta.canSetValueAtIndex()) { |
189 | meta.setValueAtIndex(m_iterable.mutablePointer(), idx, dataPtr); |
190 | } else if (meta.canSetValueAtIterator()) { |
191 | void *iterator = meta.begin(m_iterable.mutablePointer()); |
192 | meta.advanceIterator(iterator, idx); |
193 | meta.setValueAtIterator(iterator, dataPtr); |
194 | meta.destroyIterator(iterator); |
195 | } |
196 | } |
197 | |
198 | /*! |
199 | \class QSequentialIterable::const_iterator |
200 | \since 5.2 |
201 | \inmodule QtCore |
202 | \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant. |
203 | |
204 | A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance, |
205 | and can be used in a way similar to other stl-style iterators. |
206 | |
207 | \snippet code/src_corelib_kernel_qvariant.cpp 9 |
208 | |
209 | \sa QSequentialIterable |
210 | */ |
211 | |
212 | /*! |
213 | \class QSequentialIterable::iterator |
214 | \since 6.0 |
215 | \inmodule QtCore |
216 | \brief The QSequentialIterable::iterator allows iteration over a container in a QVariant. |
217 | |
218 | A QSequentialIterable::iterator can only be created by a QSequentialIterable instance, |
219 | and can be used in a way similar to other stl-style iterators. |
220 | |
221 | \sa QSequentialIterable |
222 | */ |
223 | |
224 | /*! |
225 | Returns the current item, converted to a QVariantRef. |
226 | */ |
227 | QVariantRef<QSequentialIterator> QSequentialIterator::operator*() const |
228 | { |
229 | return QVariantRef<QSequentialIterator>(this); |
230 | } |
231 | |
232 | /*! |
233 | Returns the current item, converted to a QVariantPointer. |
234 | */ |
235 | QVariantPointer<QSequentialIterator> QSequentialIterator::operator->() const |
236 | { |
237 | return QVariantPointer<QSequentialIterator>(this); |
238 | } |
239 | |
240 | /*! |
241 | Returns the current item, converted to a QVariant. |
242 | */ |
243 | QVariant QSequentialConstIterator::operator*() const |
244 | { |
245 | return QIterablePrivate::retrieveElement(metaContainer().valueMetaType(), [this](void *dataPtr) { |
246 | metaContainer().valueAtConstIterator(constIterator(), dataPtr); |
247 | }); |
248 | } |
249 | |
250 | /*! |
251 | Returns the current item, converted to a QVariantConstPointer. |
252 | */ |
253 | QVariantConstPointer QSequentialConstIterator::operator->() const |
254 | { |
255 | return QVariantConstPointer(operator*()); |
256 | } |
257 | |
258 | QT_END_NAMESPACE |
259 | |