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#else // QT_NO_JAVA_STYLE_ITERATORS
185#define Q_DECLARE_SEQUENTIAL_ITERATOR(C)
186#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C)
187#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C)
188#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C)
189#endif // QT_NO_JAVA_STYLE_ITERATORS
190
191template<typename Key, typename T, class Iterator>
192class QKeyValueIterator
193{
194public:
195 typedef typename Iterator::iterator_category iterator_category;
196 typedef typename Iterator::difference_type difference_type;
197 typedef std::pair<Key, T> value_type;
198 typedef const value_type &reference;
199
200 QKeyValueIterator() = default;
201 Q_DECL_CONSTEXPR explicit QKeyValueIterator(Iterator o) noexcept(std::is_nothrow_move_constructible<Iterator>::value)
202 : i(std::move(o)) {}
203
204 std::pair<Key, T> operator*() const {
205 return std::pair<Key, T>(i.key(), i.value());
206 }
207
208 struct pointer {
209 pointer(value_type&& r_)
210 : r(std::move(r_))
211 {}
212
213 pointer() = default;
214 pointer(const pointer &other) = default;
215 pointer(pointer &&other) = default;
216 pointer& operator=(const pointer &other) = default;
217 pointer& operator=(pointer &&other) = default;
218
219 value_type& operator*() const {
220 return r;
221 }
222
223 value_type r;
224 const value_type *operator->() const {
225 return &r;
226 }
227 };
228
229 pointer operator->() const {
230 return pointer(std::pair<Key, T>(i.key(), i.value()));
231 }
232
233 friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; }
234 friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i != rhs.i; }
235
236 inline QKeyValueIterator &operator++() { ++i; return *this; }
237 inline QKeyValueIterator operator++(int) { return QKeyValueIterator(i++);}
238 inline QKeyValueIterator &operator--() { --i; return *this; }
239 inline QKeyValueIterator operator--(int) { return QKeyValueIterator(i--); }
240 Iterator base() const { return i; }
241
242private:
243 Iterator i;
244};
245
246QT_END_NAMESPACE
247
248#endif // QITERATOR_H
249