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 QSEQUENTIALITERABLE_H
5#define QSEQUENTIALITERABLE_H
6
7#include <QtCore/qiterable.h>
8#include <QtCore/qvariant.h>
9
10QT_BEGIN_NAMESPACE
11
12class Q_CORE_EXPORT QSequentialIterator : public QIterator<QMetaSequence>
13{
14public:
15 using value_type = QVariant;
16 using reference = QVariantRef<QSequentialIterator>;
17 using pointer = QVariantPointer<QSequentialIterator>;
18
19 QSequentialIterator(QIterator &&it)
20 : QIterator(std::move(it))
21 {}
22
23 QVariantRef<QSequentialIterator> operator*() const;
24 QVariantPointer<QSequentialIterator> operator->() const;
25};
26
27class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator<QMetaSequence>
28{
29public:
30 using value_type = QVariant;
31 using reference = const QVariant &;
32 using pointer = QVariantConstPointer;
33
34 QSequentialConstIterator(QConstIterator &&it)
35 : QConstIterator(std::move(it))
36 {}
37
38 QVariant operator*() const;
39 QVariantConstPointer operator->() const;
40};
41
42class Q_CORE_EXPORT QSequentialIterable : public QIterable<QMetaSequence>
43{
44public:
45 using iterator = QTaggedIterator<QSequentialIterator, void>;
46 using const_iterator = QTaggedIterator<QSequentialConstIterator, void>;
47
48 using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
49 using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
50 using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
51 using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
52
53 using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
54 using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
55 using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
56 using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
57
58 template<class T>
59 QSequentialIterable(const T *p)
60 : QIterable(QMetaSequence::fromContainer<T>(), p)
61 {
62 Q_UNUSED(m_revision);
63 }
64
65 template<class T>
66 QSequentialIterable(T *p)
67 : QIterable(QMetaSequence::fromContainer<T>(), p)
68 {
69 }
70
71 QSequentialIterable()
72 : QIterable(QMetaSequence(), nullptr)
73 {
74 }
75
76 template<typename Pointer>
77 QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
78 : QIterable(metaSequence, iterable)
79 {
80 }
81
82 // ### Qt7: Pass QMetaType as value rather than const ref.
83 QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
84 void *iterable)
85 : QIterable(metaSequence, metaType.alignOf(), iterable)
86 {
87 }
88
89 // ### Qt7: Pass QMetaType as value rather than const ref.
90 QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
91 const void *iterable)
92 : QIterable(metaSequence, metaType.alignOf(), iterable)
93 {
94 }
95
96 QSequentialIterable(QIterable<QMetaSequence> &&other) : QIterable(std::move(other)) {}
97
98 QSequentialIterable &operator=(QIterable<QMetaSequence> &&other)
99 {
100 QIterable::operator=(std::move(other));
101 return *this;
102 }
103
104 const_iterator begin() const { return constBegin(); }
105 const_iterator end() const { return constEnd(); }
106
107 const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
108 const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
109
110 iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
111 iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
112
113 QVariant at(qsizetype idx) const;
114 void set(qsizetype idx, const QVariant &value);
115
116 enum Position { Unspecified, AtBegin, AtEnd };
117 void addValue(const QVariant &value, Position position = Unspecified);
118 void removeValue(Position position = Unspecified);
119
120 QMetaType valueMetaType() const;
121};
122
123template<>
124inline QVariantRef<QSequentialIterator>::operator QVariant() const
125{
126 if (m_pointer == nullptr)
127 return QVariant();
128 const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
129 QVariant v(metaType);
130 void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
131 m_pointer->metaContainer().valueAtIterator(iterator: m_pointer->constIterator(), result: dataPtr);
132 return v;
133}
134
135template<>
136inline QVariantRef<QSequentialIterator> &QVariantRef<QSequentialIterator>::operator=(
137 const QVariant &value)
138{
139 if (m_pointer == nullptr)
140 return *this;
141
142 QtPrivate::QVariantTypeCoercer coercer;
143 m_pointer->metaContainer().setValueAtIterator(
144 iterator: m_pointer->constIterator(),
145 value: coercer.coerce(value, type: m_pointer->metaContainer().valueMetaType()));
146 return *this;
147}
148
149Q_DECLARE_TYPEINFO(QSequentialIterable, Q_RELOCATABLE_TYPE);
150Q_DECLARE_TYPEINFO(QSequentialIterable::iterator, Q_RELOCATABLE_TYPE);
151Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_RELOCATABLE_TYPE);
152
153QT_END_NAMESPACE
154
155#endif // QSEQUENTIALITERABLE_H
156

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