You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
295 lines
9.7 KiB
295 lines
9.7 KiB
/*============================================================================= |
|
Boost.Wave: A Standard compliant C++ preprocessor library |
|
|
|
Definition of the unput queue iterator |
|
|
|
http://www.boost.org/ |
|
|
|
Copyright (c) 2001-2011 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 <list> |
|
|
|
#include <boost/assert.hpp> |
|
#include <boost/iterator_adaptors.hpp> |
|
|
|
#include <boost/wave/wave_config.hpp> |
|
#include <boost/wave/token_ids.hpp> // 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 <typename IteratorT, typename TokenT, typename ContainerT> |
|
class unput_queue_iterator |
|
: public boost::iterator_adaptor< |
|
unput_queue_iterator<IteratorT, TokenT, ContainerT>, |
|
IteratorT, TokenT const, std::forward_iterator_tag> |
|
{ |
|
typedef boost::iterator_adaptor< |
|
unput_queue_iterator<IteratorT, TokenT, ContainerT>, |
|
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<OtherDerivedT, OtherIteratorT, V, C, R, D> |
|
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<OtherDerivedT const &>(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 <typename IteratorT, typename TokenT, typename ContainerT> |
|
struct gen_unput_queue_iterator |
|
{ |
|
typedef ContainerT container_type; |
|
typedef IteratorT iterator_type; |
|
typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> |
|
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 IteratorT, typename TokenT, typename ContainerT> |
|
typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>:: |
|
container_type |
|
gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last = |
|
typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>:: |
|
container_type(); |
|
|
|
/////////////////////////////////////////////////////////////////////////// |
|
template <typename IteratorT, typename TokenT, typename ContainerT> |
|
struct gen_unput_queue_iterator< |
|
unput_queue_iterator<IteratorT, TokenT, ContainerT>, |
|
TokenT, ContainerT> |
|
{ |
|
typedef ContainerT container_type; |
|
typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> |
|
iterator_type; |
|
typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> |
|
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 <typename IteratorT> |
|
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 <typename IteratorT> |
|
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 <typename IteratorT, typename TokenT, typename ContainerT> |
|
struct next_token< |
|
unput_queue_iterator<IteratorT, TokenT, ContainerT> > { |
|
|
|
typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> 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)
|
|
|