1// Copyright (C) 2016 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 QITERATOR_H
5#define QITERATOR_H
6
7#include <QtCore/qglobal.h>
8
9QT_BEGIN_NAMESPACE
10
11#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
12
13#ifdef Q_QDOC
14#define Q_DISABLE_BACKWARD_ITERATOR
15#else
16#define Q_DISABLE_BACKWARD_ITERATOR \
17 template<typename It = decltype(i), QtPrivate::IfIteratorCanMoveBackwards<It> = true>
18#endif
19
20#define Q_DECLARE_SEQUENTIAL_ITERATOR(C) \
21\
22template <class T> \
23class Q##C##Iterator \
24{ \
25 typedef typename Q##C<T>::const_iterator const_iterator; \
26 Q##C<T> c; \
27 const_iterator i; \
28public: \
29 inline Q##C##Iterator(const Q##C<T> &container) \
30 : c(container), i(c.constBegin()) {} \
31 inline Q##C##Iterator &operator=(const Q##C<T> &container) \
32 { c = container; i = c.constBegin(); return *this; } \
33 inline void toFront() { i = c.constBegin(); } \
34 inline void toBack() { i = c.constEnd(); } \
35 inline bool hasNext() const { return i != c.constEnd(); } \
36 inline const T &next() { return *i++; } \
37 inline const T &peekNext() const { return *i; } \
38 Q_DISABLE_BACKWARD_ITERATOR \
39 inline bool hasPrevious() const { return i != c.constBegin(); } \
40 Q_DISABLE_BACKWARD_ITERATOR \
41 inline const T &previous() { return *--i; } \
42 Q_DISABLE_BACKWARD_ITERATOR \
43 inline const T &peekPrevious() const { const_iterator p = i; return *--p; } \
44 inline bool findNext(const T &t) \
45 { while (i != c.constEnd()) if (*i++ == t) return true; return false; } \
46 Q_DISABLE_BACKWARD_ITERATOR \
47 inline bool findPrevious(const T &t) \
48 { while (i != c.constBegin()) if (*(--i) == t) return true; \
49 return false; } \
50};
51
52#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C) \
53\
54template <class T> \
55class QMutable##C##Iterator \
56{ \
57 typedef typename Q##C<T>::iterator iterator; \
58 typedef typename Q##C<T>::const_iterator const_iterator; \
59 Q##C<T> *c; \
60 iterator i, n; \
61 inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
62public: \
63 inline QMutable##C##Iterator(Q##C<T> &container) \
64 : c(&container) \
65 { i = c->begin(); n = c->end(); } \
66 inline QMutable##C##Iterator &operator=(Q##C<T> &container) \
67 { c = &container; i = c->begin(); n = c->end(); return *this; } \
68 inline void toFront() { i = c->begin(); n = c->end(); } \
69 inline void toBack() { i = c->end(); n = i; } \
70 inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
71 inline T &next() { n = i++; return *n; } \
72 inline T &peekNext() const { return *i; } \
73 Q_DISABLE_BACKWARD_ITERATOR \
74 inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); } \
75 Q_DISABLE_BACKWARD_ITERATOR \
76 inline T &previous() { n = --i; return *n; } \
77 Q_DISABLE_BACKWARD_ITERATOR \
78 inline T &peekPrevious() const { iterator p = i; return *--p; } \
79 inline void remove() \
80 { if (c->constEnd() != const_iterator(n)) { i = c->erase(n); n = c->end(); } } \
81 inline void setValue(const T &t) const { if (c->constEnd() != const_iterator(n)) *n = t; } \
82 inline T &value() { Q_ASSERT(item_exists()); return *n; } \
83 inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
84 inline void insert(const T &t) { n = i = c->insert(i, t); ++i; } \
85 inline bool findNext(const T &t) \
86 { while (c->constEnd() != const_iterator(n = i)) if (*i++ == t) return true; return false; } \
87 Q_DISABLE_BACKWARD_ITERATOR \
88 inline bool findPrevious(const T &t) \
89 { while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true; \
90 n = c->end(); return false; } \
91};
92
93#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C) \
94\
95template <class Key, class T> \
96class Q##C##Iterator \
97{ \
98 typedef typename Q##C<Key,T>::const_iterator const_iterator; \
99 Q##C<Key,T> c; \
100 const_iterator i, n; \
101 inline bool item_exists() const { return n != c.constEnd(); } \
102public: \
103 typedef const_iterator Item; \
104 inline Q##C##Iterator(const Q##C<Key,T> &container) \
105 : c(container), i(c.constBegin()), n(c.constEnd()) {} \
106 inline Q##C##Iterator &operator=(const Q##C<Key,T> &container) \
107 { c = container; i = c.constBegin(); n = c.constEnd(); return *this; } \
108 inline void toFront() { i = c.constBegin(); n = c.constEnd(); } \
109 inline void toBack() { i = c.constEnd(); n = c.constEnd(); } \
110 inline bool hasNext() const { return i != c.constEnd(); } \
111 inline Item next() { n = i++; return n; } \
112 inline Item peekNext() const { return i; } \
113 Q_DISABLE_BACKWARD_ITERATOR \
114 inline bool hasPrevious() const { return i != c.constBegin(); } \
115 Q_DISABLE_BACKWARD_ITERATOR \
116 inline Item previous() { n = --i; return n; } \
117 Q_DISABLE_BACKWARD_ITERATOR \
118 inline Item peekPrevious() const { const_iterator p = i; return --p; } \
119 inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
120 inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
121 inline bool findNext(const T &t) \
122 { while ((n = i) != c.constEnd()) if (*i++ == t) return true; return false; } \
123 Q_DISABLE_BACKWARD_ITERATOR \
124 inline bool findPrevious(const T &t) \
125 { while (i != c.constBegin()) if (*(n = --i) == t) return true; \
126 n = c.constEnd(); return false; } \
127};
128
129#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C) \
130\
131template <class Key, class T> \
132class QMutable##C##Iterator \
133{ \
134 typedef typename Q##C<Key,T>::iterator iterator; \
135 typedef typename Q##C<Key,T>::const_iterator const_iterator; \
136 Q##C<Key,T> *c; \
137 iterator i, n; \
138 inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
139public: \
140 typedef iterator Item; \
141 inline QMutable##C##Iterator(Q##C<Key,T> &container) \
142 : c(&container) \
143 { i = c->begin(); n = c->end(); } \
144 inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
145 { c = &container; i = c->begin(); n = c->end(); return *this; } \
146 inline void toFront() { i = c->begin(); n = c->end(); } \
147 inline void toBack() { i = c->end(); n = c->end(); } \
148 inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
149 inline Item next() { n = i++; return n; } \
150 inline Item peekNext() const { return i; } \
151 Q_DISABLE_BACKWARD_ITERATOR \
152 inline bool hasPrevious() const { return const_iterator(i) != c->constBegin(); } \
153 Q_DISABLE_BACKWARD_ITERATOR \
154 inline Item previous() { n = --i; return n; } \
155 Q_DISABLE_BACKWARD_ITERATOR \
156 inline Item peekPrevious() const { iterator p = i; return --p; } \
157 inline void remove() \
158 { if (const_iterator(n) != c->constEnd()) { i = c->erase(n); n = c->end(); } } \
159 inline void setValue(const T &t) { if (const_iterator(n) != c->constEnd()) *n = t; } \
160 inline T &value() { Q_ASSERT(item_exists()); return *n; } \
161 inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
162 inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
163 inline bool findNext(const T &t) \
164 { while (const_iterator(n = i) != c->constEnd()) if (*i++ == t) return true; return false; } \
165 Q_DISABLE_BACKWARD_ITERATOR \
166 inline bool findPrevious(const T &t) \
167 { while (const_iterator(i) != c->constBegin()) if (*(n = --i) == t) return true; \
168 n = c->end(); return false; } \
169};
170
171#define Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(C) \
172\
173template <class Key, class T> \
174class Q##C##Iterator \
175{ \
176 typedef typename Q##C<Key,T>::const_iterator const_iterator; \
177 Q##C<Key,T> c; \
178 const_iterator i, n; \
179 inline bool item_exists() const { return n != c.constEnd(); } \
180public: \
181 typedef const_iterator Item; \
182 inline Q##C##Iterator(const Q##C<Key,T> &container) \
183 : c(container), i(c.constBegin()), n(c.constEnd()) {} \
184 inline Q##C##Iterator &operator=(const Q##C<Key,T> &container) \
185 { c = container; i = c.constBegin(); n = c.constEnd(); return *this; } \
186 inline void toFront() { i = c.constBegin(); n = c.constEnd(); } \
187 inline void toBack() { i = c.constEnd(); n = c.constEnd(); } \
188 inline bool hasNext() const { return i != c.constEnd(); } \
189 inline Item next() { n = i++; return n; } \
190 inline Item peekNext() const { return i; } \
191 inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
192 inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
193 inline bool findNext(const T &t) \
194 { while ((n = i) != c.constEnd()) if (*i++ == t) return true; return false; } \
195};
196
197#define Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(C) \
198\
199template <class Key, class T> \
200class QMutable##C##Iterator \
201{ \
202 typedef typename Q##C<Key,T>::iterator iterator; \
203 typedef typename Q##C<Key,T>::const_iterator const_iterator; \
204 Q##C<Key,T> *c; \
205 iterator i, n; \
206 inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
207public: \
208 typedef iterator Item; \
209 inline QMutable##C##Iterator(Q##C<Key,T> &container) \
210 : c(&container) \
211 { i = c->begin(); n = c->end(); } \
212 inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
213 { c = &container; i = c->begin(); n = c->end(); return *this; } \
214 inline void toFront() { i = c->begin(); n = c->end(); } \
215 inline void toBack() { i = c->end(); n = c->end(); } \
216 inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
217 inline Item next() { n = i++; return n; } \
218 inline Item peekNext() const { return i; } \
219 inline void remove() \
220 { if (const_iterator(n) != c->constEnd()) { i = c->erase(n); n = c->end(); } } \
221 inline void setValue(const T &t) { if (const_iterator(n) != c->constEnd()) *n = t; } \
222 inline T &value() { Q_ASSERT(item_exists()); return *n; } \
223 inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
224 inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
225 inline bool findNext(const T &t) \
226 { while (const_iterator(n = i) != c->constEnd()) if (*i++ == t) return true; return false; } \
227};
228
229
230#else // QT_NO_JAVA_STYLE_ITERATORS
231#define Q_DECLARE_SEQUENTIAL_ITERATOR(C)
232#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C)
233#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C)
234#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C)
235#define Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(C)
236#define Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(C)
237#endif // QT_NO_JAVA_STYLE_ITERATORS
238
239template<typename Key, typename T, class Iterator>
240class QKeyValueIterator
241{
242public:
243 typedef typename Iterator::iterator_category iterator_category;
244 typedef typename Iterator::difference_type difference_type;
245 typedef std::pair<Key, T> value_type;
246 typedef const value_type &reference;
247
248 QKeyValueIterator() = default;
249 constexpr explicit QKeyValueIterator(Iterator o) noexcept(std::is_nothrow_move_constructible<Iterator>::value)
250 : i(std::move(o)) {}
251
252 std::pair<Key, T> operator*() const {
253 return std::pair<Key, T>(i.key(), i.value());
254 }
255
256 struct pointer
257 {
258 pointer(value_type &&r_) : r(std::move(r_)) { }
259
260 pointer() = default;
261 pointer(const pointer &other) = default;
262 pointer(pointer &&other) = default;
263 pointer &operator=(const pointer &other) = default;
264 pointer &operator=(pointer &&other) = default;
265
266 value_type &operator*() const { return r; }
267
268 value_type r;
269 const value_type *operator->() const {
270 return &r;
271 }
272 };
273
274 pointer operator->() const {
275 return pointer(std::pair<Key, T>(i.key(), i.value()));
276 }
277
278 friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; }
279 friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i != rhs.i; }
280
281 inline QKeyValueIterator &operator++() { ++i; return *this; }
282 inline QKeyValueIterator operator++(int) { return QKeyValueIterator(i++);}
283 inline QKeyValueIterator &operator--() { --i; return *this; }
284 inline QKeyValueIterator operator--(int) { return QKeyValueIterator(i--); }
285 Iterator base() const { return i; }
286
287private:
288 Iterator i;
289};
290
291namespace QtPrivate {
292
293template <typename Map>
294class QKeyValueRangeStorage
295{
296protected:
297 Map m_map;
298public:
299 explicit QKeyValueRangeStorage(const Map &map) : m_map(map) {}
300 explicit QKeyValueRangeStorage(Map &&map) : m_map(std::move(map)) {}
301};
302
303template <typename Map>
304class QKeyValueRangeStorage<Map &>
305{
306protected:
307 Map &m_map;
308public:
309 explicit QKeyValueRangeStorage(Map &map) : m_map(map) {}
310};
311
312template <typename Map>
313class QKeyValueRange : public QKeyValueRangeStorage<Map>
314{
315public:
316 using QKeyValueRangeStorage<Map>::QKeyValueRangeStorage;
317 auto begin() { return this->m_map.keyValueBegin(); }
318 auto begin() const { return this->m_map.keyValueBegin(); }
319 auto end() { return this->m_map.keyValueEnd(); }
320 auto end() const { return this->m_map.keyValueEnd(); }
321};
322
323template <typename Map>
324QKeyValueRange(Map &) -> QKeyValueRange<Map &>;
325
326template <typename Map, std::enable_if_t<!std::is_reference_v<Map>, bool> = false>
327QKeyValueRange(Map &&) -> QKeyValueRange<std::remove_const_t<Map>>;
328
329} // namespace QtPrivate
330
331
332QT_END_NAMESPACE
333
334#endif // QITERATOR_H
335

source code of qtbase/src/corelib/tools/qiterator.h