• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
check_iterator_range()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(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( 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 >
operator ()iterator_range_test_detail::less117         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 >
operator ()iterator_range_test_detail::greater126         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 >
operator ()iterator_range_test_detail::less_or_equal135         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 >
operator ()iterator_range_test_detail::greater_or_equal144         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 >
operator ()iterator_range_test_detail::equal_to153         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 >
operator ()iterator_range_test_detail::not_equal_to162         bool operator()(const Left& l, const Right& r) const
163         {
164             return l != r;
165         }
166     };
167 
168     template< class Pred >
check_iterator_range_operators_impl(Pred 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 
check_iterator_range_from_array()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 
check_make_iterator_range_n()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>
check_iterator_range_operator()246 inline void check_iterator_range_operator()
247 {
248     iterator_range_test_detail::check_iterator_range_operators_impl(
249         Pred());
250 }
251 
test_advance()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 {
ptr_iteratorptr_iterator272     ptr_iterator() {}
ptr_iteratorptr_iterator273     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 
test_sfinae()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 >
test_iter_range(Container & a_cont)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 
check_reference_type()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 
init_unit_test_suite(int argc,char * argv[])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