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