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