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#ifndef QSEQUENTIALITERABLE_H
41#define QSEQUENTIALITERABLE_H
42
43#include <QtCore/qiterable.h>
44#include <QtCore/qvariant.h>
45
46QT_BEGIN_NAMESPACE
47
48class Q_CORE_EXPORT QSequentialIterator : public QIterator<QMetaSequence>
49{
50public:
51 using value_type = QVariant;
52 using reference = QVariantRef<QSequentialIterator>;
53 using pointer = QVariantPointer<QSequentialIterator>;
54
55 QSequentialIterator(QIterator &&it)
56 : QIterator(std::move(it))
57 {}
58
59 QVariantRef<QSequentialIterator> operator*() const;
60 QVariantPointer<QSequentialIterator> operator->() const;
61};
62
63class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator<QMetaSequence>
64{
65public:
66 using value_type = QVariant;
67 using reference = const QVariant &;
68 using pointer = QVariantConstPointer;
69
70 QSequentialConstIterator(QConstIterator &&it)
71 : QConstIterator(std::move(it))
72 {}
73
74 QVariant operator*() const;
75 QVariantConstPointer operator->() const;
76};
77
78class Q_CORE_EXPORT QSequentialIterable : public QIterable<QMetaSequence>
79{
80public:
81 using iterator = QTaggedIterator<QSequentialIterator, void>;
82 using const_iterator = QTaggedIterator<QSequentialConstIterator, void>;
83
84 using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
85 using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
86 using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
87 using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
88
89 using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
90 using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
91 using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
92 using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
93
94 template<class T>
95 QSequentialIterable(const T *p)
96 : QIterable(QMetaSequence::fromContainer<T>(), p)
97 {
98 Q_UNUSED(m_revision);
99 }
100
101 template<class T>
102 QSequentialIterable(T *p)
103 : QIterable(QMetaSequence::fromContainer<T>(), p)
104 {
105 }
106
107 QSequentialIterable()
108 : QIterable(QMetaSequence(), nullptr)
109 {
110 }
111
112 template<typename Pointer>
113 QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
114 : QIterable(metaSequence, iterable)
115 {
116 }
117
118 QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
119 void *iterable)
120 : QIterable(metaSequence, metaType.alignOf(), iterable)
121 {
122 }
123
124 QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
125 const void *iterable)
126 : QIterable(metaSequence, metaType.alignOf(), iterable)
127 {
128 }
129
130 QSequentialIterable(QIterable<QMetaSequence> &&other) : QIterable(std::move(other)) {}
131
132 QSequentialIterable &operator=(QIterable<QMetaSequence> &&other)
133 {
134 QIterable::operator=(std::move(other));
135 return *this;
136 }
137
138 const_iterator begin() const { return constBegin(); }
139 const_iterator end() const { return constEnd(); }
140
141 const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
142 const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
143
144 iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
145 iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
146
147 QVariant at(qsizetype idx) const;
148 void set(qsizetype idx, const QVariant &value);
149
150 enum Position { Unspecified, AtBegin, AtEnd };
151 void addValue(const QVariant &value, Position position = Unspecified);
152 void removeValue(Position position = Unspecified);
153
154 QMetaType valueMetaType() const;
155};
156
157template<>
158inline QVariantRef<QSequentialIterator>::operator QVariant() const
159{
160 if (m_pointer == nullptr)
161 return QVariant();
162 const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
163 QVariant v(metaType);
164 void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
165 m_pointer->metaContainer().valueAtIterator(m_pointer->constIterator(), dataPtr);
166 return v;
167}
168
169template<>
170inline QVariantRef<QSequentialIterator> &QVariantRef<QSequentialIterator>::operator=(
171 const QVariant &value)
172{
173 if (m_pointer == nullptr)
174 return *this;
175
176 QtPrivate::QVariantTypeCoercer coercer;
177 m_pointer->metaContainer().setValueAtIterator(
178 m_pointer->constIterator(),
179 coercer.coerce(value, m_pointer->metaContainer().valueMetaType()));
180 return *this;
181}
182
183Q_DECLARE_TYPEINFO(QSequentialIterable, Q_MOVABLE_TYPE);
184Q_DECLARE_TYPEINFO(QSequentialIterable::iterator, Q_MOVABLE_TYPE);
185Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_MOVABLE_TYPE);
186
187QT_END_NAMESPACE
188
189#endif // QSEQUENTIALITERABLE_H
190