1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2014, Oracle and/or its affiliates.
5
6 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
10
11 #ifndef BOOST_TEST_MODULE
12 #define BOOST_TEST_MODULE test_flatten_iterator
13 #endif
14
15 #include <boost/test/included/unit_test.hpp>
16
17 #include <cstddef>
18 #include <iostream>
19 #include <string>
20 #include <sstream>
21 #include <algorithm>
22 #include <iterator>
23
24 #include <vector>
25 #include <list>
26
27 #include <boost/core/ignore_unused.hpp>
28 #include <boost/mpl/if.hpp>
29 #include <boost/type_traits/is_const.hpp>
30 #include <boost/assign/std/vector.hpp>
31 #include <boost/assign/std/list.hpp>
32 #include <boost/assign/std/set.hpp>
33
34 #include "test_iterator_common.hpp"
35
36 #include <boost/geometry/iterators/flatten_iterator.hpp>
37
38 using namespace boost::assign;
39
40
41 template <typename InnerContainer>
42 struct access_begin
43 {
44 typedef typename boost::mpl::if_
45 <
46 typename boost::is_const<InnerContainer>::type,
47 typename InnerContainer::const_iterator,
48 typename InnerContainer::iterator
49 >::type return_type;
50
applyaccess_begin51 static inline return_type apply(InnerContainer& inner)
52 {
53 return inner.begin();
54 }
55 };
56
57
58 template <typename InnerContainer>
59 struct access_end
60 {
61 typedef typename boost::mpl::if_
62 <
63 typename boost::is_const<InnerContainer>::type,
64 typename InnerContainer::const_iterator,
65 typename InnerContainer::iterator
66 >::type return_type;
67
applyaccess_end68 static inline return_type apply(InnerContainer& inner)
69 {
70 return inner.end();
71 }
72 };
73
74
75 template <typename NestedContainer>
number_of_elements(NestedContainer const & c)76 inline std::size_t number_of_elements(NestedContainer const& c)
77 {
78 std::size_t num_elements(0);
79 for (typename NestedContainer::const_iterator outer = c.begin();
80 outer != c.end(); ++outer)
81 {
82 num_elements += outer->size();
83 }
84 return num_elements;
85 }
86
87
88 struct test_flatten_iterator
89 {
90 template
91 <
92 typename FlattenIterator,
93 typename ConstFlattenIterator,
94 typename NestedContainer
95 >
96 static inline
test_using_max_elementtest_flatten_iterator97 void test_using_max_element(FlattenIterator first,
98 FlattenIterator beyond,
99 ConstFlattenIterator const_first,
100 ConstFlattenIterator const_beyond,
101 NestedContainer const& c)
102 {
103 typedef typename std::iterator_traits
104 <
105 FlattenIterator
106 >::value_type value_type;
107
108 typedef typename NestedContainer::const_iterator const_outer_iterator;
109 typedef typename NestedContainer::value_type inner_container;
110 typedef typename inner_container::const_iterator const_inner_iterator;
111
112 if ( first == beyond )
113 {
114 return;
115 }
116
117 FlattenIterator it_max = std::max_element(first, beyond);
118 ConstFlattenIterator const_it_max =
119 std::max_element(const_first, const_beyond);
120
121 BOOST_CHECK( it_max == const_it_max );
122 BOOST_CHECK( *it_max == *const_it_max );
123
124 value_type old_value = *const_first;
125 value_type new_value = *it_max + 1;
126
127 *first = *it_max + 1;
128 const_outer_iterator outer = c.begin();
129 while ( outer->begin() == outer->end() )
130 {
131 ++outer;
132 }
133 const_inner_iterator inner = outer->begin();
134
135 BOOST_CHECK( *inner == new_value );
136
137 #ifdef BOOST_GEOMETRY_TEST_DEBUG
138 std::cout << std::endl;
139 std::cout << "modified 1st element of 1st non-empty "
140 << "inner container:" << std::endl;
141 print_nested_container(std::cout, c.begin(), c.end(), "nested :")
142 << std::endl;
143 print_container(std::cout, first, beyond, "flattened:") << std::endl;
144 #endif
145
146 *first = old_value;
147 BOOST_CHECK( *inner == old_value );
148 }
149
150 template <typename NestedContainer>
applytest_flatten_iterator151 static inline void apply(NestedContainer& c,
152 std::string const& case_id,
153 std::string const& container_id)
154 {
155 boost::ignore_unused(case_id, container_id);
156
157 #ifdef BOOST_GEOMETRY_TEST_DEBUG
158 std::stringstream sstream;
159 sstream << case_id << " [" << container_id << "]";
160
161 std::cout << "case id: " << sstream.str() << std::endl;
162 #endif
163 typedef typename NestedContainer::const_iterator const_outer_iterator;
164 typedef typename NestedContainer::iterator outer_iterator;
165 typedef typename NestedContainer::value_type inner_container;
166
167 typedef typename inner_container::const_iterator const_inner_iterator;
168 typedef typename inner_container::iterator inner_iterator;
169
170 typedef boost::geometry::flatten_iterator
171 <
172 const_outer_iterator,
173 const_inner_iterator,
174 typename inner_container::value_type const,
175 access_begin<inner_container const>,
176 access_end<inner_container const>
177 > const_flatten_iterator;
178
179 typedef boost::geometry::flatten_iterator
180 <
181 outer_iterator,
182 inner_iterator,
183 typename inner_container::value_type,
184 access_begin<inner_container>,
185 access_end<inner_container>
186 > flatten_iterator;
187
188 typedef typename std::iterator_traits
189 <
190 flatten_iterator
191 >::value_type value_type;
192
193 flatten_iterator begin(c.begin(), c.end());
194 flatten_iterator end(c.end());
195 const_flatten_iterator const_begin(begin);
196 const_flatten_iterator const_end(end);
197 const_begin = begin;
198 const_end = end;
199
200 // test copying, dereferencing and element equality
201 std::vector<value_type> combined;
202 for (const_outer_iterator outer = c.begin();
203 outer != c.end(); ++outer)
204 {
205 std::copy(outer->begin(), outer->end(),
206 std::back_inserter(combined));
207 }
208 test_equality(begin, end, combined);
209 test_equality(const_begin, const_end, combined);
210
211 combined.clear();
212 std::copy(begin, end, std::back_inserter(combined));
213 test_equality(begin, end, combined);
214 test_equality(const_begin, const_end, combined);
215
216 combined.clear();
217 std::copy(const_begin, const_end, std::back_inserter(combined));
218 test_equality(begin, end, combined);
219 test_equality(const_begin, const_end, combined);
220
221 // test sizes (and std::distance)
222 test_size(begin, end, combined);
223 test_size(const_begin, const_end, combined);
224
225 #ifdef BOOST_GEOMETRY_TEST_DEBUG
226 print_nested_container(std::cout, c.begin(), c.end(), "nested :")
227 << std::endl;
228 print_container(std::cout, begin, end, "flattened :")
229 << std::endl;
230
231 if ( begin != end )
232 {
233 std::cout << "min element: "
234 << *std::min_element(begin, end)
235 << std::endl;
236 std::cout << "max element: "
237 << *std::max_element(const_begin, const_end)
238 << std::endl;
239 }
240 #endif
241
242 // perform reversals (std::reverse)
243 test_using_reverse(begin, end, combined);
244
245 // test std::max_element, dereferencing and value assigment
246 test_using_max_element(begin, end, const_begin, const_end, c);
247
248 // test std::count_if / std::remove_if
249 test_using_remove_if(begin, end, combined);
250 #ifdef BOOST_GEOMETRY_TEST_DEBUG
251 std::cout << "====================" << std::endl << std::endl;
252 #endif
253 }
254 };
255
256
257
258 // the actual test cases -- START
259 template <int CaseNumber>
260 struct test_case_per_container;
261
262 template<>
263 struct test_case_per_container<0>
264 {
265 template <typename NestedContainer>
applytest_case_per_container266 static inline void apply(std::string const& case_id,
267 std::string const& container_id)
268 {
269 NestedContainer c;
270 test_flatten_iterator::apply(c, case_id, container_id);
271 }
272 };
273
274 template<>
275 struct test_case_per_container<1>
276 {
277 template <typename NestedContainer>
applytest_case_per_container278 static inline void apply(std::string const& case_id,
279 std::string const& container_id)
280 {
281 NestedContainer c;
282 for (int i = 0; i < 5; ++i)
283 {
284 c += typename NestedContainer::value_type();
285 }
286 test_flatten_iterator::apply(c, case_id, container_id);
287 }
288 };
289
290 template<>
291 struct test_case_per_container<2>
292 {
293 template <typename NestedContainer>
applytest_case_per_container294 static inline void apply(std::string const& case_id,
295 std::string const& container_id)
296 {
297 NestedContainer c;
298 typename NestedContainer::value_type ic[4];
299
300 ic[0] += 5,4,3,2,1;
301 ic[1] += 6,7,8;
302 ic[2] += 9;
303 ic[3] += 9,8,7,6,5;
304 c += ic[0],ic[1],ic[2],ic[3];
305
306 test_flatten_iterator::apply(c, case_id, container_id);
307 }
308 };
309
310 template<>
311 struct test_case_per_container<3>
312 {
313 template <typename NestedContainer>
applytest_case_per_container314 static inline void apply(std::string const& case_id,
315 std::string const& container_id)
316 {
317 NestedContainer c;
318 typename NestedContainer::value_type ic[20];
319
320 ic[2] += 5,4,3,2,1;
321 ic[3] += 6,7,8;
322 ic[8] += 9;
323 ic[9] += 9,8,7,6,5;
324 ic[14] += 4,3,2,1;
325 for (std::size_t i = 0; i < 20; ++i)
326 {
327 c += ic[i];
328 }
329
330 test_flatten_iterator::apply(c, case_id, container_id);
331 }
332 };
333 // the actual test cases -- END
334
335
336
337 template <int CaseNumber>
test_case_all_containers(std::string const & case_id)338 inline void test_case_all_containers(std::string const& case_id)
339 {
340 typedef typename std::vector<std::vector<int> > VV;
341 typedef typename std::vector<std::list<int> > VL;
342 typedef typename std::list<std::vector<int> > LV;
343 typedef typename std::list<std::list<int> > LL;
344
345 #ifdef BOOST_GEOMETRY_TEST_DEBUG
346 std::cout << std::endl << std::endl;
347 #endif
348 test_case_per_container<CaseNumber>::template apply<VV>(case_id, "VV");
349 test_case_per_container<CaseNumber>::template apply<VL>(case_id, "VL");
350 test_case_per_container<CaseNumber>::template apply<LV>(case_id, "LV");
351 test_case_per_container<CaseNumber>::template apply<LL>(case_id, "LL");
352
353 #ifdef BOOST_GEOMETRY_TEST_DEBUG
354 std::cout << std::endl;
355 std::cout << "********************************************************"
356 << std::endl << std::endl;
357 #endif
358 }
359
360
361
BOOST_AUTO_TEST_CASE(test_flatten_iterator_all)362 BOOST_AUTO_TEST_CASE( test_flatten_iterator_all )
363 {
364 test_case_all_containers<0>("empty");
365 test_case_all_containers<1>("case1");
366 test_case_all_containers<2>("case2");
367 test_case_all_containers<3>("case3");
368 }
369