/*============================================================================= Boost.Wave: A Standard compliant C++ preprocessor library Definition of the unput queue iterator http://www.boost.org/ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED) #define UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED #include #include #include #include #include // token_id // this must occur after all of the includes and before any code appears #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_PREFIX #endif /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace wave { namespace util { /////////////////////////////////////////////////////////////////////////////// // // unput_queue_iterator // // The unput_queue_iterator templates encapsulates an unput_queue together // with the direct input to be read after the unput queue is emptied // // This version is for the new iterator_adaptors (was released with // Boost V1.31.0) // /////////////////////////////////////////////////////////////////////////////// template class unput_queue_iterator : public boost::iterator_adaptor< unput_queue_iterator, IteratorT, TokenT const, std::forward_iterator_tag> { typedef boost::iterator_adaptor< unput_queue_iterator, IteratorT, TokenT const, std::forward_iterator_tag> base_type; public: typedef ContainerT container_type; typedef IteratorT iterator_type; unput_queue_iterator(IteratorT const &it, ContainerT &queue) : base_type(it), unput_queue(queue) {} ContainerT &get_unput_queue() { return unput_queue; } ContainerT const &get_unput_queue() const { return unput_queue; } IteratorT &get_base_iterator() { return base_type::base_reference(); } IteratorT const &get_base_iterator() const { return base_type::base_reference(); } unput_queue_iterator &operator= (unput_queue_iterator const &rhs) { if (this != &rhs) { unput_queue = rhs.unput_queue; base_type::operator=(rhs); } return *this; } typename base_type::reference dereference() const { if (!unput_queue.empty()) return unput_queue.front(); return *base_type::base_reference(); } void increment() { if (!unput_queue.empty()) { // there exist pending tokens in the unput queue unput_queue.pop_front(); } else { // the unput_queue is empty, so advance the base iterator ++base_type::base_reference(); } } template < typename OtherDerivedT, typename OtherIteratorT, typename V, typename C, typename R, typename D > bool equal( boost::iterator_adaptor const &x) const { // two iterators are equal, if both begin() iterators of the queue // objects are equal and the base iterators are equal as well OtherDerivedT const &rhs = static_cast(x); return ((unput_queue.empty() && rhs.unput_queue.empty()) || (&unput_queue == &rhs.unput_queue && unput_queue.begin() == rhs.unput_queue.begin() ) ) && (get_base_iterator() == rhs.get_base_iterator()); } private: ContainerT &unput_queue; }; namespace impl { /////////////////////////////////////////////////////////////////////////// template struct gen_unput_queue_iterator { typedef ContainerT container_type; typedef IteratorT iterator_type; typedef unput_queue_iterator return_type; static container_type last; static return_type generate(iterator_type const &it) { return return_type(it, last); } static return_type generate(ContainerT &queue, iterator_type const &it) { return return_type(it, queue); } }; template typename gen_unput_queue_iterator:: container_type gen_unput_queue_iterator::last = typename gen_unput_queue_iterator:: container_type(); /////////////////////////////////////////////////////////////////////////// template struct gen_unput_queue_iterator< unput_queue_iterator, TokenT, ContainerT> { typedef ContainerT container_type; typedef unput_queue_iterator iterator_type; typedef unput_queue_iterator return_type; static container_type last; static return_type generate(iterator_type &it) { return return_type(it.base(), last); } static return_type generate(ContainerT &queue, iterator_type &it) { return return_type(it.base(), queue); } }; /////////////////////////////////////////////////////////////////////////// template struct assign_iterator { static void do_ (IteratorT &dest, IteratorT const &src) { dest = src; } }; /////////////////////////////////////////////////////////////////////////// // // Look for the first non-whitespace token and return this token id. // Note though, that the embedded unput_queues are not touched in any way! // template struct next_token { static boost::wave::token_id peek(IteratorT it, IteratorT end, bool skip_whitespace = true) { using namespace boost::wave; if (skip_whitespace) { for (++it; it != end; ++it) { if (!IS_CATEGORY(*it, WhiteSpaceTokenType) && T_NEWLINE != token_id(*it)) { break; // stop at the first non-whitespace token } } } else { ++it; // we have at least to look ahead } if (it != end) return token_id(*it); return T_EOI; } }; template struct next_token< unput_queue_iterator > { typedef unput_queue_iterator iterator_type; static boost::wave::token_id peek(iterator_type it, iterator_type end, bool skip_whitespace = true) { using namespace boost::wave; typename iterator_type::container_type &queue = it.get_unput_queue(); // first try to find it in the unput_queue if (0 != queue.size()) { typename iterator_type::container_type::iterator cit = queue.begin(); typename iterator_type::container_type::iterator cend = queue.end(); if (skip_whitespace) { for (++cit; cit != cend; ++cit) { if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) && T_NEWLINE != token_id(*cit)) { break; // stop at the first non-whitespace token } } } else { ++cit; // we have at least to look ahead } if (cit != cend) return token_id(*cit); } // second try to move on into the base iterator stream typename iterator_type::iterator_type base_it = it.get_base_iterator(); typename iterator_type::iterator_type base_end = end.get_base_iterator(); if (0 == queue.size()) ++base_it; // advance, if the unput queue is empty if (skip_whitespace) { for (/**/; base_it != base_end; ++base_it) { if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) && T_NEWLINE != token_id(*base_it)) { break; // stop at the first non-whitespace token } } } if (base_it == base_end) return T_EOI; return token_id(*base_it); } }; /////////////////////////////////////////////////////////////////////////////// } // namespace impl /////////////////////////////////////////////////////////////////////////////// } // namespace util } // namespace wave } // namespace boost // the suffix header occurs after all of the code #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)