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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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