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 "qmetacontainer.h"
41#include "qmetatype.h"
42
43QT_BEGIN_NAMESPACE
44
45/*!
46 \class QMetaSequence
47 \inmodule QtCore
48 \since 6.0
49 \brief The QMetaSequence class allows type erased access to sequential containers.
50
51 \ingroup objectmodel
52
53 The class provides a number of primitive container operations, using void*
54 as operands. This way, you can manipulate a generic container retrieved from
55 a Variant without knowing its type.
56
57 The void* arguments to the various methods are typically created by using
58 a \l QVariant of the respective container or value type, and calling
59 its \l QVariant::data() or \l QVariant::constData() methods. However, you
60 can also pass plain pointers to objects of the container or value type.
61
62 Iterator invalidation follows the rules given by the underlying containers
63 and is not expressed in the API. Therefore, for a truly generic container,
64 any iterators should be considered invalid after any write operation.
65*/
66
67/*!
68 \fn template<typename C> QMetaSequence QMetaSequence::fromContainer()
69 \since 6.0
70
71 Returns the QMetaSequence corresponding to the type given as template parameter.
72*/
73
74/*!
75 Returns \c true if the underlying container provides at least an input
76 iterator as defined by std::input_iterator_tag, otherwise returns
77 \c false. Forward, Bi-directional, and random access iterators are
78 specializations of input iterators. This method will also return
79 \c true if the container provides one of those.
80
81 QMetaSequence assumes that const and non-const iterators for the same
82 container have the same iterator traits.
83 */
84bool QMetaContainer::hasInputIterator() const
85{
86 if (!d_ptr)
87 return false;
88 return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::InputCapability;
89}
90
91/*!
92 Returns \c true if the underlying container provides at least a forward
93 iterator as defined by std::forward_iterator_tag, otherwise returns
94 \c false. Bi-directional iterators and random access iterators are
95 specializations of forward iterators. This method will also return
96 \c true if the container provides one of those.
97
98 QMetaSequence assumes that const and non-const iterators for the same
99 container have the same iterator traits.
100 */
101bool QMetaContainer::hasForwardIterator() const
102{
103 if (!d_ptr)
104 return false;
105 return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::ForwardCapability;
106}
107
108/*!
109 Returns \c true if the underlying container provides a bi-directional
110 iterator or a random access iterator as defined by
111 std::bidirectional_iterator_tag and std::random_access_iterator_tag,
112 respectively. Otherwise returns \c false.
113
114 QMetaSequence assumes that const and non-const iterators for the same
115 container have the same iterator traits.
116 */
117bool QMetaContainer::hasBidirectionalIterator() const
118{
119 if (!d_ptr)
120 return false;
121 return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::BiDirectionalCapability;
122}
123
124/*!
125 Returns \c true if the underlying container provides a random access
126 iterator as defined by std::random_access_iterator_tag, otherwise returns
127 \c false.
128
129 QMetaSequence assumes that const and non-const iterators for the same
130 container have the same iterator traits.
131 */
132bool QMetaContainer::hasRandomAccessIterator() const
133{
134 if (!d_ptr)
135 return false;
136 return d_ptr->iteratorCapabilities & QtMetaContainerPrivate::RandomAccessCapability;
137}
138
139/*!
140 Returns the meta type for values stored in the container.
141 */
142QMetaType QMetaSequence::valueMetaType() const
143{
144 if (auto iface = d())
145 return QMetaType(iface->valueMetaType);
146 return QMetaType();
147}
148
149/*!
150 Returns \c true if the underlying container is sortable, otherwise returns
151 \c false. A container is considered sortable if values added to it are
152 placed in a defined location. Inserting into or adding to a sortable
153 container will always succeed. Inserting into or adding to an unsortable
154 container may not succeed, for example if the container is a QSet that
155 already contains the value being inserted.
156
157 \sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
158 canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
159 */
160bool QMetaSequence::isSortable() const
161{
162 if (auto iface = d()) {
163 return (iface->addRemoveCapabilities
164 & (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
165 && (iface->addRemoveCapabilities
166 & (QtMetaContainerPrivate::CanRemoveAtBegin
167 | QtMetaContainerPrivate::CanRemoveAtEnd));
168 }
169 return false;
170}
171
172/*!
173 Returns \c true if values added using \l addValue() can be placed at the
174 beginning of the container, otherwise returns \c false.
175
176 \sa addValueAtBegin(), canAddValueAtEnd()
177 */
178bool QMetaSequence::canAddValueAtBegin() const
179{
180 if (auto iface = d()) {
181 return iface->addValueFn
182 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
183 }
184 return false;
185}
186
187/*!
188 Adds \a value to the beginning of \a container if possible. If
189 \l canAddValueAtBegin() returns \c false, the \a value is not added.
190
191 \sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
192 */
193void QMetaSequence::addValueAtBegin(void *container, const void *value) const
194{
195 if (canAddValueAtBegin())
196 d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
197}
198
199/*!
200 Returns \c true if values can be removed from the beginning of the container
201 using \l removeValue() can be placed at the, otherwise returns \c false.
202
203 \sa removeValueAtBegin(), canRemoveValueAtEnd()
204 */
205bool QMetaSequence::canRemoveValueAtBegin() const
206{
207 if (auto iface = d()) {
208 return iface->removeValueFn
209 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
210 }
211 return false;
212}
213
214/*!
215 Removes a value from the beginning of \a container if possible. If
216 \l canRemoveValueAtBegin() returns \c false, the value is not removed.
217
218 \sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
219 */
220void QMetaSequence::removeValueAtBegin(void *container) const
221{
222 if (canRemoveValueAtBegin())
223 d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
224}
225
226/*!
227 Returns \c true if values added using \l addValue() can be placed at the
228 end of the container, otherwise returns \c false.
229
230 \sa addValueAtEnd(), canAddValueAtBegin()
231 */
232bool QMetaSequence::canAddValueAtEnd() const
233{
234 if (auto iface = d()) {
235 return iface->addValueFn
236 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
237 }
238 return false;
239}
240
241/*!
242 Adds \a value to the end of \a container if possible. If
243 \l canAddValueAtEnd() returns \c false, the \a value is not added.
244
245 \sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
246 */
247void QMetaSequence::addValueAtEnd(void *container, const void *value) const
248{
249 if (canAddValueAtEnd())
250 d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
251}
252
253/*!
254 Returns \c true if values can be removed from the end of the container
255 using \l removeValue() can be placed at the, otherwise returns \c false.
256
257 \sa removeValueAtEnd(), canRemoveValueAtBegin()
258 */
259bool QMetaSequence::canRemoveValueAtEnd() const
260{
261 if (auto iface = d()) {
262 return iface->removeValueFn
263 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
264 }
265 return false;
266}
267
268/*!
269 Removes a value from the end of \a container if possible. If
270 \l canRemoveValueAtEnd() returns \c false, the value is not removed.
271
272 \sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
273 */
274void QMetaSequence::removeValueAtEnd(void *container) const
275{
276 if (canRemoveValueAtEnd())
277 d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
278}
279
280/*!
281 Returns \c true if the container can be queried for its size, \c false
282 otherwise.
283
284 \sa size()
285 */
286bool QMetaContainer::hasSize() const
287{
288 return d_ptr && d_ptr->sizeFn;
289}
290
291/*!
292 Returns the number of values in the given \a container if it can be
293 queried for its size. Otherwise returns \c -1.
294
295 \sa hasSize()
296 */
297qsizetype QMetaContainer::size(const void *container) const
298{
299 return hasSize() ? d_ptr->sizeFn(container) : -1;
300}
301
302/*!
303 Returns \c true if the container can be cleared, \c false otherwise.
304
305 \sa clear()
306 */
307bool QMetaContainer::canClear() const
308{
309 return d_ptr && d_ptr->clearFn;
310}
311
312/*!
313 Clears the given \a container if it can be cleared.
314
315 \sa canClear()
316 */
317void QMetaContainer::clear(void *container) const
318{
319 if (canClear())
320 d_ptr->clearFn(container);
321}
322
323/*!
324 Returns \c true if values can be retrieved from the container by index,
325 otherwise \c false.
326
327 \sa valueAtIndex()
328 */
329bool QMetaSequence::canGetValueAtIndex() const
330{
331 if (auto iface = d())
332 return iface->valueAtIndexFn;
333 return false;
334}
335
336/*!
337 Retrieves the value at \a index in the \a container and places it in the
338 memory location pointed to by \a result, if that is possible.
339
340 \sa canGetValueAtIndex()
341 */
342void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *result) const
343{
344 if (canGetValueAtIndex())
345 d()->valueAtIndexFn(container, index, result);
346}
347
348/*!
349 Returns \c true if an value can be written to the container by index,
350 otherwise \c false.
351
352 \sa setValueAtIndex()
353*/
354bool QMetaSequence::canSetValueAtIndex() const
355{
356 if (auto iface = d())
357 return iface->setValueAtIndexFn;
358 return false;
359}
360
361/*!
362 Overwrites the value at \a index in the \a container using the \a value
363 passed as parameter if that is possible.
364
365 \sa canSetValueAtIndex()
366 */
367void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void *value) const
368{
369 if (canSetValueAtIndex())
370 d()->setValueAtIndexFn(container, index, value);
371}
372
373/*!
374 Returns \c true if values can be added to the container, \c false
375 otherwise.
376
377 \sa addValue(), isSortable()
378 */
379bool QMetaSequence::canAddValue() const
380{
381 if (auto iface = d())
382 return iface->addValueFn;
383 return false;
384}
385
386/*!
387 Adds \a value to the \a container if possible. If \l canAddValue()
388 returns \c false, the \a value is not added. Else, if
389 \l canAddValueAtEnd() returns \c true, the \a value is added
390 to the end of the \a container. Else, if
391 \l canAddValueAtBegin() returns \c true, the \a value is added to
392 the beginning of the container. Else, the value is added in an unspecified
393 place or not at all. The latter is the case for adding values to an
394 unordered container, for example \l QSet.
395
396 \sa canAddValue(), canAddValueAtBegin(),
397 canAddValueAtEnd(), isSortable(), removeValue()
398 */
399void QMetaSequence::addValue(void *container, const void *value) const
400{
401 if (canAddValue()) {
402 d()->addValueFn(container, value,
403 QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
404 }
405}
406
407/*!
408 Returns \c true if values can be removed from the container, \c false
409 otherwise.
410
411 \sa removeValue(), isSortable()
412 */
413bool QMetaSequence::canRemoveValue() const
414{
415 if (auto iface = d())
416 return iface->removeValueFn;
417 return false;
418}
419
420/*!
421 Removes an value from the \a container if possible. If
422 \l canRemoveValue() returns \c false, no value is removed. Else, if
423 \l canRemoveValueAtEnd() returns \c true, the last value in
424 the \a container is removed. Else, if \l canRemoveValueAtBegin()
425 returns \c true, the first value in the \a container is removed. Else,
426 an unspecified value or nothing is removed.
427
428 \sa canRemoveValue(), canRemoveValueAtBegin(),
429 canRemoveValueAtEnd(), isSortable(), addValue()
430 */
431void QMetaSequence::removeValue(void *container) const
432{
433 if (canRemoveValue()) {
434 d()->removeValueFn(container,
435 QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
436 }
437}
438
439/*!
440 Returns \c true if the underlying container offers a non-const iterator,
441 \c false otherwise.
442
443 \sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
444 advanceIterator(), copyIterator()
445 */
446bool QMetaContainer::hasIterator() const
447{
448 if (!d_ptr || !d_ptr->createIteratorFn)
449 return false;
450 Q_ASSERT(d_ptr->destroyIteratorFn);
451 Q_ASSERT(d_ptr->compareIteratorFn);
452 Q_ASSERT(d_ptr->copyIteratorFn);
453 Q_ASSERT(d_ptr->advanceIteratorFn);
454 Q_ASSERT(d_ptr->diffIteratorFn);
455 return true;
456}
457
458/*!
459 Creates and returns a non-const iterator pointing to the beginning of
460 \a container. The iterator is allocated on the heap using new. It has to be
461 destroyed using \l destroyIterator eventually, to reclaim the memory.
462
463 Returns \c nullptr if the container doesn't offer any non-const iterators.
464
465 \sa end(), constBegin(), constEnd(), destroyIterator()
466 */
467void *QMetaContainer::begin(void *container) const
468{
469 return hasIterator()
470 ? d_ptr->createIteratorFn(
471 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
472 : nullptr;
473}
474
475/*!
476 Creates and returns a non-const iterator pointing to the end of
477 \a container. The iterator is allocated on the heap using new. It has to be
478 destroyed using \l destroyIterator eventually, to reclaim the memory.
479
480 Returns \c nullptr if the container doesn't offer any non-const iterators.
481
482 \sa hasIterator(), end(), constBegin(), constEnd(), destroyIterator()
483 */
484void *QMetaContainer::end(void *container) const
485{
486 return hasIterator()
487 ? d_ptr->createIteratorFn(
488 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
489 : nullptr;
490}
491
492/*!
493 Destroys a non-const \a iterator previously created using \l begin() or
494 \l end().
495
496 \sa begin(), end(), destroyConstIterator()
497 */
498void QMetaContainer::destroyIterator(const void *iterator) const
499{
500 if (hasIterator())
501 d_ptr->destroyIteratorFn(iterator);
502}
503
504/*!
505 Returns \c true if the non-const iterators \a i and \a j point to the same
506 value in the container they are iterating over, otherwise returns \c
507 false.
508
509 \sa begin(), end()
510 */
511bool QMetaContainer::compareIterator(const void *i, const void *j) const
512{
513 return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
514}
515
516/*!
517 Copies the non-const iterator \a source into the non-const iterator
518 \a target. Afterwards compareIterator(target, source) returns \c true.
519
520 \sa begin(), end()
521 */
522void QMetaContainer::copyIterator(void *target, const void *source) const
523{
524 if (hasIterator())
525 d_ptr->copyIteratorFn(target, source);
526}
527
528/*!
529 Advances the non-const \a iterator by \a step steps. If \a steps is negative
530 the \a iterator is moved backwards, towards the beginning of the container.
531 The behavior is unspecified for negative values of \a step if
532 \l hasBidirectionalIterator() returns false.
533
534 \sa begin(), end()
535 */
536void QMetaContainer::advanceIterator(void *iterator, qsizetype step) const
537{
538 if (hasIterator())
539 d_ptr->advanceIteratorFn(iterator, step);
540}
541
542/*!
543 Returns the distance between the non-const iterators \a i and \a j, the
544 equivalent of \a i \c - \a j. If \a j is closer to the end of the container
545 than \a i, the returned value is negative. The behavior is unspecified in
546 this case if \l hasBidirectionalIterator() returns false.
547
548 \sa begin(), end()
549 */
550qsizetype QMetaContainer::diffIterator(const void *i, const void *j) const
551{
552 return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
553}
554
555/*!
556 Returns \c true if the underlying container can retrieve the value pointed
557 to by a non-const iterator, \c false otherwise.
558
559 \sa hasIterator(), valueAtIterator()
560 */
561bool QMetaSequence::canGetValueAtIterator() const
562{
563 if (auto iface = d())
564 return iface->valueAtIteratorFn;
565 return false;
566}
567
568/*!
569 Retrieves the value pointed to by the non-const \a iterator and stores it
570 in the memory location pointed to by \a result, if possible.
571
572 \sa canGetValueAtIterator(), begin(), end()
573 */
574void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
575{
576 if (canGetValueAtIterator())
577 d()->valueAtIteratorFn(iterator, result);
578}
579
580/*!
581 Returns \c true if the underlying container can write to the value pointed
582 to by a non-const iterator, \c false otherwise.
583
584 \sa hasIterator(), setValueAtIterator()
585 */
586bool QMetaSequence::canSetValueAtIterator() const
587{
588 if (auto iface = d())
589 return iface->setValueAtIteratorFn;
590 return false;
591}
592
593/*!
594 Writes \a value to the value pointed to by the non-const \a iterator, if
595 possible.
596
597 \sa canSetValueAtIterator(), begin(), end()
598 */
599void QMetaSequence::setValueAtIterator(const void *iterator, const void *value) const
600{
601 if (canSetValueAtIterator())
602 d()->setValueAtIteratorFn(iterator, value);
603}
604
605/*!
606 Returns \c true if the underlying container can insert a new value, taking
607 the location pointed to by a non-const iterator into account.
608
609 \sa hasIterator(), insertValueAtIterator()
610 */
611bool QMetaSequence::canInsertValueAtIterator() const
612{
613 if (auto iface = d())
614 return iface->insertValueAtIteratorFn;
615 return false;
616}
617
618/*!
619 Inserts \a value into the \a container, if possible, taking the non-const
620 \a iterator into account. If \l canInsertValueAtIterator() returns
621 \c false, the \a value is not inserted. Else if \l isSortable() returns
622 \c true, the value is inserted before the value pointed to by
623 \a iterator. Else, the \a value is inserted at an unspecified place or not
624 at all. In the latter case, the \a iterator is taken as a hint. If it points
625 to the correct place for the \a value, the operation may be faster than a
626 \l addValue() without iterator.
627
628 \sa canInsertValueAtIterator(), isSortable(), begin(), end()
629 */
630void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
631 const void *value) const
632{
633 if (canInsertValueAtIterator())
634 d()->insertValueAtIteratorFn(container, iterator, value);
635}
636
637/*!
638 Returns \c true if the value pointed to by a non-const iterator can be
639 erased, \c false otherwise.
640
641 \sa hasIterator(), eraseValueAtIterator()
642 */
643bool QMetaSequence::canEraseValueAtIterator() const
644{
645 if (auto iface = d())
646 return iface->eraseValueAtIteratorFn;
647 return false;
648}
649
650/*!
651 Erases the value pointed to by the non-const \a iterator from the
652 \a container, if possible.
653
654 \sa canEraseValueAtIterator(), begin(), end()
655 */
656void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator) const
657{
658 if (canEraseValueAtIterator())
659 d()->eraseValueAtIteratorFn(container, iterator);
660}
661
662/*!
663 Returns \c true if a range between two iterators can be erased from the
664 container, \c false otherwise.
665 */
666bool QMetaSequence::canEraseRangeAtIterator() const
667{
668 if (auto iface = d())
669 return iface->eraseRangeAtIteratorFn;
670 return false;
671}
672
673/*!
674 Erases the range of values between the iterators \a iterator1 and
675 \a iterator2 from the \a container, if possible.
676
677 \sa canEraseValueAtIterator(), begin(), end()
678 */
679void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
680 const void *iterator2) const
681{
682 if (canEraseRangeAtIterator())
683 d()->eraseRangeAtIteratorFn(container, iterator1, iterator2);
684}
685
686/*!
687 Returns \c true if the underlying container offers a const iterator,
688 \c false otherwise.
689
690 \sa constBegin(), constEnd(), destroyConstIterator(),
691 compareConstIterator(), diffConstIterator(), advanceConstIterator(),
692 copyConstIterator()
693 */
694bool QMetaContainer::hasConstIterator() const
695{
696 if (!d_ptr || !d_ptr->createConstIteratorFn)
697 return false;
698 Q_ASSERT(d_ptr->destroyConstIteratorFn);
699 Q_ASSERT(d_ptr->compareConstIteratorFn);
700 Q_ASSERT(d_ptr->copyConstIteratorFn);
701 Q_ASSERT(d_ptr->advanceConstIteratorFn);
702 Q_ASSERT(d_ptr->diffConstIteratorFn);
703 return true;
704}
705
706/*!
707 Creates and returns a const iterator pointing to the beginning of
708 \a container. The iterator is allocated on the heap using new. It has to be
709 destroyed using \l destroyConstIterator eventually, to reclaim the memory.
710
711 Returns \c nullptr if the container doesn't offer any const iterators.
712
713 \sa constEnd(), begin(), end(), destroyConstIterator()
714 */
715void *QMetaContainer::constBegin(const void *container) const
716{
717 return hasConstIterator()
718 ? d_ptr->createConstIteratorFn(
719 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
720 : nullptr;
721}
722
723/*!
724 Creates and returns a const iterator pointing to the end of
725 \a container. The iterator is allocated on the heap using new. It has to be
726 destroyed using \l destroyConstIterator eventually, to reclaim the memory.
727
728 Returns \c nullptr if the container doesn't offer any const iterators.
729
730 \sa constBegin(), begin(), end(), destroyConstIterator()
731 */
732void *QMetaContainer::constEnd(const void *container) const
733{
734 return hasConstIterator()
735 ? d_ptr->createConstIteratorFn(
736 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
737 : nullptr;
738}
739
740/*!
741 Destroys a const \a iterator previously created using \l constBegin() or
742 \l constEnd().
743
744 \sa constBegin(), constEnd(), destroyIterator()
745 */
746void QMetaContainer::destroyConstIterator(const void *iterator) const
747{
748 if (hasConstIterator())
749 d_ptr->destroyConstIteratorFn(iterator);
750}
751
752/*!
753 Returns \c true if the const iterators \a i and \a j point to the same
754 value in the container they are iterating over, otherwise returns \c
755 false.
756
757 \sa constBegin(), constEnd()
758 */
759bool QMetaContainer::compareConstIterator(const void *i, const void *j) const
760{
761 return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
762}
763
764/*!
765 Copies the const iterator \a source into the const iterator
766 \a target. Afterwards compareConstIterator(target, source) returns \c true.
767
768 \sa constBegin(), constEnd()
769 */
770void QMetaContainer::copyConstIterator(void *target, const void *source) const
771{
772 if (hasConstIterator())
773 d_ptr->copyConstIteratorFn(target, source);
774}
775
776/*!
777 Advances the const \a iterator by \a step steps. If \a steps is negative
778 the \a iterator is moved backwards, towards the beginning of the container.
779 The behavior is unspecified for negative values of \a step if
780 \l hasBidirectionalIterator() returns false.
781
782 \sa constBegin(), constEnd()
783 */
784void QMetaContainer::advanceConstIterator(void *iterator, qsizetype step) const
785{
786 if (hasConstIterator())
787 d_ptr->advanceConstIteratorFn(iterator, step);
788}
789
790/*!
791 Returns the distance between the const iterators \a i and \a j, the
792 equivalent of \a i \c - \a j. If \a j is closer to the end of the container
793 than \a i, the returned value is negative. The behavior is unspecified in
794 this case if \l hasBidirectionalIterator() returns false.
795
796 \sa constBegin(), constEnd()
797 */
798qsizetype QMetaContainer::diffConstIterator(const void *i, const void *j) const
799{
800 return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
801}
802
803/*!
804 Returns \c true if the underlying container can retrieve the value pointed
805 to by a const iterator, \c false otherwise.
806
807 \sa hasConstIterator(), valueAtConstIterator()
808 */
809bool QMetaSequence::canGetValueAtConstIterator() const
810{
811 if (auto iface = d())
812 return iface->valueAtConstIteratorFn;
813 return false;
814}
815
816/*!
817 Retrieves the value pointed to by the const \a iterator and stores it
818 in the memory location pointed to by \a result, if possible.
819
820 \sa canGetValueAtConstIterator(), constBegin(), constEnd()
821 */
822void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) const
823{
824 if (canGetValueAtConstIterator())
825 d()->valueAtConstIteratorFn(iterator, result);
826}
827
828/*!
829 \fn bool operator==(QMetaSequence a, QMetaSequence b)
830 \since 6.0
831 \relates QMetaSequence
832
833 Returns \c true if the QMetaSequence \a a represents the same container type
834 as the QMetaSequence \a b, otherwise returns \c false.
835*/
836
837/*!
838 \fn bool operator!=(QMetaSequence a, QMetaSequence b)
839 \since 6.0
840 \relates QMetaSequence
841
842 Returns \c true if the QMetaSequence \a a represents a different container
843 type than the QMetaSequence \a b, otherwise returns \c false.
844*/
845
846
847/*!
848 Returns the meta type for keys in the container.
849 */
850QMetaType QMetaAssociation::keyMetaType() const
851{
852 if (auto iface = d())
853 return QMetaType(iface->keyMetaType);
854 return QMetaType();
855}
856
857/*!
858 Returns the meta type for mapped values in the container.
859 */
860QMetaType QMetaAssociation::mappedMetaType() const
861{
862 if (auto iface = d())
863 return QMetaType(iface->mappedMetaType);
864 return QMetaType();
865}
866
867QT_END_NAMESPACE
868