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 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | class Q_CORE_EXPORT QSequentialIterator : public QIterator<QMetaSequence> |
13 | { |
14 | public: |
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 | |
27 | class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator<QMetaSequence> |
28 | { |
29 | public: |
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 | |
42 | class Q_CORE_EXPORT QSequentialIterable : public QIterable<QMetaSequence> |
43 | { |
44 | public: |
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 | |
123 | template<> |
124 | inline 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 | |
135 | template<> |
136 | inline 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 | |
149 | Q_DECLARE_TYPEINFO(QSequentialIterable, Q_RELOCATABLE_TYPE); |
150 | Q_DECLARE_TYPEINFO(QSequentialIterable::iterator, Q_RELOCATABLE_TYPE); |
151 | Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_RELOCATABLE_TYPE); |
152 | |
153 | QT_END_NAMESPACE |
154 | |
155 | #endif // QSEQUENTIALITERABLE_H |
156 | |