]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(__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( str ); | |
42 | r = boost::make_iterator_range( str.begin(), str.end() ); | |
43 | cirange r2 = boost::make_iterator_range( cstr ); | |
44 | r2 = boost::make_iterator_range( cstr.begin(), cstr.end() ); | |
45 | r2 = boost::make_iterator_range( str ); | |
46 | ||
47 | BOOST_CHECK( !r.empty() ); | |
48 | BOOST_CHECK( !r2.empty() ); | |
49 | ||
50 | //#if BOOST_WORKAROUND(__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 | ||
b32b8144 FG |
62 | BOOST_CHECK_EQUAL( r.size(), boost::size( r ) ); |
63 | BOOST_CHECK_EQUAL( r2.size(), boost::size( r2 ) ); | |
7c673cae FG |
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( std::wstring( L"a wide string" ) ) | |
72 | << boost::make_iterator_range( 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( str ); | |
79 | BOOST_CHECK( rr.equal( r ) ); | |
80 | ||
81 | rr = boost::make_iterator_range( str.begin(), 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( 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( str, 1, -1 ); | |
100 | BOOST_CHECK( rrr == boost::as_literal("ello worl") ); | |
101 | rrr = boost::make_iterator_range( rrr, -1, 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(arr, 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(std::string()); | |
173 | vals.push_back("a"); | |
174 | vals.push_back("b"); | |
175 | vals.push_back("z"); | |
176 | vals.push_back("ab"); | |
177 | vals.push_back("ba"); | |
178 | vals.push_back("abc"); | |
179 | vals.push_back("cba"); | |
180 | vals.push_back("aa"); | |
181 | vals.push_back("aaa"); | |
182 | vals.push_back("aab"); | |
183 | vals.push_back("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(leftValue); | |
199 | iter_range right = boost::make_iterator_range(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(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(i); | |
225 | ||
226 | boost::iterator_range<std::vector<uint32_t>::iterator> rng = | |
227 | boost::make_iterator_range_n(boost::begin(input), 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(boost::begin(cinput), 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(1); | |
256 | l.push_back(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( 999 ); | |
310 | test_iter_range<veci_type>(a_vec); | |
311 | test_iter_range<veci_type const>(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 |