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/config.hpp>
13 #include <boost/assert.hpp>
14 #include <boost/core/addressof.hpp>
15 #include <boost/mpl/if.hpp>
16 #include <boost/function_types/is_function_pointer.hpp>
17 #include <boost/function_types/result_type.hpp>
18 #include <boost/iterator/iterator_facade.hpp>
19 #include <boost/none.hpp>
20 #include <boost/optional/optional.hpp>
21 #include <boost/utility/result_of.hpp>
22 
23 #ifdef BOOST_RESULT_OF_USE_TR1
24 #include <boost/type_traits/is_function.hpp>
25 #endif
26 
27 namespace boost {
28 
29 namespace iterators {
30 
31     namespace impl {
32 
33         // Computes the return type of an lvalue-call with an empty argument,
34         // i.e. decltype(declval<F&>()()). F should be a nullary lvalue-callable
35         // or function.
36         template <class F>
37         struct result_of_nullary_lvalue_call
38         {
39             typedef typename result_of<
40 #ifdef BOOST_RESULT_OF_USE_TR1
41                 typename mpl::if_<is_function<F>, F&, F>::type()
42 #else
43                 F&()
44 #endif
45             >::type type;
46         };
47 
48         template <class Function, class Input>
49         class function_input_iterator
50             : public iterator_facade<
51             function_input_iterator<Function, Input>,
52             typename result_of_nullary_lvalue_call<Function>::type,
53             single_pass_traversal_tag,
54             typename result_of_nullary_lvalue_call<Function>::type const &
55             >
56         {
57         public:
function_input_iterator()58             function_input_iterator() {}
function_input_iterator(Function & f_,Input state_=Input ())59             function_input_iterator(Function & f_, Input state_ = Input())
60                 : f(boost::addressof(f_)), state(state_) {}
61 
increment()62             void increment() {
63                 if(value)
64                     value = none;
65                 else
66                     (*f)();
67                 ++state;
68             }
69 
70             typename result_of_nullary_lvalue_call<Function>::type const &
dereference() const71                 dereference() const {
72                     return (value ? value : value = (*f)()).get();
73             }
74 
equal(function_input_iterator const & other) const75             bool equal(function_input_iterator const & other) const {
76                 return f == other.f && state == other.state;
77             }
78 
79         private:
80             Function * f;
81             Input state;
82             mutable optional<typename result_of_nullary_lvalue_call<Function>::type> value;
83         };
84 
85         template <class Function, class Input>
86         class function_pointer_input_iterator
87             : public iterator_facade<
88             function_pointer_input_iterator<Function, Input>,
89             typename function_types::result_type<Function>::type,
90             single_pass_traversal_tag,
91             typename function_types::result_type<Function>::type const &
92             >
93         {
94         public:
function_pointer_input_iterator()95             function_pointer_input_iterator() {}
function_pointer_input_iterator(Function & f_,Input state_=Input ())96             function_pointer_input_iterator(Function &f_, Input state_ = Input())
97                 : f(f_), state(state_) {}
98 
increment()99             void increment() {
100                 if(value)
101                     value = none;
102                 else
103                     (*f)();
104                 ++state;
105             }
106 
107             typename function_types::result_type<Function>::type const &
dereference() const108                 dereference() const {
109                     return (value ? value : value = (*f)()).get();
110             }
111 
equal(function_pointer_input_iterator const & other) const112             bool equal(function_pointer_input_iterator const & other) const {
113                 return f == other.f && state == other.state;
114             }
115 
116         private:
117             Function f;
118             Input state;
119             mutable optional<typename function_types::result_type<Function>::type> value;
120         };
121 
122     } // namespace impl
123 
124     template <class Function, class Input>
125     class function_input_iterator
126         : public mpl::if_<
127             function_types::is_function_pointer<Function>,
128             impl::function_pointer_input_iterator<Function,Input>,
129             impl::function_input_iterator<Function,Input>
130         >::type
131     {
132         typedef typename mpl::if_<
133             function_types::is_function_pointer<Function>,
134             impl::function_pointer_input_iterator<Function,Input>,
135             impl::function_input_iterator<Function,Input>
136         >::type base_type;
137     public:
function_input_iterator(Function & f,Input i)138         function_input_iterator(Function & f, Input i)
139             : base_type(f, i) {}
140     };
141 
142     template <class Function, class Input>
143     inline function_input_iterator<Function, Input>
make_function_input_iterator(Function & f,Input state)144         make_function_input_iterator(Function & f, Input state) {
145             typedef function_input_iterator<Function, Input> result_t;
146             return result_t(f, state);
147     }
148 
149     template <class Function, class Input>
150     inline function_input_iterator<Function*, Input>
make_function_input_iterator(Function * f,Input state)151         make_function_input_iterator(Function * f, Input state) {
152             typedef function_input_iterator<Function*, Input> result_t;
153             return result_t(f, state);
154     }
155 
156     struct infinite {
operator ++boost::iterators::infinite157         infinite & operator++() { return *this; }
operator ++boost::iterators::infinite158         infinite & operator++(int) { return *this; }
operator ==boost::iterators::infinite159         bool operator==(infinite &) const { return false; };
operator ==boost::iterators::infinite160         bool operator==(infinite const &) const { return false; };
161     };
162 
163 } // namespace iterators
164 
165 using iterators::function_input_iterator;
166 using iterators::make_function_input_iterator;
167 using iterators::infinite;
168 
169 } // namespace boost
170 
171 #endif
172 
173