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 
16 namespace boost
17 {
18     enum range_return_value
19     {
20         // (*) indicates the most common values
21         return_found,       // only the found resulting iterator (*)
22         return_next,        // next(found) iterator
23         return_prior,       // prior(found) iterator
24         return_begin_found, // [begin, found) range (*)
25         return_begin_next,  // [begin, next(found)) range
26         return_begin_prior, // [begin, prior(found)) range
27         return_found_end,   // [found, end) range (*)
28         return_next_end,    // [next(found), end) range
29         return_prior_end,   // [prior(found), end) range
30         return_begin_end    // [begin, end) range
31     };
32 
33     template< class SinglePassRange, range_return_value >
34     struct range_return
35     {
36         typedef boost::iterator_range<
37             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
38 
packboost::range_return39         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
40                          SinglePassRange& rng)
41         {
42             return type(found, boost::end(rng));
43         }
44     };
45 
46     template< class SinglePassRange >
47     struct range_return< SinglePassRange, return_found >
48     {
49         typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type type;
50 
packboost::range_return51         static type pack(type found, SinglePassRange&)
52         {
53             return found;
54         }
55     };
56 
57     template< class SinglePassRange >
58     struct range_return< SinglePassRange, return_next >
59     {
60         typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type type;
61 
packboost::range_return62         static type pack(type found, SinglePassRange& rng)
63         {
64             return found == boost::end(rng)
65                 ? found
66                 : boost::next(found);
67         }
68     };
69 
70     template< class BidirectionalRange >
71     struct range_return< BidirectionalRange, return_prior >
72     {
73         typedef BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type type;
74 
packboost::range_return75         static type pack(type found, BidirectionalRange& rng)
76         {
77             return found == boost::begin(rng)
78                 ? found
79                 : boost::prior(found);
80         }
81     };
82 
83     template< class SinglePassRange >
84     struct range_return< SinglePassRange, return_begin_found >
85     {
86         typedef boost::iterator_range<
87             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
88 
packboost::range_return89         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
90                          SinglePassRange& rng)
91         {
92             return type(boost::begin(rng), found);
93         }
94     };
95 
96     template< class SinglePassRange >
97     struct range_return< SinglePassRange, return_begin_next >
98     {
99         typedef boost::iterator_range<
100             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
101 
packboost::range_return102         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
103                          SinglePassRange& rng)
104         {
105             return type( boost::begin(rng),
106                          found == boost::end(rng) ? found : boost::next(found) );
107         }
108     };
109 
110     template< class BidirectionalRange >
111     struct range_return< BidirectionalRange, return_begin_prior >
112     {
113         typedef boost::iterator_range<
114             BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type > type;
115 
packboost::range_return116         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type found,
117                          BidirectionalRange& rng)
118         {
119             return type( boost::begin(rng),
120                          found == boost::begin(rng) ? found : boost::prior(found) );
121         }
122     };
123 
124     template< class SinglePassRange >
125     struct range_return< SinglePassRange, return_found_end >
126     {
127         typedef boost::iterator_range<
128             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
129 
packboost::range_return130         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
131                          SinglePassRange& rng)
132         {
133             return type(found, boost::end(rng));
134         }
135     };
136 
137     template< class SinglePassRange >
138     struct range_return< SinglePassRange, return_next_end >
139     {
140         typedef boost::iterator_range<
141             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
142 
packboost::range_return143         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type found,
144                          SinglePassRange& rng)
145         {
146             return type( found == boost::end(rng) ? found : boost::next(found),
147                          boost::end(rng) );
148         }
149     };
150 
151     template< class BidirectionalRange >
152     struct range_return< BidirectionalRange, return_prior_end >
153     {
154         typedef boost::iterator_range<
155             BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type > type;
156 
packboost::range_return157         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type found,
158                          BidirectionalRange& rng)
159         {
160             return type( found == boost::begin(rng) ? found : boost::prior(found),
161                          boost::end(rng) );
162         }
163     };
164 
165     template< class SinglePassRange >
166     struct range_return< SinglePassRange, return_begin_end >
167     {
168         typedef boost::iterator_range<
169             BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type > type;
170 
packboost::range_return171         static type pack(BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type,
172                          SinglePassRange& rng)
173         {
174             return type(boost::begin(rng), boost::end(rng));
175         }
176     };
177 
178 }
179 
180 #endif // include guard
181