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