1 //  Copyright Neil Groves 2009. Use, modification and
2 //  distribution is subject to the Boost Software License, Version
3 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
4 //  http://www.boost.org/LICENSE_1_0.txt)
5 //
6 //
7 // For more information, see http://www.boost.org/libs/range/
8 //
9 #ifndef BOOST_RANGE_DETAIL_RANGE_RETURN_HPP_INCLUDED
10 #define BOOST_RANGE_DETAIL_RANGE_RETURN_HPP_INCLUDED
11 
12 #include <boost/range/begin.hpp>
13 #include <boost/range/end.hpp>
14 #include <boost/range/iterator_range.hpp>
15 #include <boost/next_prior.hpp>
16 
17 namespace boost
18 {
19     enum range_return_value
20     {
21         // (*) indicates the most common values
22         return_found,       // only the found resulting iterator (*)
23         return_next,        // next(found) iterator
24         return_prior,       // prior(found) iterator
25         return_begin_found, // [begin, found) range (*)
26         return_begin_next,  // [begin, next(found)) range
27         return_begin_prior, // [begin, prior(found)) range
28         return_found_end,   // [found, end) range (*)
29         return_next_end,    // [next(found), end) range
30         return_prior_end,   // [prior(found), end) range
31         return_begin_end    // [begin, end) range
32     };
33 
34     template< class SinglePassRange, range_return_value >
35     struct range_return
36     {
37         typedef boost::iterator_range<
38             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
39 
packboost::range_return40         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
41                          SinglePassRange& rng)
42         {
43             return type(found, boost::end(rng));
44         }
45     };
46 
47     template< class SinglePassRange >
48     struct range_return< SinglePassRange, return_found >
49     {
50         typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type type;
51 
packboost::range_return52         static type pack(type found, SinglePassRange&)
53         {
54             return found;
55         }
56     };
57 
58     template< class SinglePassRange >
59     struct range_return< SinglePassRange, return_next >
60     {
61         typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type type;
62 
packboost::range_return63         static type pack(type found, SinglePassRange& rng)
64         {
65             return found == boost::end(rng)
66                 ? found
67                 : boost::next(found);
68         }
69     };
70 
71     template< class BidirectionalRange >
72     struct range_return< BidirectionalRange, return_prior >
73     {
74         typedef BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type type;
75 
packboost::range_return76         static type pack(type found, BidirectionalRange& rng)
77         {
78             return found == boost::begin(rng)
79                 ? found
80                 : boost::prior(found);
81         }
82     };
83 
84     template< class SinglePassRange >
85     struct range_return< SinglePassRange, return_begin_found >
86     {
87         typedef boost::iterator_range<
88             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
89 
packboost::range_return90         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
91                          SinglePassRange& rng)
92         {
93             return type(boost::begin(rng), found);
94         }
95     };
96 
97     template< class SinglePassRange >
98     struct range_return< SinglePassRange, return_begin_next >
99     {
100         typedef boost::iterator_range<
101             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
102 
packboost::range_return103         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
104                          SinglePassRange& rng)
105         {
106             return type( boost::begin(rng),
107                          found == boost::end(rng) ? found : boost::next(found) );
108         }
109     };
110 
111     template< class BidirectionalRange >
112     struct range_return< BidirectionalRange, return_begin_prior >
113     {
114         typedef boost::iterator_range<
115             BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type > type;
116 
packboost::range_return117         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type found,
118                          BidirectionalRange& rng)
119         {
120             return type( boost::begin(rng),
121                          found == boost::begin(rng) ? found : boost::prior(found) );
122         }
123     };
124 
125     template< class SinglePassRange >
126     struct range_return< SinglePassRange, return_found_end >
127     {
128         typedef boost::iterator_range<
129             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
130 
packboost::range_return131         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
132                          SinglePassRange& rng)
133         {
134             return type(found, boost::end(rng));
135         }
136     };
137 
138     template< class SinglePassRange >
139     struct range_return< SinglePassRange, return_next_end >
140     {
141         typedef boost::iterator_range<
142             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
143 
packboost::range_return144         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
145                          SinglePassRange& rng)
146         {
147             return type( found == boost::end(rng) ? found : boost::next(found),
148                          boost::end(rng) );
149         }
150     };
151 
152     template< class BidirectionalRange >
153     struct range_return< BidirectionalRange, return_prior_end >
154     {
155         typedef boost::iterator_range<
156             BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type > type;
157 
packboost::range_return158         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type found,
159                          BidirectionalRange& rng)
160         {
161             return type( found == boost::begin(rng) ? found : boost::prior(found),
162                          boost::end(rng) );
163         }
164     };
165 
166     template< class SinglePassRange >
167     struct range_return< SinglePassRange, return_begin_end >
168     {
169         typedef boost::iterator_range<
170             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
171 
packboost::range_return172         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type,
173                          SinglePassRange& rng)
174         {
175             return type(boost::begin(rng), boost::end(rng));
176         }
177     };
178 
179 }
180 
181 #endif // include guard
182