source: NonGTP/Boost/boost/wave/util/unput_queue_iterator.hpp @ 857

Revision 857, 15.3 KB checked in by igarcia, 18 years ago (diff)
Line 
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-2005 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
22///////////////////////////////////////////////////////////////////////////////
23namespace boost {
24namespace wave {
25namespace util {
26
27#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
28    BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
29
30template <typename TokenT, typename ContainerT>
31class unput_queue_policies : public boost::default_iterator_policies
32{
33public:
34    unput_queue_policies(ContainerT &unput_queue_)
35    :   unput_queue(unput_queue_)
36    {}
37   
38    unput_queue_policies &operator= (unput_queue_policies const &rhs)
39    {
40        unput_queue = rhs.unput_queue;
41        return *this;
42    }
43   
44    template <typename BaseT>
45    void initialize(BaseT &)
46    {}
47
48    template <typename IteratorAdaptorT>
49    typename IteratorAdaptorT::reference
50    dereference(const IteratorAdaptorT &x) const
51    {
52        if (x.policies().unput_queue.size() > 0)
53            return x.policies().unput_queue.front();
54        return *x.base();
55    }
56
57    template <typename IteratorAdaptorT>
58    void
59    increment(IteratorAdaptorT &x)
60    {
61        if (x.policies().unput_queue.size() > 0) {
62        // there exist pending tokens in the unput queue
63            x.policies().unput_queue.pop_front();
64        }
65        else {
66        // the unput_queue is empty, so advance the base iterator
67            ++x.base();
68        }
69    }
70
71    template <typename IteratorAdaptorT1, typename IteratorAdaptorT2>
72    bool
73    equal(const IteratorAdaptorT1 &x, const IteratorAdaptorT2 &y) const
74    {
75    // two iterators are equal, if both begin() iterators of the queue objects
76    // are equal and the base iterators are equal as well
77        return
78           (x.policies().unput_queue.begin() == y.policies().unput_queue.begin() ||
79            (0 == x.policies().queuesize() && 0 == y.policies().queuesize())) &&
80            x.base() == y.base();
81    }
82   
83    typename ContainerT::size_type queuesize() const
84    { return unput_queue.size(); }
85
86    ContainerT &get_unput_queue() { return unput_queue; }
87    ContainerT const &get_unput_queue() const { return unput_queue; }
88   
89private:
90    ContainerT &unput_queue;
91};
92
93///////////////////////////////////////////////////////////////////////////////
94//
95//  unput_queue_iterator
96//
97//      The unput_queue_iterator templates encapsulates an unput_queue together
98//      with the direct input to be read after the unput queue is emptied
99//
100//      This version is for the old iterator_adaptors (Boost V1.30.x)
101//
102///////////////////////////////////////////////////////////////////////////////
103template <typename IteratorT, typename TokenT, typename ContainerT>
104class unput_queue_iterator
105:   public boost::iterator_adaptor<
106        IteratorT, unput_queue_policies<TokenT, ContainerT>, TokenT,
107        TokenT const &, TokenT const *>
108{
109    typedef
110        boost::iterator_adaptor<
111            IteratorT, unput_queue_policies<TokenT, ContainerT>, TokenT,
112            TokenT const &, TokenT const *
113        >
114        base_type;
115    typedef unput_queue_policies<TokenT, ContainerT> policies_type;
116       
117public:
118    typedef ContainerT  container_type;
119    typedef IteratorT   iterator_type;
120   
121    unput_queue_iterator(IteratorT const &it, ContainerT &queue)
122    :   base_type(it, policies_type(queue))
123    {}
124   
125    ContainerT &get_unput_queue()
126        { return policies().get_unput_queue(); }
127    ContainerT const &get_unput_queue() const
128        { return policies().get_unput_queue(); }
129    IteratorT &get_base_iterator()
130        { return base(); }
131    IteratorT const &get_base_iterator() const
132        { return base(); }
133};
134
135#else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
136
137///////////////////////////////////////////////////////////////////////////////
138//
139//  unput_queue_iterator
140//
141//      The unput_queue_iterator templates encapsulates an unput_queue together
142//      with the direct input to be read after the unput queue is emptied
143//
144//      This version is for the new iterator_adaptors (was released with
145//      Boost V1.31.0)
146//
147///////////////////////////////////////////////////////////////////////////////
148template <typename IteratorT, typename TokenT, typename ContainerT>
149class unput_queue_iterator
150:   public boost::iterator_adaptor<
151        unput_queue_iterator<IteratorT, TokenT, ContainerT>,
152            IteratorT, TokenT const, std::forward_iterator_tag>
153{
154    typedef boost::iterator_adaptor<
155                unput_queue_iterator<IteratorT, TokenT, ContainerT>,
156                IteratorT, TokenT const, std::forward_iterator_tag>
157        base_type;
158       
159public:
160    typedef ContainerT  container_type;
161    typedef IteratorT   iterator_type;
162
163    unput_queue_iterator(IteratorT const &it, ContainerT &queue)
164    :   base_type(it), unput_queue(queue)
165    {}
166   
167    ContainerT &get_unput_queue()
168        { return unput_queue; }
169    ContainerT const &get_unput_queue() const
170        { return unput_queue; }
171    IteratorT &get_base_iterator()
172        { return base_type::base_reference(); }
173    IteratorT const &get_base_iterator() const
174        { return base_type::base_reference(); }
175   
176    unput_queue_iterator &operator= (unput_queue_iterator const &rhs)
177    {
178        if (this != &rhs) {
179            unput_queue = rhs.unput_queue;
180            base_type::operator=(rhs);
181        }
182        return *this;
183    }
184
185    typename base_type::reference dereference() const
186    {
187        if (!unput_queue.empty())
188            return unput_queue.front();
189        return *base_type::base_reference();
190    }
191
192    void increment()
193    {
194        if (!unput_queue.empty()) {
195        // there exist pending tokens in the unput queue
196            unput_queue.pop_front();
197        }
198        else {
199        // the unput_queue is empty, so advance the base iterator
200            ++base_type::base_reference();
201        }
202    }
203
204    template <
205        typename OtherDerivedT, typename OtherIteratorT,
206        typename V, typename C, typename R, typename D
207    >   
208    bool equal(
209        boost::iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
210        const &x) const
211    {
212    // two iterators are equal, if both begin() iterators of the queue
213    // objects are equal and the base iterators are equal as well
214        OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
215        return
216            (unput_queue.empty() && rhs.unput_queue.empty() ||
217              (&unput_queue == &rhs.unput_queue &&
218               unput_queue.begin() == rhs.unput_queue.begin()
219              )
220            ) &&
221            get_base_iterator() == rhs.get_base_iterator();
222    }
223
224private:
225    ContainerT &unput_queue;
226};
227
228#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
229
230namespace impl {
231
232    ///////////////////////////////////////////////////////////////////////////
233    template <typename IteratorT, typename TokenT, typename ContainerT>
234    struct gen_unput_queue_iterator
235    {
236        typedef ContainerT  container_type;
237        typedef IteratorT iterator_type;
238        typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
239            return_type;
240               
241        static container_type last;
242       
243        static return_type
244        generate(iterator_type const &it)
245        {
246            return return_type(it, last);
247        }
248
249        static return_type
250        generate(ContainerT &queue, iterator_type const &it)
251        {
252            return return_type(it, queue);
253        }
254    };
255   
256    template <typename IteratorT, typename TokenT, typename ContainerT>
257    typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
258          container_type 
259        gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last =
260            typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
261                  container_type();
262
263    ///////////////////////////////////////////////////////////////////////////
264    template <typename IteratorT, typename TokenT, typename ContainerT>
265    struct gen_unput_queue_iterator<
266        unput_queue_iterator<IteratorT, TokenT, ContainerT>,
267            TokenT, ContainerT>
268    {
269        typedef ContainerT  container_type;
270        typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
271            iterator_type;
272        typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
273            return_type;
274       
275        static container_type last;
276       
277        static return_type
278        generate(iterator_type &it)
279        {
280            return return_t(it.base(), last);
281        }
282
283        static return_type
284        generate(ContainerT &queue, iterator_type &it)
285        {
286            return return_t(it.base(), queue);
287        }
288    };
289   
290    ///////////////////////////////////////////////////////////////////////////
291    template <typename IteratorT>
292    struct assign_iterator {
293   
294        static void
295        do_ (IteratorT &dest, IteratorT const &src)
296        {
297            dest = src;
298        }
299    };
300   
301#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
302    BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
303   
304    template <typename IteratorT, typename TokenT, typename ContainerT>
305    struct assign_iterator<
306        unput_queue_iterator<IteratorT, TokenT, ContainerT> >
307    {
308        typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
309            iterator_type;
310       
311        static void
312        do_ (iterator_type &dest, iterator_type const &src)
313        {
314            dest.base() = src.base();
315            dest.policies() = src.policies();
316        }
317    };
318   
319#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
320
321    ///////////////////////////////////////////////////////////////////////////
322    //
323    // Look for the first non-whitespace token and return this token id.
324    // Note though, that the embedded unput_queues are not touched in any way!
325    //
326    template <typename IteratorT>
327    struct next_token {
328   
329        static boost::wave::token_id 
330        peek(IteratorT it, IteratorT end, bool skip_whitespace = true)
331        {
332            using namespace boost::wave;
333            if (skip_whitespace) {
334                for (++it; it != end; ++it) {
335                    if (!IS_CATEGORY(*it, WhiteSpaceTokenType) &&
336                        T_NEWLINE != token_id(*it))
337                    {
338                        break;  // stop at the first non-whitespace token
339                    }
340                }
341            }
342            else {
343                ++it;           // we have at least to look ahead
344            }
345            if (it != end)
346                return token_id(*it);
347            return T_EOI;
348        }
349    };
350   
351    template <typename IteratorT, typename TokenT, typename ContainerT>
352    struct next_token<
353        unput_queue_iterator<IteratorT, TokenT, ContainerT> > {
354       
355        typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> iterator_type;
356       
357        static boost::wave::token_id
358        peek(iterator_type it, iterator_type end, bool skip_whitespace = true)
359        {
360            using namespace boost::wave;
361           
362        typename iterator_type::container_type &queue = it.get_unput_queue();
363       
364        // first try to find it in the unput_queue
365            if (0 != queue.size()) {
366            typename iterator_type::container_type::iterator cit = queue.begin();
367            typename iterator_type::container_type::iterator cend = queue.end();
368
369                if (skip_whitespace) {           
370                    for (++cit; cit != cend; ++cit) {
371                        if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) &&
372                            T_NEWLINE != token_id(*cit))
373                        {
374                            break;  // stop at the first non-whitespace token
375                        }
376                    }
377                }
378                else {
379                    ++cit;          // we have at least to look ahead
380                }
381                if (cit != cend)
382                    return token_id(*cit);
383            }
384           
385        // second try to move on into the base iterator stream
386        typename iterator_type::iterator_type base_it = it.get_base_iterator();
387        typename iterator_type::iterator_type base_end = end.get_base_iterator();
388
389            if (0 == queue.size())
390                ++base_it;  // advance, if the unput queue is empty
391
392            if (skip_whitespace) {
393                for (/**/; base_it != base_end; ++base_it) {
394                    if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) &&
395                        T_NEWLINE != token_id(*base_it))
396                    {
397                        break;  // stop at the first non-whitespace token
398                    }
399                }
400            }
401            if (base_it == base_end)
402                return T_EOI;
403
404            return token_id(*base_it);
405        }
406    };
407
408    // Skip all whitespace characters and queue the skipped characters into the
409    // given container
410    template <typename IteratorT>
411    inline boost::wave::token_id
412    skip_whitespace(IteratorT &first, IteratorT const &last)
413    {
414        using namespace cpplexer;
415       
416    token_id id = next_token<IteratorT>::peek(first, last, false);
417
418        if (IS_CATEGORY(id, WhiteSpaceTokenType)) {
419            do {
420                ++first;
421                id = next_token<IteratorT>::peek(first, last, false);
422            } while (IS_CATEGORY(id, WhiteSpaceTokenType));
423        }
424        ++first;
425        return id;
426    }
427   
428    template <typename IteratorT, typename ContainerT>
429    inline boost::wave::token_id
430    skip_whitespace(IteratorT &first, IteratorT const &last, ContainerT &queue)
431    {
432        using namespace cpplexer;
433        queue.push_back (*first);       // queue up the current token
434       
435    token_id id = next_token<IteratorT>::peek(first, last, false);
436
437        if (IS_CATEGORY(id, WhiteSpaceTokenType)) {
438            do {
439                queue.push_back(*++first);  // queue up the next whitespace
440                id = next_token<IteratorT>::peek(first, last, false);
441            } while (IS_CATEGORY(id, WhiteSpaceTokenType));
442        }
443        ++first;
444        return id;
445    }
446
447///////////////////////////////////////////////////////////////////////////////
448}   // namespace impl
449
450///////////////////////////////////////////////////////////////////////////////
451}   // namespace util
452}   // namespace wave
453}   // namespace boost
454
455#endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)
Note: See TracBrowser for help on using the repository browser.