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 GEOMETRY_TEST_ITERATORS_TEST_ITERATOR_COMMON_HPP
12 #define GEOMETRY_TEST_ITERATORS_TEST_ITERATOR_COMMON_HPP
13 
14 #include <cstddef>
15 #include <iostream>
16 #include <iterator>
17 #include <string>
18 #include <algorithm>
19 
20 #include <boost/test/included/unit_test.hpp>
21 
22 // helper functions for testing the concatenate and flatten iterators
23 
24 template <typename Iterator>
print_container(std::ostream & os,Iterator begin,Iterator end,std::string const & header)25 inline std::ostream& print_container(std::ostream& os,
26                                      Iterator begin, Iterator end,
27                                      std::string const& header)
28 {
29     std::cout << header;
30     for (Iterator it = begin; it != end; ++it)
31     {
32         os << " " << *it;
33     }
34     return os;
35 }
36 
37 
38 template <typename Iterator>
print_nested_container(std::ostream & os,Iterator begin,Iterator end,std::string const & header)39 inline std::ostream& print_nested_container(std::ostream& os,
40                                             Iterator begin, Iterator end,
41                                             std::string const& header)
42 {
43     typedef typename std::iterator_traits<Iterator>::value_type inner_container;
44     typedef typename inner_container::const_iterator inner_iterator;
45 
46     std::cout << header;
47     for (Iterator outer = begin; outer != end; ++outer)
48     {
49         os << " (";
50         for (inner_iterator inner = outer->begin();
51              inner != outer->end(); ++inner)
52         {
53             if ( inner != outer->begin() )
54             {
55                 os << " ";
56             }
57             os << *inner;
58         }
59         os << ") ";
60     }
61     return os;
62 }
63 
64 
65 template <typename T>
66 struct is_odd
67 {
operator ()is_odd68     inline bool operator()(T const& t) const
69     {
70         return t % 2 != 0;
71     }
72 };
73 
74 
75 template <typename T>
76 struct is_even
77 {
operator ()is_even78     inline bool operator()(T const& t) const
79     {
80         return !is_odd<T>()(t);
81     }
82 };
83 
84 
85 
86 
87 template <typename CombinedIterator, typename CombinedContainer>
test_size(CombinedIterator first,CombinedIterator beyond,CombinedContainer const & combined)88 inline void test_size(CombinedIterator first, CombinedIterator beyond,
89                       CombinedContainer const& combined)
90 {
91     std::size_t size = static_cast<std::size_t>(std::distance(first, beyond));
92     BOOST_CHECK( combined.size() == size );
93 
94     size = 0;
95     for (CombinedIterator it = first; it != beyond; ++it)
96     {
97         ++size;
98     }
99     BOOST_CHECK( combined.size() == size );
100 
101     size = 0;
102     for (CombinedIterator it = beyond; it != first; --it)
103     {
104         ++size;
105     }
106     BOOST_CHECK( combined.size() == size );
107 }
108 
109 
110 
111 template <typename CombinedIterator, typename CombinedContainer>
test_equality(CombinedIterator first,CombinedIterator beyond,CombinedContainer const & combined)112 inline void test_equality(CombinedIterator first, CombinedIterator beyond,
113                           CombinedContainer const& combined)
114 {
115     typedef typename CombinedContainer::const_iterator iterator;
116 
117     iterator it = combined.begin();
118     for (CombinedIterator cit = first; cit != beyond; ++cit, ++it)
119     {
120         BOOST_CHECK( *cit == *it );
121     }
122 
123     if ( combined.begin() != combined.end() )
124     {
125         BOOST_CHECK( first != beyond );
126         iterator it = combined.end();
127         CombinedIterator cit = beyond;
128         for (--cit, --it; cit != first; --cit, --it)
129         {
130             BOOST_CHECK( *cit == *it );
131         }
132         BOOST_CHECK( cit == first && it == combined.begin() );
133         BOOST_CHECK( *cit == *it );
134     }
135     else
136     {
137         BOOST_CHECK( first == beyond );
138     }
139 }
140 
141 
142 
143 template <typename CombinedIterator, typename CombinedContainer>
test_using_remove_if(CombinedIterator first,CombinedIterator beyond,CombinedContainer & combined)144 inline void test_using_remove_if(CombinedIterator first,
145                                  CombinedIterator beyond,
146                                  CombinedContainer& combined)
147 {
148     typedef typename std::iterator_traits
149         <
150             CombinedIterator
151         >::value_type value_type;
152 
153 #ifdef BOOST_GEOMETRY_TEST_DEBUG
154     std::cout << std::endl;
155     std::cout << "odd elements removed:" << std::endl;
156     print_container(std::cout, first, beyond, "before:") << std::endl;
157 #endif
158     typename std::iterator_traits<CombinedIterator>::difference_type
159         num_even = std::count_if(first, beyond, is_even<value_type>());
160 
161     CombinedIterator new_beyond =
162         std::remove_if(first, beyond, is_odd<value_type>());
163 
164     std::size_t new_size = std::distance(first, new_beyond);
165 
166     for (CombinedIterator it = first; it != new_beyond; ++it)
167     {
168         BOOST_CHECK( !is_odd<value_type>()(*it) );
169     }
170     BOOST_CHECK( new_size == static_cast<std::size_t>(num_even) );
171 
172 #ifdef BOOST_GEOMETRY_TEST_DEBUG
173     print_container(std::cout, first, new_beyond, "after :") << std::endl;
174 #endif
175 
176     combined.erase(std::remove_if(combined.begin(), combined.end(),
177                                   is_odd<value_type>()),
178                    combined.end());
179     test_equality(first, new_beyond, combined);
180 }
181 
182 
183 template <typename CombinedIterator, typename CombinedContainer>
test_using_reverse(CombinedIterator first,CombinedIterator beyond,CombinedContainer & combined)184 inline void test_using_reverse(CombinedIterator first,
185                                CombinedIterator beyond,
186                                CombinedContainer& combined)
187 {
188     std::reverse(first, beyond);
189     std::reverse(combined.begin(), combined.end());
190     test_equality(first, beyond, combined);
191 
192 #ifdef BOOST_GEOMETRY_TEST_DEBUG
193     print_container(std::cout, first, beyond, "reversed:") << std::endl;
194 #endif
195 
196     std::reverse(first, beyond);
197     std::reverse(combined.begin(), combined.end());
198     test_equality(first, beyond, combined);
199 
200 #ifdef BOOST_GEOMETRY_TEST_DEBUG
201     print_container(std::cout, first, beyond, "re-reversed:") << std::endl;
202 #endif
203 }
204 
205 
206 #endif // GEOMETRY_TEST_ITERATORS_TEST_ITERATOR_COMMON_HPP
207