1 | // Copyright (c) 2001, Daniel C. Nuffer |
2 | // Copyright (c) 2001-2011 Hartmut Kaiser |
3 | // http://spirit.sourceforge.net/ |
4 | // |
5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | #if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM) |
9 | #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM |
10 | |
11 | #include <boost/config.hpp> |
12 | #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp> |
13 | #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp> |
14 | #include <boost/spirit/home/support/iterators/detail/combine_policies.hpp> |
15 | #include <boost/limits.hpp> |
16 | #include <boost/detail/workaround.hpp> |
17 | #include <boost/core/invoke_swap.hpp> |
18 | #include <boost/utility/base_from_member.hpp> |
19 | |
20 | namespace boost { namespace spirit |
21 | { |
22 | /////////////////////////////////////////////////////////////////////////// |
23 | // The default multi_pass instantiation uses a ref-counted std_deque scheme. |
24 | /////////////////////////////////////////////////////////////////////////// |
25 | template<typename T, typename Policies> |
26 | class multi_pass |
27 | : private boost::base_from_member< |
28 | typename Policies::BOOST_NESTED_TEMPLATE shared<T>*> |
29 | , public Policies::BOOST_NESTED_TEMPLATE unique<T> |
30 | { |
31 | private: |
32 | // unique and shared data types |
33 | typedef typename Policies::BOOST_NESTED_TEMPLATE unique<T> |
34 | policies_base_type; |
35 | typedef typename Policies::BOOST_NESTED_TEMPLATE shared<T> |
36 | shared_data_type; |
37 | |
38 | typedef boost::base_from_member<shared_data_type*> member_base; |
39 | |
40 | // define the types the standard embedded iterator typedefs are taken |
41 | // from |
42 | typedef typename policies_base_type::input_policy iterator_type; |
43 | |
44 | public: |
45 | // standard iterator typedefs |
46 | typedef std::forward_iterator_tag iterator_category; |
47 | typedef typename iterator_type::value_type value_type; |
48 | typedef typename iterator_type::difference_type difference_type; |
49 | typedef typename iterator_type::distance_type distance_type; |
50 | typedef typename iterator_type::reference reference; |
51 | typedef typename iterator_type::pointer pointer; |
52 | |
53 | multi_pass() : member_base(static_cast<shared_data_type*>(0)) {} |
54 | |
55 | explicit multi_pass(T& input) |
56 | : member_base(new shared_data_type(input)), policies_base_type(input) {} |
57 | |
58 | explicit multi_pass(T const& input) |
59 | : member_base(new shared_data_type(input)), policies_base_type(input) {} |
60 | |
61 | multi_pass(multi_pass const& x) |
62 | : member_base(x.member), policies_base_type(x) |
63 | { |
64 | policies_base_type::clone(*this); |
65 | } |
66 | |
67 | #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
68 | // The standard library shipped with gcc-3.1 has a bug in |
69 | // bits/basic_string.tcc. It tries to use iter::iter(0) to |
70 | // construct an iterator. Ironically, this happens in sanity |
71 | // checking code that isn't required by the standard. |
72 | // The workaround is to provide an additional constructor that |
73 | // ignores its int argument and behaves like the default constructor. |
74 | multi_pass(int) : member_base(static_cast<shared_data_type*>(0)) {} |
75 | #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
76 | |
77 | ~multi_pass() |
78 | { |
79 | if (policies_base_type::release(*this)) { |
80 | policies_base_type::destroy(*this); |
81 | delete this->member; |
82 | } |
83 | } |
84 | |
85 | multi_pass& operator=(multi_pass const& x) |
86 | { |
87 | if (this != &x) { |
88 | multi_pass temp(x); |
89 | temp.swap(*this); |
90 | } |
91 | return *this; |
92 | } |
93 | |
94 | void swap(multi_pass& x) |
95 | { |
96 | boost::core::invoke_swap(this->member, x.member); |
97 | this->policies_base_type::swap(x); |
98 | } |
99 | |
100 | reference operator*() const |
101 | { |
102 | policies_base_type::docheck(*this); |
103 | return policies_base_type::dereference(*this); |
104 | } |
105 | pointer operator->() const |
106 | { |
107 | return &(operator*()); |
108 | } |
109 | |
110 | multi_pass& operator++() |
111 | { |
112 | policies_base_type::docheck(*this); |
113 | policies_base_type::increment(*this); |
114 | return *this; |
115 | } |
116 | multi_pass operator++(int) |
117 | { |
118 | multi_pass tmp(*this); |
119 | ++*this; |
120 | return tmp; |
121 | } |
122 | |
123 | void clear_queue(BOOST_SCOPED_ENUM(traits::clear_mode) mode = |
124 | traits::clear_mode::clear_if_enabled) |
125 | { |
126 | if (mode == traits::clear_mode::clear_always || !inhibit_clear_queue()) |
127 | policies_base_type::clear_queue(*this); |
128 | } |
129 | bool inhibit_clear_queue() const |
130 | { |
131 | return this->member->inhibit_clear_queue_; |
132 | } |
133 | void inhibit_clear_queue(bool flag) |
134 | { |
135 | this->member->inhibit_clear_queue_ = flag; |
136 | } |
137 | |
138 | bool operator==(multi_pass const& y) const |
139 | { |
140 | if (is_eof()) |
141 | return y.is_eof(); |
142 | if (y.is_eof()) |
143 | return false; |
144 | |
145 | return policies_base_type::equal_to(*this, y); |
146 | } |
147 | bool operator<(multi_pass const& y) const |
148 | { |
149 | return policies_base_type::less_than(*this, y); |
150 | } |
151 | |
152 | bool operator!=(multi_pass const& y) const |
153 | { |
154 | return !(*this == y); |
155 | } |
156 | bool operator>(multi_pass const& y) const |
157 | { |
158 | return y < *this; |
159 | } |
160 | bool operator>=(multi_pass const& y) const |
161 | { |
162 | return !(*this < y); |
163 | } |
164 | bool operator<=(multi_pass const& y) const |
165 | { |
166 | return !(y < *this); |
167 | } |
168 | |
169 | // allow access to base member |
170 | shared_data_type* shared() const { return this->member; } |
171 | |
172 | private: // helper functions |
173 | bool is_eof() const |
174 | { |
175 | return (0 == this->member) || policies_base_type::is_eof(*this); |
176 | } |
177 | }; |
178 | |
179 | /////////////////////////////////////////////////////////////////////////// |
180 | // Generator function |
181 | /////////////////////////////////////////////////////////////////////////// |
182 | template <typename Policies, typename T> |
183 | inline multi_pass<T, Policies> |
184 | make_multi_pass(T& i) |
185 | { |
186 | return multi_pass<T, Policies>(i); |
187 | } |
188 | template <typename Policies, typename T> |
189 | inline multi_pass<T, Policies> |
190 | make_multi_pass(T const& i) |
191 | { |
192 | return multi_pass<T, Policies>(i); |
193 | } |
194 | |
195 | /////////////////////////////////////////////////////////////////////////// |
196 | template <typename T> |
197 | inline multi_pass<T> |
198 | make_default_multi_pass(T& i) |
199 | { |
200 | return multi_pass<T>(i); |
201 | } |
202 | template <typename T> |
203 | inline multi_pass<T> |
204 | make_default_multi_pass(T const& i) |
205 | { |
206 | return multi_pass<T>(i); |
207 | } |
208 | |
209 | /////////////////////////////////////////////////////////////////////////// |
210 | template <typename T, typename Policies> |
211 | inline void |
212 | swap(multi_pass<T, Policies> &x, multi_pass<T, Policies> &y) |
213 | { |
214 | x.swap(y); |
215 | } |
216 | |
217 | /////////////////////////////////////////////////////////////////////////// |
218 | // define special functions allowing to integrate any multi_pass iterator |
219 | // with expectation points |
220 | namespace traits |
221 | { |
222 | template <typename T, typename Policies> |
223 | void clear_queue(multi_pass<T, Policies>& mp |
224 | , BOOST_SCOPED_ENUM(traits::clear_mode) mode) |
225 | { |
226 | mp.clear_queue(mode); |
227 | } |
228 | |
229 | template <typename T, typename Policies> |
230 | void inhibit_clear_queue(multi_pass<T, Policies>& mp, bool flag) |
231 | { |
232 | mp.inhibit_clear_queue(flag); |
233 | } |
234 | |
235 | template <typename T, typename Policies> |
236 | bool inhibit_clear_queue(multi_pass<T, Policies>& mp) |
237 | { |
238 | return mp.inhibit_clear_queue(); |
239 | } |
240 | } |
241 | |
242 | }} // namespace boost::spirit |
243 | |
244 | #endif |
245 | |
246 | |
247 | |