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

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