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#ifndef QMETACONTAINER_H
41#define QMETACONTAINER_H
42
43#include <QtCore/qcontainerinfo.h>
44#include <QtCore/qflags.h>
45#include <QtCore/qglobal.h>
46
47QT_BEGIN_NAMESPACE
48
49class QMetaType;
50namespace QtPrivate {
51class QMetaTypeInterface;
52template<typename T>
53constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
54}
55
56namespace QtMetaContainerPrivate {
57
58enum IteratorCapability : quint8 {
59 InputCapability = 1 << 0,
60 ForwardCapability = 1 << 1,
61 BiDirectionalCapability = 1 << 2,
62 RandomAccessCapability = 1 << 3,
63};
64
65Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
66Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
67
68enum AddRemoveCapability : quint8 {
69 CanAddAtBegin = 1 << 0,
70 CanRemoveAtBegin = 1 << 1,
71 CanAddAtEnd = 1 << 2,
72 CanRemoveAtEnd = 1 << 3
73};
74Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
75Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
76
77class QMetaContainerInterface
78{
79public:
80 enum Position : quint8 { AtBegin, AtEnd, Unspecified };
81 ushort revision = 0;
82 IteratorCapabilities iteratorCapabilities;
83
84 using SizeFn = qsizetype(*)(const void *);
85 SizeFn sizeFn;
86 using ClearFn = void(*)(void *);
87 ClearFn clearFn;
88
89 using CreateIteratorFn = void *(*)(void *, Position);
90 CreateIteratorFn createIteratorFn;
91 using DestroyIteratorFn = void(*)(const void *);
92 DestroyIteratorFn destroyIteratorFn;
93 using CompareIteratorFn = bool(*)(const void *, const void *);
94 CompareIteratorFn compareIteratorFn;
95 using CopyIteratorFn = void(*)(void *, const void *);
96 CopyIteratorFn copyIteratorFn;
97 using AdvanceIteratorFn = void(*)(void *, qsizetype);
98 AdvanceIteratorFn advanceIteratorFn;
99 using DiffIteratorFn = qsizetype(*)(const void *, const void *);
100 DiffIteratorFn diffIteratorFn;
101
102 using CreateConstIteratorFn = void *(*)(const void *, Position);
103 CreateConstIteratorFn createConstIteratorFn;
104 DestroyIteratorFn destroyConstIteratorFn;
105 CompareIteratorFn compareConstIteratorFn;
106 CopyIteratorFn copyConstIteratorFn;
107 AdvanceIteratorFn advanceConstIteratorFn;
108 DiffIteratorFn diffConstIteratorFn;
109
110 QMetaContainerInterface() = default;
111
112 template<typename MetaContainer>
113 constexpr QMetaContainerInterface(const MetaContainer &)
114 : iteratorCapabilities(MetaContainer::getIteratorCapabilities())
115 , sizeFn(MetaContainer::getSizeFn())
116 , clearFn(MetaContainer::getClearFn())
117 , createIteratorFn(MetaContainer::getCreateIteratorFn())
118 , destroyIteratorFn(MetaContainer::getDestroyIteratorFn())
119 , compareIteratorFn(MetaContainer::getCompareIteratorFn())
120 , copyIteratorFn(MetaContainer::getCopyIteratorFn())
121 , advanceIteratorFn(MetaContainer::getAdvanceIteratorFn())
122 , diffIteratorFn(MetaContainer::getDiffIteratorFn())
123 , createConstIteratorFn(MetaContainer::getCreateConstIteratorFn())
124 , destroyConstIteratorFn(MetaContainer::getDestroyConstIteratorFn())
125 , compareConstIteratorFn(MetaContainer::getCompareConstIteratorFn())
126 , copyConstIteratorFn(MetaContainer::getCopyConstIteratorFn())
127 , advanceConstIteratorFn(MetaContainer::getAdvanceConstIteratorFn())
128 , diffConstIteratorFn(MetaContainer::getDiffConstIteratorFn())
129 {}
130};
131
132class QMetaSequenceInterface : public QMetaContainerInterface
133{
134public:
135 const QtPrivate::QMetaTypeInterface *valueMetaType;
136 AddRemoveCapabilities addRemoveCapabilities;
137
138 using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
139 ValueAtIndexFn valueAtIndexFn;
140 using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
141 SetValueAtIndexFn setValueAtIndexFn;
142
143 using AddValueFn = void(*)(void *, const void *, Position);
144 AddValueFn addValueFn;
145 using RemoveValueFn = void(*)(void *, Position);
146 RemoveValueFn removeValueFn;
147
148 using ValueAtIteratorFn = void(*)(const void *, void *);
149 ValueAtIteratorFn valueAtIteratorFn;
150 using SetValueAtIteratorFn = void(*)(const void *, const void *);
151 SetValueAtIteratorFn setValueAtIteratorFn;
152 using InsertValueAtIteratorFn = void(*)(void *, const void *, const void *);
153 InsertValueAtIteratorFn insertValueAtIteratorFn;
154
155 ValueAtIteratorFn valueAtConstIteratorFn;
156
157 using EraseValueAtIteratorFn = void(*)(void *, const void *);
158 EraseValueAtIteratorFn eraseValueAtIteratorFn;
159
160 using EraseRangeAtIteratorFn = void(*)(void *, const void *, const void *);
161 EraseRangeAtIteratorFn eraseRangeAtIteratorFn;
162
163 QMetaSequenceInterface() = default;
164
165 template<typename MetaSequence>
166 constexpr QMetaSequenceInterface(const MetaSequence &m)
167 : QMetaContainerInterface(m)
168 , valueMetaType(MetaSequence::getValueMetaType())
169 , addRemoveCapabilities(MetaSequence::getAddRemoveCapabilities())
170 , valueAtIndexFn(MetaSequence::getValueAtIndexFn())
171 , setValueAtIndexFn(MetaSequence::getSetValueAtIndexFn())
172 , addValueFn(MetaSequence::getAddValueFn())
173 , removeValueFn(MetaSequence::getRemoveValueFn())
174 , valueAtIteratorFn(MetaSequence::getValueAtIteratorFn())
175 , setValueAtIteratorFn(MetaSequence::getSetValueAtIteratorFn())
176 , insertValueAtIteratorFn(MetaSequence::getInsertValueAtIteratorFn())
177 , valueAtConstIteratorFn(MetaSequence::getValueAtConstIteratorFn())
178 , eraseValueAtIteratorFn(MetaSequence::getEraseValueAtIteratorFn())
179 , eraseRangeAtIteratorFn(MetaSequence::getEraseRangeAtIteratorFn())
180 {}
181};
182
183class QMetaAssociationInterface : public QMetaContainerInterface
184{
185public:
186 const QtPrivate::QMetaTypeInterface *keyMetaType;
187 const QtPrivate::QMetaTypeInterface *mappedMetaType;
188
189 using InsertKeyFn = void(*)(void *, const void *);
190 InsertKeyFn insertKeyFn;
191 using RemoveKeyFn = void(*)(void *, const void *);
192 RemoveKeyFn removeKeyFn;
193 using ContainsKeyFn = bool(*)(const void *, const void *);
194 ContainsKeyFn containsKeyFn;
195
196 using MappedAtKeyFn = void(*)(const void *, const void *, void *);
197 MappedAtKeyFn mappedAtKeyFn;
198 using SetMappedAtKeyFn = void(*)(void *, const void *, const void *);
199 SetMappedAtKeyFn setMappedAtKeyFn;
200
201 using CreateIteratorAtKeyFn = void *(*)(void *, const void *);
202 CreateIteratorAtKeyFn createIteratorAtKeyFn;
203 using CreateConstIteratorAtKeyFn = void *(*)(const void *, const void *);
204 CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn;
205
206 using KeyAtIteratorFn = void(*)(const void *, void *);
207 KeyAtIteratorFn keyAtIteratorFn;
208 KeyAtIteratorFn keyAtConstIteratorFn;
209
210 using MappedAtIteratorFn = void(*)(const void *, void *);
211 MappedAtIteratorFn mappedAtIteratorFn;
212 MappedAtIteratorFn mappedAtConstIteratorFn;
213
214 using SetMappedAtIteratorFn = void(*)(const void *, const void *);
215 SetMappedAtIteratorFn setMappedAtIteratorFn;
216
217 using EraseKeyAtIteratorFn = void(*)(void *, const void *);
218 EraseKeyAtIteratorFn eraseKeyAtIteratorFn;
219
220 QMetaAssociationInterface() = default;
221
222 template<typename MetaAssociation>
223 constexpr QMetaAssociationInterface(const MetaAssociation &m)
224 : QMetaContainerInterface(m)
225 , keyMetaType(MetaAssociation::getKeyMetaType())
226 , mappedMetaType(MetaAssociation::getMappedMetaType())
227 , insertKeyFn(MetaAssociation::getInsertKeyFn())
228 , removeKeyFn(MetaAssociation::getRemoveKeyFn())
229 , containsKeyFn(MetaAssociation::getContainsKeyFn())
230 , mappedAtKeyFn(MetaAssociation::getMappedAtKeyFn())
231 , setMappedAtKeyFn(MetaAssociation::getSetMappedAtKeyFn())
232 , createIteratorAtKeyFn(MetaAssociation::createIteratorAtKeyFn())
233 , createConstIteratorAtKeyFn(MetaAssociation::createConstIteratorAtKeyFn())
234 , keyAtIteratorFn(MetaAssociation::getKeyAtIteratorFn())
235 , keyAtConstIteratorFn(MetaAssociation::getKeyAtConstIteratorFn())
236 , mappedAtIteratorFn(MetaAssociation::getMappedAtIteratorFn())
237 , mappedAtConstIteratorFn(MetaAssociation::getMappedAtConstIteratorFn())
238 , setMappedAtIteratorFn(MetaAssociation::getSetMappedAtIteratorFn())
239 , eraseKeyAtIteratorFn(MetaAssociation::getEraseKeyAtIteratorFn())
240 {}
241};
242
243template<typename C>
244class QMetaContainerForContainer
245{
246 friend QMetaContainerInterface;
247
248 template <typename Iterator>
249 static constexpr IteratorCapabilities capabilitiesForIterator()
250 {
251 using Tag = typename std::iterator_traits<Iterator>::iterator_category;
252 IteratorCapabilities caps {};
253 if constexpr (std::is_base_of_v<std::input_iterator_tag, Tag>)
254 caps |= InputCapability;
255 if constexpr (std::is_base_of_v<std::forward_iterator_tag, Tag>)
256 caps |= ForwardCapability;
257 if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, Tag>)
258 caps |= BiDirectionalCapability;
259 if constexpr (std::is_base_of_v<std::random_access_iterator_tag, Tag>)
260 caps |= RandomAccessCapability;
261 return caps;
262 }
263
264 static constexpr IteratorCapabilities getIteratorCapabilities()
265 {
266 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>)
267 return capabilitiesForIterator<QContainerTraits::iterator<C>>();
268 else if constexpr (QContainerTraits::has_const_iterator_v<C>)
269 return capabilitiesForIterator<QContainerTraits::const_iterator<C>>();
270 else
271 return {};
272 }
273
274 static constexpr QMetaContainerInterface::SizeFn getSizeFn()
275 {
276 if constexpr (QContainerTraits::has_size_v<C>) {
277 return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
278 } else {
279 return nullptr;
280 }
281 }
282
283 static constexpr QMetaContainerInterface::ClearFn getClearFn()
284 {
285 if constexpr (QContainerTraits::has_clear_v<C>) {
286 return [](void *c) { return static_cast<C *>(c)->clear(); };
287 } else {
288 return nullptr;
289 }
290 }
291
292 static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn()
293 {
294 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
295 return [](void *c, QMetaContainerInterface::Position p) -> void* {
296 using Iterator = QContainerTraits::iterator<C>;
297 switch (p) {
298 case QMetaContainerInterface::Unspecified:
299 return new Iterator;
300 case QMetaContainerInterface::AtBegin:
301 return new Iterator(static_cast<C *>(c)->begin());
302 break;
303 case QMetaContainerInterface::AtEnd:
304 return new Iterator(static_cast<C *>(c)->end());
305 break;
306 }
307 return nullptr;
308 };
309 } else {
310 return nullptr;
311 }
312 }
313
314 static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn()
315 {
316 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
317 return [](const void *i) {
318 using Iterator = QContainerTraits::iterator<C>;
319 delete static_cast<const Iterator *>(i);
320 };
321 } else {
322 return nullptr;
323 }
324 }
325
326 static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn()
327 {
328 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
329 return [](const void *i, const void *j) {
330 using Iterator = QContainerTraits::iterator<C>;
331 return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
332 };
333 } else {
334 return nullptr;
335 }
336 }
337
338 static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn()
339 {
340 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
341 return [](void *i, const void *j) {
342 using Iterator = QContainerTraits::iterator<C>;
343 *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
344 };
345 } else {
346 return nullptr;
347 }
348 }
349
350 static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn()
351 {
352 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
353 return [](void *i, qsizetype step) {
354 std::advance(*static_cast<QContainerTraits::iterator<C> *>(i), step);
355 };
356 } else {
357 return nullptr;
358 }
359 }
360
361 static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn()
362 {
363 if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
364 return [](const void *i, const void *j) -> qsizetype {
365 return std::distance(*static_cast<const QContainerTraits::iterator<C> *>(j),
366 *static_cast<const QContainerTraits::iterator<C> *>(i));
367 };
368 } else {
369 return nullptr;
370 }
371 }
372
373 static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn()
374 {
375 if constexpr (QContainerTraits::has_const_iterator_v<C>) {
376 return [](const void *c, QMetaContainerInterface::Position p) -> void* {
377 using Iterator = QContainerTraits::const_iterator<C>;
378 switch (p) {
379 case QMetaContainerInterface::Unspecified:
380 return new Iterator;
381 case QMetaContainerInterface::AtBegin:
382 return new Iterator(static_cast<const C *>(c)->begin());
383 case QMetaContainerInterface::AtEnd:
384 return new Iterator(static_cast<const C *>(c)->end());
385 }
386 return nullptr;
387 };
388 } else {
389 return nullptr;
390 }
391 }
392
393 static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn()
394 {
395 if constexpr (QContainerTraits::has_const_iterator_v<C>) {
396 return [](const void *i) {
397 using Iterator = QContainerTraits::const_iterator<C>;
398 delete static_cast<const Iterator *>(i);
399 };
400 } else {
401 return nullptr;
402 }
403 }
404
405 static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn()
406 {
407 if constexpr (QContainerTraits::has_const_iterator_v<C>) {
408 return [](const void *i, const void *j) {
409 using Iterator = QContainerTraits::const_iterator<C>;
410 return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
411 };
412 } else {
413 return nullptr;
414 }
415 }
416
417 static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn()
418 {
419 if constexpr (QContainerTraits::has_const_iterator_v<C>) {
420 return [](void *i, const void *j) {
421 using Iterator = QContainerTraits::const_iterator<C>;
422 *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
423 };
424 } else {
425 return nullptr;
426 }
427 }
428
429 static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
430 {
431 if constexpr (QContainerTraits::has_const_iterator_v<C>) {
432 return [](void *i, qsizetype step) {
433 std::advance(*static_cast<QContainerTraits::const_iterator<C> *>(i), step);
434 };
435 } else {
436 return nullptr;
437 }
438 }
439
440 static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn()
441 {
442 if constexpr (QContainerTraits::has_const_iterator_v<C>) {
443 return [](const void *i, const void *j) -> qsizetype {
444 return std::distance(*static_cast<const QContainerTraits::const_iterator<C> *>(j),
445 *static_cast<const QContainerTraits::const_iterator<C> *>(i));
446 };
447 } else {
448 return nullptr;
449 }
450 }
451
452protected:
453
454 template<typename EraseFn>
455 static constexpr EraseFn getEraseAtIteratorFn()
456 {
457 if constexpr (QContainerTraits::has_iterator_v<C>
458 && QContainerTraits::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
459 return [](void *c, const void *i) {
460 static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i));
461 };
462 } else {
463 return nullptr;
464 }
465 }
466};
467
468template<typename C>
469class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
470{
471 friend QMetaSequenceInterface;
472
473 static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType()
474 {
475 if constexpr (QContainerTraits::has_value_type_v<C>)
476 return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
477 else
478 return nullptr;
479 }
480
481 static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
482 {
483 AddRemoveCapabilities caps;
484 if constexpr (QContainerTraits::has_push_back_v<C>)
485 caps |= CanAddAtEnd;
486 if constexpr (QContainerTraits::has_pop_back_v<C>)
487 caps |= CanRemoveAtEnd;
488 if constexpr (QContainerTraits::has_push_front_v<C>)
489 caps |= CanAddAtBegin;
490 if constexpr (QContainerTraits::has_pop_front_v<C>)
491 caps |= CanRemoveAtBegin;
492 return caps;
493 }
494
495 static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn()
496 {
497 if constexpr (QContainerTraits::has_at_index_v<C>) {
498 return [](const void *c, qsizetype i, void *r) {
499 *static_cast<QContainerTraits::value_type<C> *>(r)
500 = static_cast<const C *>(c)->at(i);
501 };
502 } else if constexpr (QContainerTraits::can_get_at_index_v<C>) {
503 return [](const void *c, qsizetype i, void *r) {
504 *static_cast<QContainerTraits::value_type<C> *>(r)
505 = (*static_cast<const C *>(c))[i];
506 };
507 } else {
508 return nullptr;
509 }
510 }
511
512 static constexpr QMetaSequenceInterface::SetValueAtIndexFn getSetValueAtIndexFn()
513 {
514 if constexpr (QContainerTraits::can_set_at_index_v<C>) {
515 return [](void *c, qsizetype i, const void *e) {
516 (*static_cast<C *>(c))[i]
517 = *static_cast<const QContainerTraits::value_type<C> *>(e);
518 };
519 } else {
520 return nullptr;
521 }
522 }
523
524 static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
525 {
526 if constexpr (QContainerTraits::has_push_back_v<C>) {
527 if constexpr (QContainerTraits::has_push_front_v<C>) {
528 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
529 const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
530 switch (position) {
531 case QMetaSequenceInterface::AtBegin:
532 static_cast<C *>(c)->push_front(value);
533 break;
534 case QMetaSequenceInterface::AtEnd:
535 case QMetaSequenceInterface::Unspecified:
536 static_cast<C *>(c)->push_back(value);
537 break;
538 }
539 };
540 } else {
541 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
542 const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
543 switch (position) {
544 case QMetaSequenceInterface::AtBegin:
545 break;
546 case QMetaSequenceInterface::AtEnd:
547 case QMetaSequenceInterface::Unspecified:
548 static_cast<C *>(c)->push_back(value);
549 break;
550 }
551 };
552 }
553 } else if constexpr (QContainerTraits::has_push_front_v<C>) {
554 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
555 const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
556 switch (position) {
557 case QMetaSequenceInterface::Unspecified:
558 case QMetaSequenceInterface::AtBegin:
559 static_cast<C *>(c)->push_front(value);
560 case QMetaSequenceInterface::AtEnd:
561 break;
562 }
563 };
564 } else if constexpr (QContainerTraits::has_insert_v<C>) {
565 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
566 if (position == QMetaSequenceInterface::Unspecified) {
567 static_cast<C *>(c)->insert(
568 *static_cast<const QContainerTraits::value_type<C> *>(v));
569 }
570 };
571 } else {
572 return nullptr;
573 }
574 }
575
576 static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
577 {
578 if constexpr (QContainerTraits::has_pop_back_v<C>) {
579 if constexpr (QContainerTraits::has_pop_front_v<C>) {
580 return [](void *c, QMetaSequenceInterface::Position position) {
581 switch (position) {
582 case QMetaSequenceInterface::AtBegin:
583 static_cast<C *>(c)->pop_front();
584 break;
585 case QMetaSequenceInterface::AtEnd:
586 case QMetaSequenceInterface::Unspecified:
587 static_cast<C *>(c)->pop_back();
588 break;
589 }
590 };
591 } else {
592 return [](void *c, QMetaSequenceInterface::Position position) {
593 switch (position) {
594 case QMetaSequenceInterface::AtBegin:
595 break;
596 case QMetaSequenceInterface::Unspecified:
597 case QMetaSequenceInterface::AtEnd:
598 static_cast<C *>(c)->pop_back();
599 break;
600 }
601 };
602 }
603 } else if constexpr (QContainerTraits::has_pop_front_v<C>) {
604 return [](void *c, QMetaSequenceInterface::Position position) {
605 switch (position) {
606 case QMetaSequenceInterface::Unspecified:
607 case QMetaSequenceInterface::AtBegin:
608 static_cast<C *>(c)->pop_front();
609 break;
610 case QMetaSequenceInterface::AtEnd:
611 break;
612 }
613 };
614 } else {
615 return nullptr;
616 }
617 }
618
619 static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
620 {
621 if constexpr (QContainerTraits::has_iterator_v<C>
622 && QContainerTraits::iterator_dereferences_to_value_v<C> && !std::is_const_v<C>) {
623 return [](const void *i, void *r) {
624 *static_cast<QContainerTraits::value_type<C> *>(r) =
625 *(*static_cast<const QContainerTraits::iterator<C> *>(i));
626 };
627 } else {
628 return nullptr;
629 }
630 }
631
632 static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
633 {
634 if constexpr (QContainerTraits::has_iterator_v<C>
635 && QContainerTraits::can_set_value_at_iterator_v<C> && !std::is_const_v<C>) {
636 return [](const void *i, const void *e) {
637 *(*static_cast<const QContainerTraits::iterator<C> *>(i))
638 = *static_cast<const QContainerTraits::value_type<C> *>(e);
639 };
640 } else {
641 return nullptr;
642 }
643 }
644
645 static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
646 {
647 if constexpr (QContainerTraits::has_iterator_v<C>
648 && QContainerTraits::can_insert_value_at_iterator_v<C> && !std::is_const_v<C>) {
649 return [](void *c, const void *i, const void *e) {
650 static_cast<C *>(c)->insert(
651 *static_cast<const QContainerTraits::iterator<C> *>(i),
652 *static_cast<const QContainerTraits::value_type<C> *>(e));
653 };
654 } else {
655 return nullptr;
656 }
657 }
658
659 static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
660 {
661 if constexpr (QContainerTraits::has_const_iterator_v<C>
662 && QContainerTraits::iterator_dereferences_to_value_v<C>) {
663 return [](const void *i, void *r) {
664 *static_cast<QContainerTraits::value_type<C> *>(r) =
665 *(*static_cast<const QContainerTraits::const_iterator<C> *>(i));
666 };
667 } else {
668 return nullptr;
669 }
670 }
671
672 static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
673 {
674 return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
675 QMetaSequenceInterface::EraseValueAtIteratorFn>();
676 }
677
678 static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
679 {
680 if constexpr (QContainerTraits::has_iterator_v<C>
681 && QContainerTraits::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
682 return [](void *c, const void *i, const void *j) {
683 static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i),
684 *static_cast<const QContainerTraits::iterator<C> *>(j));
685 };
686 } else {
687 return nullptr;
688 }
689 }
690};
691
692template<typename C>
693class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
694{
695 friend QMetaAssociationInterface;
696
697 static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType()
698 {
699 if constexpr (QContainerTraits::has_key_type_v<C>)
700 return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
701 else
702 return nullptr;
703 }
704
705 static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType()
706 {
707 if constexpr (QContainerTraits::has_mapped_type_v<C>)
708 return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
709 else
710 return nullptr;
711 }
712
713 static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn()
714 {
715 if constexpr (QContainerTraits::can_insert_key_v<C>) {
716 return [](void *c, const void *k) {
717 static_cast<C *>(c)->insert(
718 *static_cast<const QContainerTraits::key_type<C> *>(k));
719 };
720 } else if constexpr (QContainerTraits::can_insert_pair_v<C>) {
721 return [](void *c, const void *k) {
722 static_cast<C *>(c)->insert(
723 {*static_cast<const QContainerTraits::key_type<C> *>(k), {}});
724 };
725 } else if constexpr (QContainerTraits::can_insert_key_mapped_v<C>) {
726 return [](void *c, const void *k) {
727 static_cast<C *>(c)->insert(
728 *static_cast<const QContainerTraits::key_type<C> *>(k), {});
729 };
730 } else {
731 return nullptr;
732 }
733 }
734
735 static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn()
736 {
737 if constexpr (QContainerTraits::can_erase_at_key_v<C>) {
738 return [](void *c, const void *k) {
739 static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::key_type<C> *>(k));
740 };
741 } else if constexpr (QContainerTraits::can_remove_at_key_v<C>) {
742 return [](void *c, const void *k) {
743 static_cast<C *>(c)->remove(*static_cast<const QContainerTraits::key_type<C> *>(k));
744 };
745 } else {
746 return nullptr;
747 }
748 }
749
750 static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn()
751 {
752 if constexpr (QContainerTraits::has_contains_v<C>) {
753 return [](const void *c, const void *k) {
754 return static_cast<const C *>(c)->contains(
755 *static_cast<const QContainerTraits::key_type<C> *>(k));
756 };
757 } else if (QContainerTraits::has_find_v<C>) {
758 return [](const void *c, const void *k) {
759 const C *container = static_cast<const C *>(c);
760 return container->find(
761 *static_cast<const QContainerTraits::key_type<C> *>(k))
762 != container->end();
763 };
764 } else {
765 return nullptr;
766 }
767 }
768
769 static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn()
770 {
771 if constexpr (QContainerTraits::has_at_key_v<C>) {
772 return [](const void *c, const void *k, void *r) {
773 *static_cast<QContainerTraits::mapped_type<C> *>(r)
774 = static_cast<const C *>(c)->at(
775 *static_cast<const QContainerTraits::key_type<C> *>(k));
776 };
777 } else if constexpr (QContainerTraits::can_get_at_key_v<C>) {
778 return [](const void *c, const void *k, void *r) {
779 *static_cast<QContainerTraits::mapped_type<C> *>(r)
780 = (*static_cast<const C *>(c))[
781 *static_cast<const QContainerTraits::key_type<C> *>(k)];
782 };
783 } else {
784 return nullptr;
785 }
786 }
787
788 static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn()
789 {
790 if constexpr (QContainerTraits::can_set_at_key_v<C>) {
791 return [](void *c, const void *k, const void *m) {
792 (*static_cast<C *>(c))[*static_cast<const QContainerTraits::key_type<C> *>(k)] =
793 *static_cast<const QContainerTraits::mapped_type<C> *>(m);
794 };
795 } else {
796 return nullptr;
797 }
798 }
799
800 static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn()
801 {
802 if constexpr (QContainerTraits::has_find_v<C>) {
803 return [](void *c, const void *k) -> void* {
804 using Iterator = QContainerTraits::iterator<C>;
805 return new Iterator(static_cast<C *>(c)->find(
806 *static_cast<const QContainerTraits::key_type<C> *>(k)));
807 };
808 } else {
809 return nullptr;
810 }
811 }
812
813 static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn()
814 {
815 if constexpr (QContainerTraits::has_find_v<C>) {
816 return [](const void *c, const void *k) -> void* {
817 using Iterator = QContainerTraits::const_iterator<C>;
818 return new Iterator(static_cast<const C *>(c)->find(
819 *static_cast<const QContainerTraits::key_type<C> *>(k)));
820 };
821 } else {
822 return nullptr;
823 }
824 }
825
826 template<typename Iterator>
827 static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn()
828 {
829 if constexpr (QContainerTraits::iterator_has_key_v<C>) {
830 return [](const void *i, void *k) {
831 *static_cast<QContainerTraits::key_type<C> *>(k)
832 = static_cast<const Iterator *>(i)->key();
833 };
834 } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v<C>
835 && QContainerTraits::value_type_has_first_v<C>) {
836 return [](const void *i, void *k) {
837 *static_cast<QContainerTraits::key_type<C> *>(k)
838 = (*static_cast<const Iterator *>(i))->first;
839 };
840 } else if constexpr (QContainerTraits::iterator_dereferences_to_key_v<C>) {
841 return [](const void *i, void *k) {
842 *static_cast<QContainerTraits::key_type<C> *>(k)
843 = *(*static_cast<const Iterator *>(i));
844 };
845 } else {
846 return nullptr;
847 }
848 }
849
850 static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn()
851 {
852 return keyAtIteratorFn<QContainerTraits::iterator<C>>();
853 }
854
855 static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn()
856 {
857 return keyAtIteratorFn<QContainerTraits::const_iterator<C>>();
858 }
859
860 template<typename Iterator>
861 static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn()
862 {
863 if constexpr (QContainerTraits::iterator_has_value_v<C>) {
864 return [](const void *i, void *k) {
865 *static_cast<QContainerTraits::mapped_type<C> *>(k)
866 = static_cast<const Iterator *>(i)->value();
867 };
868 } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v<C>
869 && QContainerTraits::value_type_has_second_v<C>) {
870 return [](const void *i, void *k) {
871 *static_cast<QContainerTraits::mapped_type<C> *>(k)
872 = (*static_cast<const Iterator *>(i))->second;
873 };
874 } else if constexpr (QContainerTraits::iterator_dereferences_to_mapped_v<C>) {
875 return [](const void *i, void *k) {
876 *static_cast<QContainerTraits::mapped_type<C> *>(k)
877 = *static_cast<const Iterator *>(i);
878 };
879 } else {
880 return nullptr;
881 }
882 }
883
884 static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn()
885 {
886 return mappedAtIteratorFn<QContainerTraits::iterator<C>>();
887 }
888
889 static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn()
890 {
891 return mappedAtIteratorFn<QContainerTraits::const_iterator<C>>();
892 }
893
894 static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn()
895 {
896 if constexpr (QContainerTraits::can_set_mapped_at_iterator_v<C> && !std::is_const_v<C>) {
897 return [](const void *i, const void *m) {
898 *(*static_cast<const QContainerTraits::iterator<C> *>(i))
899 = *static_cast<const QContainerTraits::mapped_type<C> *>(m);
900 };
901 } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v<C>
902 && QContainerTraits::value_type_has_second_v<C>) {
903 return [](const void *i, const void *m) {
904 (*static_cast<const QContainerTraits::iterator<C> *>(i))->second
905 = *static_cast<const QContainerTraits::mapped_type<C> *>(m);
906 };
907 } else {
908 return nullptr;
909 }
910 }
911
912 static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn()
913 {
914 return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
915 QMetaAssociationInterface::EraseKeyAtIteratorFn>();
916 }
917};
918
919} // namespace QtMetaContainerPrivate
920
921class Q_CORE_EXPORT QMetaContainer
922{
923public:
924 QMetaContainer() = default;
925 explicit QMetaContainer(const QtMetaContainerPrivate::QMetaContainerInterface *d) : d_ptr(d) {}
926
927 bool hasInputIterator() const;
928 bool hasForwardIterator() const;
929 bool hasBidirectionalIterator() const;
930 bool hasRandomAccessIterator() const;
931
932 bool hasSize() const;
933 qsizetype size(const void *container) const;
934
935 bool canClear() const;
936 void clear(void *container) const;
937
938 bool hasIterator() const;
939 void *begin(void *container) const;
940 void *end(void *container) const;
941 void destroyIterator(const void *iterator) const;
942 bool compareIterator(const void *i, const void *j) const;
943 void copyIterator(void *target, const void *source) const;
944 void advanceIterator(void *iterator, qsizetype step) const;
945 qsizetype diffIterator(const void *i, const void *j) const;
946
947 bool hasConstIterator() const;
948 void *constBegin(const void *container) const;
949 void *constEnd(const void *container) const;
950 void destroyConstIterator(const void *iterator) const;
951 bool compareConstIterator(const void *i, const void *j) const;
952 void copyConstIterator(void *target, const void *source) const;
953 void advanceConstIterator(void *iterator, qsizetype step) const;
954 qsizetype diffConstIterator(const void *i, const void *j) const;
955
956protected:
957 const QtMetaContainerPrivate::QMetaContainerInterface *d_ptr = nullptr;
958};
959
960class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
961{
962public:
963 QMetaSequence() = default;
964 explicit QMetaSequence(const QtMetaContainerPrivate::QMetaSequenceInterface *d) : QMetaContainer(d) {}
965
966 template<typename T>
967 static constexpr QMetaSequence fromContainer()
968 {
969 return QMetaSequence(&MetaSequence<T>::value);
970 }
971
972 QMetaType valueMetaType() const;
973
974 bool isSortable() const;
975 bool canAddValueAtBegin() const;
976 void addValueAtBegin(void *container, const void *value) const;
977 bool canAddValueAtEnd() const;
978 void addValueAtEnd(void *container, const void *value) const;
979 bool canRemoveValueAtBegin() const;
980 void removeValueAtBegin(void *container) const;
981 bool canRemoveValueAtEnd() const;
982 void removeValueAtEnd(void *container) const;
983
984 bool canGetValueAtIndex() const;
985 void valueAtIndex(const void *container, qsizetype index, void *result) const;
986
987 bool canSetValueAtIndex() const;
988 void setValueAtIndex(void *container, qsizetype index, const void *value) const;
989
990 bool canAddValue() const;
991 void addValue(void *container, const void *value) const;
992
993 bool canRemoveValue() const;
994 void removeValue(void *container) const;
995
996 bool canGetValueAtIterator() const;
997 void valueAtIterator(const void *iterator, void *result) const;
998
999 bool canSetValueAtIterator() const;
1000 void setValueAtIterator(const void *iterator, const void *value) const;
1001
1002 bool canInsertValueAtIterator() const;
1003 void insertValueAtIterator(void *container, const void *iterator, const void *value) const;
1004
1005 bool canEraseValueAtIterator() const;
1006 void eraseValueAtIterator(void *container, const void *iterator) const;
1007
1008 bool canEraseRangeAtIterator() const;
1009 void eraseRangeAtIterator(void *container, const void *iterator1, const void *iterator2) const;
1010
1011 bool canGetValueAtConstIterator() const;
1012 void valueAtConstIterator(const void *iterator, void *result) const;
1013
1014 friend bool operator==(const QMetaSequence &a, const QMetaSequence &b)
1015 {
1016 return a.d() == b.d();
1017 }
1018 friend bool operator!=(const QMetaSequence &a, const QMetaSequence &b)
1019 {
1020 return a.d() != b.d();
1021 }
1022
1023private:
1024 template<typename T>
1025 struct MetaSequence
1026 {
1027 static constexpr const QtMetaContainerPrivate::QMetaSequenceInterface value
1028 = QtMetaContainerPrivate::QMetaSequenceInterface(
1029 QtMetaContainerPrivate::QMetaSequenceForContainer<T>());
1030 };
1031
1032 const QtMetaContainerPrivate::QMetaSequenceInterface *d() const
1033 {
1034 return static_cast<const QtMetaContainerPrivate::QMetaSequenceInterface *>(d_ptr);
1035 }
1036};
1037
1038class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
1039{
1040public:
1041 QMetaAssociation() = default;
1042 explicit QMetaAssociation(const QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {}
1043
1044 template<typename T>
1045 static constexpr QMetaAssociation fromContainer()
1046 {
1047 return QMetaAssociation(&MetaAssociation<T>::value);
1048 }
1049
1050 QMetaType keyMetaType() const;
1051 QMetaType mappedMetaType() const;
1052
1053 bool canInsertKey() const
1054 {
1055 if (auto iface = d())
1056 return iface->insertKeyFn;
1057 return false;
1058 }
1059 void insertKey(void *container, const void *key) const
1060 {
1061 if (canInsertKey())
1062 d()->insertKeyFn(container, key);
1063 }
1064
1065 bool canRemoveKey() const
1066 {
1067 if (auto iface = d())
1068 return iface->removeKeyFn;
1069 return false;
1070 }
1071 void removeKey(void *container, const void *key) const
1072 {
1073 if (canRemoveKey())
1074 d()->removeKeyFn(container, key);
1075 }
1076
1077 bool canContainsKey() const
1078 {
1079 if (auto iface = d())
1080 return iface->containsKeyFn;
1081 return false;
1082 }
1083 bool containsKey(const void *container, const void *key) const
1084 {
1085 if (canContainsKey())
1086 return d()->containsKeyFn(container, key);
1087 return false;
1088 }
1089
1090
1091 bool canGetMappedAtKey() const
1092 {
1093 if (auto iface = d())
1094 return iface->mappedAtKeyFn;
1095 return false;
1096 }
1097 void mappedAtKey(const void *container, const void *key, void *mapped) const
1098 {
1099 if (canGetMappedAtKey())
1100 d()->mappedAtKeyFn(container, key, mapped);
1101 }
1102
1103 bool canSetMappedAtKey() const
1104 {
1105 if (auto iface = d())
1106 return iface->setMappedAtKeyFn;
1107 return false;
1108 }
1109 void setMappedAtKey(void *container, const void *key, const void *mapped) const
1110 {
1111 if (canSetMappedAtKey())
1112 d()->setMappedAtKeyFn(container, key, mapped);
1113 }
1114
1115 bool canGetKeyAtIterator() const
1116 {
1117 if (auto iface = d())
1118 return iface->keyAtIteratorFn;
1119 return false;
1120 }
1121
1122 void keyAtIterator(const void *iterator, void *key) const
1123 {
1124 if (canGetKeyAtIterator())
1125 d()->keyAtIteratorFn(iterator, key);
1126 }
1127
1128 bool canGetKeyAtConstIterator() const
1129 {
1130 if (auto iface = d())
1131 return iface->keyAtConstIteratorFn;
1132 return false;
1133 }
1134
1135 void keyAtConstIterator(const void *iterator, void *key) const
1136 {
1137 if (canGetKeyAtConstIterator())
1138 d()->keyAtConstIteratorFn(iterator, key);
1139 }
1140
1141 bool canGetMappedAtIterator() const
1142 {
1143 if (auto iface = d())
1144 return iface->mappedAtIteratorFn;
1145 return false;
1146 }
1147
1148 void mappedAtIterator(const void *iterator, void *mapped) const
1149 {
1150 if (canGetMappedAtIterator())
1151 d()->mappedAtIteratorFn(iterator, mapped);
1152 }
1153
1154 bool canGetMappedAtConstIterator() const
1155 {
1156 if (auto iface = d())
1157 return iface->mappedAtConstIteratorFn;
1158 return false;
1159 }
1160
1161 void mappedAtConstIterator(const void *iterator, void *mapped) const
1162 {
1163 if (canGetMappedAtConstIterator())
1164 d()->mappedAtConstIteratorFn(iterator, mapped);
1165 }
1166
1167 bool canSetMappedAtIterator() const
1168 {
1169 if (auto iface = d())
1170 return iface->setMappedAtIteratorFn;
1171 return false;
1172 }
1173
1174 void setMappedAtIterator(const void *iterator, const void *mapped) const
1175 {
1176 if (canSetMappedAtIterator())
1177 d()->setMappedAtIteratorFn(iterator, mapped);
1178 }
1179
1180 bool canCreateIteratorAtKey() const
1181 {
1182 if (auto iface = d())
1183 return iface->createIteratorAtKeyFn;
1184 return false;
1185 }
1186
1187 void *createIteratorAtKey(void *container, const void *key) const
1188 {
1189 if (canCreateIteratorAtKey())
1190 return d()->createIteratorAtKeyFn(container, key);
1191 return nullptr;
1192 }
1193
1194 bool canCreateConstIteratorAtKey() const
1195 {
1196 if (auto iface = d())
1197 return iface->createConstIteratorAtKeyFn;
1198 return false;
1199 }
1200
1201 void *createConstIteratorAtKey(const void *container, const void *key) const
1202 {
1203 if (canCreateConstIteratorAtKey())
1204 return d()->createConstIteratorAtKeyFn(container, key);
1205 return nullptr;
1206 }
1207
1208 friend bool operator==(const QMetaAssociation &a, const QMetaAssociation &b)
1209 {
1210 return a.d() == b.d();
1211 }
1212 friend bool operator!=(const QMetaAssociation &a, const QMetaAssociation &b)
1213 {
1214 return a.d() != b.d();
1215 }
1216
1217private:
1218 template<typename T>
1219 struct MetaAssociation
1220 {
1221 static constexpr const QtMetaContainerPrivate::QMetaAssociationInterface value
1222 = QtMetaContainerPrivate::QMetaAssociationInterface(
1223 QtMetaContainerPrivate::QMetaAssociationForContainer<T>());
1224 };
1225
1226 const QtMetaContainerPrivate::QMetaAssociationInterface *d() const
1227 {
1228 return static_cast<const QtMetaContainerPrivate::QMetaAssociationInterface *>(d_ptr);
1229 }
1230};
1231
1232QT_END_NAMESPACE
1233
1234#endif // QMETACONTAINER_H
1235