1 // Copyright 2009 (C) Dean Michael Berris <me@deanberris.com>
2 // Copyright 2012 (C) Google, Inc.
3 // Copyright 2012 (C) Jeffrey Lee Hellrung, Jr.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #ifndef BOOST_FUNCTION_INPUT_ITERATOR
10 #define BOOST_FUNCTION_INPUT_ITERATOR
11 
12 #include <boost/assert.hpp>
13 #include <boost/mpl/if.hpp>
14 #include <boost/function_types/is_function_pointer.hpp>
15 #include <boost/function_types/is_function_reference.hpp>
16 #include <boost/function_types/result_type.hpp>
17 #include <boost/iterator/iterator_facade.hpp>
18 #include <boost/none.hpp>
19 #include <boost/optional/optional.hpp>
20 
21 namespace boost {
22 
23 namespace iterators {
24 
25     namespace impl {
26 
27         template <class Function, class Input>
28         class function_input_iterator
29             : public iterator_facade<
30             function_input_iterator<Function, Input>,
31             typename Function::result_type,
32             single_pass_traversal_tag,
33             typename Function::result_type const &
34             >
35         {
36         public:
function_input_iterator()37             function_input_iterator() {}
function_input_iterator(Function & f_,Input state_=Input ())38             function_input_iterator(Function & f_, Input state_ = Input())
39                 : f(&f_), state(state_) {}
40 
increment()41             void increment() {
42                 if(value)
43                     value = none;
44                 else
45                     (*f)();
46                 ++state;
47             }
48 
49             typename Function::result_type const &
dereference() const50                 dereference() const {
51                     return (value ? value : value = (*f)()).get();
52             }
53 
equal(function_input_iterator const & other) const54             bool equal(function_input_iterator const & other) const {
55                 return f == other.f && state == other.state;
56             }
57 
58         private:
59             Function * f;
60             Input state;
61             mutable optional<typename Function::result_type> value;
62         };
63 
64         template <class Function, class Input>
65         class function_pointer_input_iterator
66             : public iterator_facade<
67             function_pointer_input_iterator<Function, Input>,
68             typename function_types::result_type<Function>::type,
69             single_pass_traversal_tag,
70             typename function_types::result_type<Function>::type const &
71             >
72         {
73         public:
function_pointer_input_iterator()74             function_pointer_input_iterator() {}
function_pointer_input_iterator(Function & f_,Input state_=Input ())75             function_pointer_input_iterator(Function &f_, Input state_ = Input())
76                 : f(f_), state(state_) {}
77 
increment()78             void increment() {
79                 if(value)
80                     value = none;
81                 else
82                     (*f)();
83                 ++state;
84             }
85 
86             typename function_types::result_type<Function>::type const &
dereference() const87                 dereference() const {
88                     return (value ? value : value = (*f)()).get();
89             }
90 
equal(function_pointer_input_iterator const & other) const91             bool equal(function_pointer_input_iterator const & other) const {
92                 return f == other.f && state == other.state;
93             }
94 
95         private:
96             Function f;
97             Input state;
98             mutable optional<typename function_types::result_type<Function>::type> value;
99         };
100 
101         template <class Function, class Input>
102         class function_reference_input_iterator
103             : public function_pointer_input_iterator<Function*,Input>
104         {
105         public:
function_reference_input_iterator(Function & f_,Input state_=Input ())106             function_reference_input_iterator(Function & f_, Input state_ = Input())
107                 : function_pointer_input_iterator<Function*,Input>(&f_, state_)
108             {}
109         };
110 
111     } // namespace impl
112 
113     template <class Function, class Input>
114     class function_input_iterator
115         : public mpl::if_<
116             function_types::is_function_pointer<Function>,
117             impl::function_pointer_input_iterator<Function,Input>,
118             typename mpl::if_<
119                 function_types::is_function_reference<Function>,
120                 impl::function_reference_input_iterator<Function,Input>,
121                 impl::function_input_iterator<Function,Input>
122             >::type
123         >::type
124     {
125         typedef typename mpl::if_<
126             function_types::is_function_pointer<Function>,
127             impl::function_pointer_input_iterator<Function,Input>,
128             typename mpl::if_<
129                 function_types::is_function_reference<Function>,
130                 impl::function_reference_input_iterator<Function,Input>,
131                 impl::function_input_iterator<Function,Input>
132             >::type
133         >::type base_type;
134     public:
function_input_iterator(Function & f,Input i)135         function_input_iterator(Function & f, Input i)
136             : base_type(f, i) {}
137     };
138 
139     template <class Function, class Input>
140     inline function_input_iterator<Function, Input>
make_function_input_iterator(Function & f,Input state)141         make_function_input_iterator(Function & f, Input state) {
142             typedef function_input_iterator<Function, Input> result_t;
143             return result_t(f, state);
144     }
145 
146     template <class Function, class Input>
147     inline function_input_iterator<Function*, Input>
make_function_input_iterator(Function * f,Input state)148         make_function_input_iterator(Function * f, Input state) {
149             typedef function_input_iterator<Function*, Input> result_t;
150             return result_t(f, state);
151     }
152 
153     struct infinite {
operator ++boost::iterators::infinite154         infinite & operator++() { return *this; }
operator ++boost::iterators::infinite155         infinite & operator++(int) { return *this; }
operator ==boost::iterators::infinite156         bool operator==(infinite &) const { return false; };
operator ==boost::iterators::infinite157         bool operator==(infinite const &) const { return false; };
158     };
159 
160 } // namespace iterators
161 
162 using iterators::function_input_iterator;
163 using iterators::make_function_input_iterator;
164 using iterators::infinite;
165 
166 } // namespace boost
167 
168 #endif
169 
170