1 | // Boost.Range library |
2 | // |
3 | // Copyright Thorsten Ottosen & Larry Evans 2003-2005. Use, modification and |
4 | // distribution is subject to the Boost Software License, Version |
5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | // |
8 | // For more information, see http://www.boost.org/libs/range/ |
9 | // |
10 | |
11 | //#include <boost/range/as_array.hpp> |
12 | |
13 | #include <boost/detail/workaround.hpp> |
14 | |
15 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
16 | # pragma warn -8091 // suppress warning in Boost.Test |
17 | # pragma warn -8057 // unused argument argc/argv in Boost.Test |
18 | #endif |
19 | |
20 | #include <boost/range/iterator_range.hpp> |
21 | #include <boost/range/functions.hpp> |
22 | #include <boost/range/as_literal.hpp> |
23 | #include <boost/cstdint.hpp> |
24 | #include <boost/test/test_tools.hpp> |
25 | #include <boost/test/unit_test.hpp> |
26 | #include <iostream> |
27 | #include <string> |
28 | #include <vector> |
29 | |
30 | void check_reference_type(); |
31 | |
32 | void check_iterator_range() |
33 | { |
34 | |
35 | typedef std::string::iterator iterator; |
36 | typedef std::string::const_iterator const_iterator; |
37 | typedef boost::iterator_range<iterator> irange; |
38 | typedef boost::iterator_range<const_iterator> cirange; |
39 | std::string str = "hello world" ; |
40 | const std::string cstr = "const world" ; |
41 | irange r = boost::make_iterator_range( r&: str ); |
42 | r = boost::make_iterator_range( Begin: str.begin(), End: str.end() ); |
43 | cirange r2 = boost::make_iterator_range( r: cstr ); |
44 | r2 = boost::make_iterator_range( Begin: cstr.begin(), End: cstr.end() ); |
45 | r2 = boost::make_iterator_range( r&: str ); |
46 | |
47 | BOOST_CHECK( !r.empty() ); |
48 | BOOST_CHECK( !r2.empty() ); |
49 | |
50 | //#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
51 | // if( !(bool)r ) |
52 | // BOOST_CHECK( false ); |
53 | // if( !(bool)r2 ) |
54 | // BOOST_CHECK( false ); |
55 | //#else |
56 | if( !r ) |
57 | BOOST_CHECK( false ); |
58 | if( !r2 ) |
59 | BOOST_CHECK( false ); |
60 | //#endif |
61 | |
62 | BOOST_CHECK_EQUAL( r.size(), boost::size( r ) ); |
63 | BOOST_CHECK_EQUAL( r2.size(), boost::size( r2 ) ); |
64 | |
65 | BOOST_CHECK_EQUAL( std::distance( r.begin(), r.end() ), |
66 | std::distance( boost::begin( r2 ), boost::end( r2 ) ) ); |
67 | std::cout << r << r2; |
68 | |
69 | |
70 | #ifndef BOOST_NO_STD_WSTRING |
71 | std::wcout << boost::make_iterator_range( r: std::wstring( L"a wide string" ) ) |
72 | << boost::make_iterator_range( r: L"another wide string" ); |
73 | #endif |
74 | |
75 | std::string res = boost::copy_range<std::string>( r ); |
76 | BOOST_CHECK_EQUAL_COLLECTIONS( res.begin(), res.end(), r.begin(), r.end() ); |
77 | |
78 | irange rr = boost::make_iterator_range( r&: str ); |
79 | BOOST_CHECK( rr.equal( r ) ); |
80 | |
81 | rr = boost::make_iterator_range( Begin: str.begin(), End: str.begin() + 5 ); |
82 | BOOST_CHECK( rr == boost::as_literal("hello" ) ); |
83 | BOOST_CHECK( rr != boost::as_literal("hell" ) ); |
84 | BOOST_CHECK( rr < boost::as_literal("hello dude" ) ); |
85 | BOOST_CHECK( boost::as_literal("hello" ) == rr ); |
86 | BOOST_CHECK( boost::as_literal("hell" ) != rr ); |
87 | BOOST_CHECK( ! (boost::as_literal("hello dude" ) < rr ) ); |
88 | irange rrr = rr; |
89 | BOOST_CHECK( rrr == rr ); |
90 | BOOST_CHECK( !( rrr != rr ) ); |
91 | BOOST_CHECK( !( rrr < rr ) ); |
92 | |
93 | const irange cr = boost::make_iterator_range( r&: str ); |
94 | BOOST_CHECK_EQUAL( cr.front(), 'h' ); |
95 | BOOST_CHECK_EQUAL( cr.back(), 'd' ); |
96 | BOOST_CHECK_EQUAL( cr[1], 'e' ); |
97 | BOOST_CHECK_EQUAL( cr(1), 'e' ); |
98 | |
99 | rrr = boost::make_iterator_range( r&: str, advance_begin: 1, advance_end: -1 ); |
100 | BOOST_CHECK( rrr == boost::as_literal("ello worl" ) ); |
101 | rrr = boost::make_iterator_range( r&: rrr, advance_begin: -1, advance_end: 1 ); |
102 | BOOST_CHECK( rrr == str ); |
103 | |
104 | check_reference_type(); |
105 | |
106 | // Check that an iterator range can be instantiated with |
107 | // a pointer to an array as an iterator. |
108 | int arr[2][2]; |
109 | boost::make_iterator_range(Begin: arr, End: arr + 2); |
110 | } |
111 | |
112 | namespace iterator_range_test_detail |
113 | { |
114 | struct less |
115 | { |
116 | template< class Left, class Right > |
117 | bool operator()(const Left& l, const Right& r) const |
118 | { |
119 | return l < r; |
120 | } |
121 | }; |
122 | |
123 | struct greater |
124 | { |
125 | template< class Left, class Right > |
126 | bool operator()(const Left& l, const Right& r) const |
127 | { |
128 | return l > r; |
129 | } |
130 | }; |
131 | |
132 | struct less_or_equal |
133 | { |
134 | template< class Left, class Right > |
135 | bool operator()(const Left& l, const Right& r) const |
136 | { |
137 | return l <= r; |
138 | } |
139 | }; |
140 | |
141 | struct greater_or_equal |
142 | { |
143 | template< class Left, class Right > |
144 | bool operator()(const Left& l, const Right& r) const |
145 | { |
146 | return l >= r; |
147 | } |
148 | }; |
149 | |
150 | struct equal_to |
151 | { |
152 | template< class Left, class Right > |
153 | bool operator()(const Left& l, const Right& r) const |
154 | { |
155 | return l == r; |
156 | } |
157 | }; |
158 | |
159 | struct not_equal_to |
160 | { |
161 | template< class Left, class Right > |
162 | bool operator()(const Left& l, const Right& r) const |
163 | { |
164 | return l != r; |
165 | } |
166 | }; |
167 | |
168 | template< class Pred > |
169 | void check_iterator_range_operators_impl(Pred pred) |
170 | { |
171 | std::vector<std::string> vals; |
172 | vals.push_back(x: std::string()); |
173 | vals.push_back(x: "a" ); |
174 | vals.push_back(x: "b" ); |
175 | vals.push_back(x: "z" ); |
176 | vals.push_back(x: "ab" ); |
177 | vals.push_back(x: "ba" ); |
178 | vals.push_back(x: "abc" ); |
179 | vals.push_back(x: "cba" ); |
180 | vals.push_back(x: "aa" ); |
181 | vals.push_back(x: "aaa" ); |
182 | vals.push_back(x: "aab" ); |
183 | vals.push_back(x: "bba" ); |
184 | |
185 | typedef std::string::const_iterator citer; |
186 | typedef boost::iterator_range<citer> iter_range; |
187 | |
188 | typedef std::vector<std::string>::const_iterator value_const_iterator; |
189 | value_const_iterator first_val = vals.begin(); |
190 | value_const_iterator last_val = vals.end(); |
191 | |
192 | for (value_const_iterator left_it = first_val; left_it != last_val; ++left_it) |
193 | { |
194 | const std::string& leftValue = *left_it; |
195 | for (value_const_iterator right_it = first_val; right_it != last_val; ++right_it) |
196 | { |
197 | const std::string& rightValue = *right_it; |
198 | iter_range left = boost::make_iterator_range(r: leftValue); |
199 | iter_range right = boost::make_iterator_range(r: rightValue); |
200 | |
201 | const bool reference = pred(leftValue, rightValue); |
202 | |
203 | BOOST_CHECK_EQUAL( pred(left, right), reference ); |
204 | BOOST_CHECK_EQUAL( pred(left, rightValue), reference ); |
205 | BOOST_CHECK_EQUAL( pred(leftValue, right), reference ); |
206 | } |
207 | } |
208 | } |
209 | |
210 | void check_iterator_range_from_array() |
211 | { |
212 | double source[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 }; |
213 | boost::iterator_range<double*> rng = boost::make_iterator_range(r&: source); |
214 | BOOST_CHECK_EQUAL_COLLECTIONS( rng.begin(), rng.end(), |
215 | source, source + 6 ); |
216 | } |
217 | |
218 | void check_make_iterator_range_n() |
219 | { |
220 | using boost::uint32_t; |
221 | |
222 | std::vector<uint32_t> input; |
223 | for (uint32_t i = 0; i < 10u; ++i) |
224 | input.push_back(x: i); |
225 | |
226 | boost::iterator_range<std::vector<uint32_t>::iterator> rng = |
227 | boost::make_iterator_range_n(first: boost::begin(r&: input), n: 8u); |
228 | |
229 | BOOST_CHECK(rng.begin() == input.begin()); |
230 | BOOST_CHECK(rng.end() == input.begin() + 8); |
231 | BOOST_CHECK_EQUAL(rng.size(), 8u); |
232 | |
233 | const std::vector<uint32_t>& cinput = input; |
234 | |
235 | boost::iterator_range<std::vector<uint32_t>::const_iterator> crng = |
236 | boost::make_iterator_range_n(first: boost::begin(r: cinput), n: 8u); |
237 | |
238 | BOOST_CHECK(crng.begin() == cinput.begin()); |
239 | BOOST_CHECK(crng.end() == cinput.begin() + 8); |
240 | BOOST_CHECK_EQUAL(crng.size(), 8u); |
241 | } |
242 | |
243 | } // namespace iterator_range_test_detail |
244 | |
245 | template<typename Pred> |
246 | inline void check_iterator_range_operator() |
247 | { |
248 | iterator_range_test_detail::check_iterator_range_operators_impl( |
249 | Pred()); |
250 | } |
251 | |
252 | inline void test_advance() |
253 | { |
254 | std::vector<int> l; |
255 | l.push_back(x: 1); |
256 | l.push_back(x: 2); |
257 | typedef boost::iterator_range<std::vector<int>::iterator> rng_t; |
258 | |
259 | rng_t r1(l.begin(), l.end()); |
260 | BOOST_CHECK(r1.advance_begin(1).advance_end(-1).empty()); |
261 | |
262 | rng_t r2(l.begin(), l.end()); |
263 | BOOST_CHECK_EQUAL(r2.advance_begin(1).size(), 1u); |
264 | |
265 | rng_t r3(l.begin(), l.end()); |
266 | BOOST_CHECK_EQUAL(r3.advance_end(-1).size(), 1u); |
267 | } |
268 | |
269 | struct ptr_iterator |
270 | : boost::iterator_adaptor<ptr_iterator, int *> |
271 | { |
272 | ptr_iterator() {} |
273 | ptr_iterator(int *p) : boost::iterator_adaptor<ptr_iterator, int *>(p) {} |
274 | private: |
275 | typedef void iterator; // To throw off the SFINAE mechanism in iterator_range |
276 | }; |
277 | |
278 | void test_sfinae() |
279 | { |
280 | boost::iterator_range<ptr_iterator> r(ptr_iterator(0), ptr_iterator(0)); |
281 | } |
282 | |
283 | // |
284 | // |
285 | // Check that constness is propagated correct from |
286 | // the iterator types. |
287 | // |
288 | // Test contributed by Larry Evans. |
289 | // |
290 | |
291 | template< class Container > |
292 | int test_iter_range( Container& a_cont ) |
293 | { |
294 | typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type citer_type; |
295 | typedef boost::iterator_range<citer_type> riter_type; |
296 | riter_type a_riter( boost::make_iterator_range( a_cont ) ); |
297 | a_riter.front(); |
298 | a_riter.back(); |
299 | int i = a_riter[0]; |
300 | return i; |
301 | } |
302 | |
303 | |
304 | |
305 | void check_reference_type() |
306 | { |
307 | typedef std::vector<int> veci_type; |
308 | veci_type a_vec; |
309 | a_vec.push_back( x: 999 ); |
310 | test_iter_range<veci_type>(a_cont&: a_vec); |
311 | test_iter_range<veci_type const>(a_cont: a_vec); |
312 | } |
313 | |
314 | boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) |
315 | { |
316 | boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); |
317 | |
318 | test->add(BOOST_TEST_CASE(&check_iterator_range)); |
319 | test->add(BOOST_TEST_CASE(&check_iterator_range_operator<iterator_range_test_detail::less>)); |
320 | test->add(BOOST_TEST_CASE(&check_iterator_range_operator<iterator_range_test_detail::less_or_equal>)); |
321 | test->add(BOOST_TEST_CASE(&check_iterator_range_operator<iterator_range_test_detail::greater>)); |
322 | test->add(BOOST_TEST_CASE(&check_iterator_range_operator<iterator_range_test_detail::greater_or_equal>)); |
323 | test->add(BOOST_TEST_CASE(&check_iterator_range_operator<iterator_range_test_detail::equal_to>)); |
324 | test->add(BOOST_TEST_CASE(&check_iterator_range_operator<iterator_range_test_detail::not_equal_to>)); |
325 | test->add(BOOST_TEST_CASE(&iterator_range_test_detail::check_make_iterator_range_n)); |
326 | test->add(BOOST_TEST_CASE(&test_advance)); |
327 | |
328 | return test; |
329 | } |
330 | |
331 | |