Tulip 5.7.1
Large graphs analysis and drawing
Loading...
Searching...
No Matches
Iterator.h
1/*
2 *
3 * This file is part of Tulip (https://tulip.labri.fr)
4 *
5 * Authors: David Auber and the Tulip development Team
6 * from LaBRI, University of Bordeaux
7 *
8 * Tulip is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation, either version 3
11 * of the License, or (at your option) any later version.
12 *
13 * Tulip is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
17 *
18 */
19
20#ifndef TULIP_ITERATOR_H
21#define TULIP_ITERATOR_H
22
23#include <cassert>
24#include <list>
25#include <set>
26#include <tuple>
27#include <vector>
28
29#include <tulip/tulipconf.h>
30
31namespace tlp {
32
33///@cond DOXYGEN_HIDDEN
34#ifndef NDEBUG
35extern TLP_SCOPE void incrNumIterators();
36extern TLP_SCOPE void decrNumIterators();
37extern TLP_SCOPE int getNumIterators();
38#endif
39///@endcond
40
41/**
42 * @brief Interface for Tulip iterators.
43 * Allows basic iteration operations only.
44 *
45 * Below are some examples about how to use Tulip iterators in C++ code.
46 *
47 * @code
48 *
49 * // graph is a pointer to a tlp::Graph instance
50 *
51 * // shortest syntax using C++11 for range based loops
52 * for (auto n : graph->getNodes()) {
53 * // do something with n
54 * }
55 *
56 * // legacy syntax using Tulip forEach macro
57 * #include <tulip/ForEach.h>
58 * tlp::node n;
59 * forEach(n, graph->getNodes()) {
60 * // do something with n
61 * }
62 *
63 * // no syntactic sugar syntax (needs to explicitly delete the iterator
64 * // after its use)
65 * tlp::Iterator<tl::node> *nodesIt = graph->getNodes();
66 * while (nodesIt->hasNext()) {
67 * tlp::node n = nodes->next();
68 * // do something with n
69 * }
70 * delete nodesIt;
71 * @endcode
72 **/
73template <typename T>
74struct Iterator {
75 ///
76 Iterator() {
77#ifndef NDEBUG
78 incrNumIterators();
79#endif
80 }
81 ///
82 virtual ~Iterator() {
83#ifndef NDEBUG
84 decrNumIterators();
85#endif
86 }
87 /**
88 * @brief Moves the Iterator on the next element.
89 *
90 * @return The current element pointed by the Iterator.
91 **/
92 virtual T next() = 0;
93
94 /**
95 * @brief Tells if the sequence is at its end.
96 *
97 * @return bool Whether there are more elements to iterate.
98 **/
99 virtual bool hasNext() = 0;
100
101private:
102 // glue code in order to use Tulip iterators with C++11 for range based loops
103 struct iterator_t {
104
105 enum IteratorStatus { Begin = 0, Finished = 1, End = 3 };
106
107 IteratorStatus _iteratorStatus;
108 Iterator<T> *_it;
109
110 iterator_t(Iterator<T> *it, IteratorStatus iteratorStatus = End)
111 : _iteratorStatus(iteratorStatus), _it(it) {
112 if ((_iteratorStatus == Begin) && (_it->hasNext() == false)) {
113 _iteratorStatus = Finished;
114 }
115 }
116
117 ~iterator_t() {
118 if (_iteratorStatus != End) {
119 delete _it;
120 }
121 }
122
123 inline bool operator!=(const iterator_t &it) const {
124 return ((_iteratorStatus & it._iteratorStatus) == 0) || (_it != it._it);
125 }
126
127 inline const iterator_t &operator++() {
128 if (!_it->hasNext())
129 _iteratorStatus = Finished;
130 return *this;
131 }
132
133 inline T operator*() const {
134 assert(_iteratorStatus != Finished);
135 return _it->next();
136 }
137 };
138
139public:
140 inline iterator_t begin() {
141 return iterator_t(this, iterator_t::Begin);
142 }
143
144 inline iterator_t end() {
145 return iterator_t(this);
146 }
147};
148
149#ifndef DOXYGEN_NOTFOR_DEVEL
150// as Iterator is only accessible through pointer
151// we must have a specific definition of begin and end
152template <typename T>
153inline auto begin(Iterator<T> *it) -> decltype(it->begin()) {
154 return it->begin();
155}
156
157template <typename T>
158inline auto end(Iterator<T> *it) -> decltype(it->end()) {
159 return it->end();
160}
161#endif
162
163/**
164 * @brief Counts the number of iterated elements
165 * @ingroup Iterators
166 *
167 * @since Tulip 5.2
168 *
169 * Counts the number of elements iterated by the provided iterator.
170 * That function takes ownership of the iterator and will delete it.
171 *
172 * @param it a Tulip iterator
173 *
174 * @return The number of iterated elements
175 **/
176template <typename T>
177inline unsigned int iteratorCount(Iterator<T> *it) {
178 unsigned int count = 0;
179 while (it->hasNext()) {
180 ++count;
181 it->next();
182 }
183 delete it;
184 return count;
185}
186
187/**
188 * @brief Checks a minimum amount of iterated elements
189 * @ingroup Iterators
190 *
191 * @since Tulip 5.2
192 *
193 * Checks if the iterator returns at least n values.
194 * That function takes ownership of the iterator and will delete it.
195 *
196 * @param it a Tulip iterator
197 *
198 * @return true if the iterator returns at least n values
199 **/
200template <typename T>
201inline bool iteratorCountCheck(Iterator<T> *it, unsigned int minNbElements) {
202 unsigned int count = 0;
203 while (it->hasNext()) {
204 ++count;
205 if (count == minNbElements) {
206 delete it;
207 return true;
208 }
209 it->next();
210 }
211 delete it;
212 return false;
213}
214
215/**
216 * @brief Checks if an iterator is empty
217 * @ingroup Iterators
218 *
219 * @since Tulip 5.2
220 *
221 * Checks if the iterator does not return any value.
222 * That function takes ownership of the iterator and will delete it.
223 *
224 * @param it a Tulip iterator
225 *
226 * @return true if the iterator is empty
227 **/
228template <typename T>
229inline bool iteratorEmpty(Iterator<T> *it) {
230 return !iteratorCountCheck(it, 1);
231}
232
233/**
234 * @brief Applies a function to each iterated element
235 * @ingroup Iterators
236 *
237 * @since Tulip 5.2
238 *
239 * Applies a function to each element iterated by the provided iterator.
240 * That function takes ownership of the iterator and will delete it.
241 *
242 * @param it a Tulip iterator
243 * @param mapFunction functor or lambda function taking one parameter of the same type of the
244 *iterated elements
245 *
246 *
247 **/
248template <typename T, class MapFunction>
249inline void iteratorMap(Iterator<T> *it, MapFunction &&mapFunction) {
250 if (sizeof(T) > sizeof(double)) {
251 for (const auto &v : it) {
252 mapFunction(v);
253 }
254 } else {
255 for (auto v : it) {
256 mapFunction(v);
257 }
258 }
259}
260
261/**
262 * @brief Reduces iterated elements to a single value
263 * @ingroup Iterators
264 *
265 * @since Tulip 5.2
266 *
267 * Produces a single value from the iterated elements (e.g. sum).
268 * That function takes ownership of the iterator and will delete it.
269 *
270 * @param it a Tulip iterator
271 * @param initVal initial value of the reduced result
272 * @param reduceFunction functor or lambda function taking two parameters : first one being the
273 *current reduced value,
274 * second one being the current iterated element and returning intermediate reduced value
275 *
276 * @return the reduced value from the iterated elements
277 *
278 **/
279template <typename T, typename reduceType, class ReduceFunction>
280inline reduceType iteratorReduce(Iterator<T> *it, const reduceType &initVal,
281 ReduceFunction reduceFunction) {
282 reduceType val = initVal;
283 if (sizeof(T) > sizeof(double)) {
284 for (const auto &v : it) {
285 val = reduceFunction(val, v);
286 }
287 } else {
288 for (auto v : it) {
289 val = reduceFunction(val, v);
290 }
291 }
292 return val;
293}
294
295/**
296 * @brief Converts an iterator to a std::list
297 * @ingroup Iterators
298 *
299 * @since Tulip 5.2
300 *
301 * Returns a std::list filled with the iterated elements.
302 * That function takes ownership of the iterator and will delete it.
303 *
304 * @param it a Tulip iterator
305 *
306 * @return a std::list filled with iterated elements
307 **/
308template <typename T>
309inline std::list<T> iteratorList(Iterator<T> *it) {
310 std::list<T> ret;
311 while (it->hasNext()) {
312 ret.emplace_back(std::move(it->next()));
313 }
314 delete it;
315 return ret;
316}
317
318/**
319 * @brief Converts an iterator to a std::vector
320 * @ingroup Iterators
321 *
322 * @since Tulip 5.2
323 *
324 * Returns a std::vector filled with the iterated elements.
325 * That function takes ownership of the iterator and will delete it.
326 *
327 * @param it a Tulip iterator
328 *
329 * @return a std::vector filled with iterated elements
330 **/
331template <typename T>
332inline std::vector<T> iteratorVector(Iterator<T> *it) {
333 std::vector<T> ret;
334 while (it->hasNext()) {
335 ret.emplace_back(std::move(it->next()));
336 }
337 delete it;
338 return ret;
339}
340
341/**
342 * @brief Converts an iterator to a std::set
343 * @ingroup Iterators
344 *
345 * @since Tulip 5.2
346 *
347 * Returns a std::set filled with the iterated elements.
348 * That function takes ownership of the iterator and will delete it.
349 *
350 * @param it a Tulip iterator
351 *
352 * @return a std::set filled with iterated elements
353 **/
354template <typename T>
355inline std::set<T> iteratorSet(Iterator<T> *it) {
356 std::set<T> ret;
357 while (it->hasNext()) {
358 ret.emplace(std::move(it->next()));
359 }
360 delete it;
361 return ret;
362}
363
364#ifndef DOXYGEN_NOTFOR_DEVEL
365template <typename TYPE>
366class UINTIterator : public Iterator<TYPE> {
367public:
368 UINTIterator(Iterator<unsigned int> *it) : it(it) {}
369 ~UINTIterator() override {
370 delete it;
371 }
372 bool hasNext() override {
373 return it->hasNext();
374 }
375 TYPE next() override {
376 return TYPE(it->next());
377 }
378
379private:
380 Iterator<unsigned int> *it;
381};
382
383#endif // DOXYGEN_NOTFOR_DEVEL
384} // namespace tlp
385
386#ifdef _MSC_VER
387
388#include <tulip/Edge.h>
389#include <tulip/Node.h>
390
391template struct TLP_SCOPE tlp::Iterator<tlp::edge>;
392template struct TLP_SCOPE tlp::Iterator<tlp::node>;
393#endif
394#endif
reduceType iteratorReduce(Iterator< T > *it, const reduceType &initVal, ReduceFunction reduceFunction)
Reduces iterated elements to a single value.
Definition: Iterator.h:280
bool iteratorEmpty(Iterator< T > *it)
Checks if an iterator is empty.
Definition: Iterator.h:229
std::set< T > iteratorSet(Iterator< T > *it)
Converts an iterator to a std::set.
Definition: Iterator.h:355
std::vector< T > iteratorVector(Iterator< T > *it)
Converts an iterator to a std::vector.
Definition: Iterator.h:332
std::list< T > iteratorList(Iterator< T > *it)
Converts an iterator to a std::list.
Definition: Iterator.h:309
void iteratorMap(Iterator< T > *it, MapFunction &&mapFunction)
Applies a function to each iterated element.
Definition: Iterator.h:249
unsigned int iteratorCount(Iterator< T > *it)
Counts the number of iterated elements.
Definition: Iterator.h:177
bool iteratorCountCheck(Iterator< T > *it, unsigned int minNbElements)
Checks a minimum amount of iterated elements.
Definition: Iterator.h:201
Interface for Tulip iterators. Allows basic iteration operations only.
Definition: Iterator.h:74
virtual bool hasNext()=0
Tells if the sequence is at its end.
virtual T next()=0
Moves the Iterator on the next element.