Line data Source code
1 : /*=============================================================================
2 : Boost.Wave: A Standard compliant C++ preprocessor library
3 :
4 : Definition of the unput queue iterator
5 :
6 : http://www.boost.org/
7 :
8 : Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
9 : Software License, Version 1.0. (See accompanying file
10 : LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 : =============================================================================*/
12 : #if !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)
13 : #define UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED
14 :
15 : #include <list>
16 :
17 : #include <boost/assert.hpp>
18 : #include <boost/iterator_adaptors.hpp>
19 :
20 : #include <boost/wave/wave_config.hpp>
21 : #include <boost/wave/token_ids.hpp> // token_id
22 :
23 : // this must occur after all of the includes and before any code appears
24 : #ifdef BOOST_HAS_ABI_HEADERS
25 : #include BOOST_ABI_PREFIX
26 : #endif
27 :
28 : ///////////////////////////////////////////////////////////////////////////////
29 : namespace boost {
30 : namespace wave {
31 : namespace util {
32 :
33 : ///////////////////////////////////////////////////////////////////////////////
34 : //
35 : // unput_queue_iterator
36 : //
37 : // The unput_queue_iterator templates encapsulates an unput_queue together
38 : // with the direct input to be read after the unput queue is emptied
39 : //
40 : // This version is for the new iterator_adaptors (was released with
41 : // Boost V1.31.0)
42 : //
43 : ///////////////////////////////////////////////////////////////////////////////
44 : template <typename IteratorT, typename TokenT, typename ContainerT>
45 0 : class unput_queue_iterator
46 : : public boost::iterator_adaptor<
47 : unput_queue_iterator<IteratorT, TokenT, ContainerT>,
48 : IteratorT, TokenT const, std::forward_iterator_tag>
49 : {
50 : typedef boost::iterator_adaptor<
51 : unput_queue_iterator<IteratorT, TokenT, ContainerT>,
52 : IteratorT, TokenT const, std::forward_iterator_tag>
53 : base_type;
54 :
55 : public:
56 : typedef ContainerT container_type;
57 : typedef IteratorT iterator_type;
58 :
59 0 : unput_queue_iterator(IteratorT const &it, ContainerT &queue)
60 0 : : base_type(it), unput_queue(queue)
61 : {}
62 :
63 0 : ContainerT &get_unput_queue()
64 : { return unput_queue; }
65 : ContainerT const &get_unput_queue() const
66 : { return unput_queue; }
67 0 : IteratorT &get_base_iterator()
68 0 : { return base_type::base_reference(); }
69 0 : IteratorT const &get_base_iterator() const
70 0 : { return base_type::base_reference(); }
71 :
72 0 : unput_queue_iterator &operator= (unput_queue_iterator const &rhs)
73 : {
74 0 : if (this != &rhs) {
75 0 : unput_queue = rhs.unput_queue;
76 0 : base_type::operator=(rhs);
77 : }
78 0 : return *this;
79 : }
80 :
81 0 : typename base_type::reference dereference() const
82 : {
83 0 : if (!unput_queue.empty())
84 0 : return unput_queue.front();
85 0 : return *base_type::base_reference();
86 : }
87 :
88 0 : void increment()
89 : {
90 0 : if (!unput_queue.empty()) {
91 : // there exist pending tokens in the unput queue
92 0 : unput_queue.pop_front();
93 : }
94 : else {
95 : // the unput_queue is empty, so advance the base iterator
96 0 : ++base_type::base_reference();
97 : }
98 0 : }
99 :
100 : template <
101 : typename OtherDerivedT, typename OtherIteratorT,
102 : typename V, typename C, typename R, typename D
103 : >
104 0 : bool equal(
105 : boost::iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
106 : const &x) const
107 : {
108 : // two iterators are equal, if both begin() iterators of the queue
109 : // objects are equal and the base iterators are equal as well
110 0 : OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
111 : return
112 0 : ((unput_queue.empty() && rhs.unput_queue.empty()) ||
113 0 : (&unput_queue == &rhs.unput_queue &&
114 0 : unput_queue.begin() == rhs.unput_queue.begin()
115 : )
116 0 : ) &&
117 0 : (get_base_iterator() == rhs.get_base_iterator());
118 : }
119 :
120 : private:
121 : ContainerT &unput_queue;
122 : };
123 :
124 : namespace impl {
125 :
126 : ///////////////////////////////////////////////////////////////////////////
127 : template <typename IteratorT, typename TokenT, typename ContainerT>
128 : struct gen_unput_queue_iterator
129 : {
130 : typedef ContainerT container_type;
131 : typedef IteratorT iterator_type;
132 : typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
133 : return_type;
134 :
135 : static container_type last;
136 :
137 : static return_type
138 0 : generate(iterator_type const &it)
139 : {
140 0 : return return_type(it, last);
141 : }
142 :
143 : static return_type
144 0 : generate(ContainerT &queue, iterator_type const &it)
145 : {
146 0 : return return_type(it, queue);
147 : }
148 : };
149 :
150 : template <typename IteratorT, typename TokenT, typename ContainerT>
151 : typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
152 : container_type
153 : gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last =
154 : typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
155 : container_type();
156 :
157 : ///////////////////////////////////////////////////////////////////////////
158 : template <typename IteratorT, typename TokenT, typename ContainerT>
159 : struct gen_unput_queue_iterator<
160 : unput_queue_iterator<IteratorT, TokenT, ContainerT>,
161 : TokenT, ContainerT>
162 : {
163 : typedef ContainerT container_type;
164 : typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
165 : iterator_type;
166 : typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
167 : return_type;
168 :
169 : static container_type last;
170 :
171 : static return_type
172 : generate(iterator_type &it)
173 : {
174 : return return_type(it.base(), last);
175 : }
176 :
177 : static return_type
178 : generate(ContainerT &queue, iterator_type &it)
179 : {
180 : return return_type(it.base(), queue);
181 : }
182 : };
183 :
184 : ///////////////////////////////////////////////////////////////////////////
185 : template <typename IteratorT>
186 : struct assign_iterator
187 : {
188 : static void
189 0 : do_ (IteratorT &dest, IteratorT const &src)
190 : {
191 0 : dest = src;
192 0 : }
193 : };
194 :
195 : ///////////////////////////////////////////////////////////////////////////
196 : //
197 : // Look for the first non-whitespace token and return this token id.
198 : // Note though, that the embedded unput_queues are not touched in any way!
199 : //
200 : template <typename IteratorT>
201 : struct next_token
202 : {
203 : static boost::wave::token_id
204 0 : peek(IteratorT it, IteratorT end, bool skip_whitespace = true)
205 : {
206 : using namespace boost::wave;
207 0 : if (skip_whitespace) {
208 0 : for (++it; it != end; ++it) {
209 0 : if (!IS_CATEGORY(*it, WhiteSpaceTokenType) &&
210 0 : T_NEWLINE != token_id(*it))
211 : {
212 : break; // stop at the first non-whitespace token
213 : }
214 : }
215 : }
216 : else {
217 0 : ++it; // we have at least to look ahead
218 : }
219 0 : if (it != end)
220 0 : return token_id(*it);
221 : return T_EOI;
222 : }
223 : };
224 :
225 : template <typename IteratorT, typename TokenT, typename ContainerT>
226 : struct next_token<
227 : unput_queue_iterator<IteratorT, TokenT, ContainerT> > {
228 :
229 : typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> iterator_type;
230 :
231 : static boost::wave::token_id
232 0 : peek(iterator_type it, iterator_type end, bool skip_whitespace = true)
233 : {
234 : using namespace boost::wave;
235 :
236 0 : typename iterator_type::container_type &queue = it.get_unput_queue();
237 :
238 : // first try to find it in the unput_queue
239 0 : if (0 != queue.size()) {
240 0 : typename iterator_type::container_type::iterator cit = queue.begin();
241 0 : typename iterator_type::container_type::iterator cend = queue.end();
242 :
243 0 : if (skip_whitespace) {
244 0 : for (++cit; cit != cend; ++cit) {
245 0 : if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) &&
246 0 : T_NEWLINE != token_id(*cit))
247 : {
248 : break; // stop at the first non-whitespace token
249 : }
250 : }
251 : }
252 : else {
253 0 : ++cit; // we have at least to look ahead
254 : }
255 0 : if (cit != cend)
256 0 : return token_id(*cit);
257 : }
258 :
259 : // second try to move on into the base iterator stream
260 0 : typename iterator_type::iterator_type base_it = it.get_base_iterator();
261 0 : typename iterator_type::iterator_type base_end = end.get_base_iterator();
262 :
263 0 : if (0 == queue.size())
264 0 : ++base_it; // advance, if the unput queue is empty
265 :
266 0 : if (skip_whitespace) {
267 0 : for (/**/; base_it != base_end; ++base_it) {
268 0 : if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) &&
269 0 : T_NEWLINE != token_id(*base_it))
270 : {
271 : break; // stop at the first non-whitespace token
272 : }
273 : }
274 : }
275 0 : if (base_it == base_end)
276 : return T_EOI;
277 :
278 0 : return token_id(*base_it);
279 : }
280 : };
281 :
282 : ///////////////////////////////////////////////////////////////////////////////
283 : } // namespace impl
284 :
285 : ///////////////////////////////////////////////////////////////////////////////
286 : } // namespace util
287 : } // namespace wave
288 : } // namespace boost
289 :
290 : // the suffix header occurs after all of the code
291 : #ifdef BOOST_HAS_ABI_HEADERS
292 : #include BOOST_ABI_SUFFIX
293 : #endif
294 :
295 : #endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)
|