123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- // Copyright (c) 2001 Daniel C. Nuffer
- // 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(BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM)
- #define BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM
- #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
- #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
- #include <boost/assert.hpp>
- #include <vector>
- namespace boost { namespace spirit { namespace iterator_policies
- {
- ///////////////////////////////////////////////////////////////////////////
- // class split_std_deque
- //
- // Implementation of the StoragePolicy used by multi_pass
- // This stores all data in a std::vector (despite its name), and keeps an
- // offset to the current position. It stores all the data unless there is
- // only one iterator using the queue.
- //
- ///////////////////////////////////////////////////////////////////////////
- struct split_std_deque
- {
- enum { threshold = 16 };
- ///////////////////////////////////////////////////////////////////////
- template <typename Value>
- class unique //: public detail::default_storage_policy
- {
- private:
- typedef std::vector<Value> queue_type;
- protected:
- unique() : queued_position(0) {}
- unique(unique const& x)
- : queued_position(x.queued_position) {}
- void swap(unique& x)
- {
- boost::swap(queued_position, x.queued_position);
- }
- // This is called when the iterator is dereferenced. It's a
- // template method so we can recover the type of the multi_pass
- // iterator and call advance_input and input_is_valid.
- template <typename MultiPass>
- static typename MultiPass::reference
- dereference(MultiPass const& mp)
- {
- queue_type& queue = mp.shared()->queued_elements;
- typename queue_type::size_type size = queue.size();
- BOOST_ASSERT(mp.queued_position <= size);
- if (mp.queued_position == size)
- {
- // check if this is the only iterator
- if (size >= threshold && MultiPass::is_unique(mp))
- {
- // free up the memory used by the queue.
- queue.clear();
- mp.queued_position = 0;
- }
- return MultiPass::get_input(mp);
- }
- return queue[mp.queued_position];
- }
- // This is called when the iterator is incremented. It's a template
- // method so we can recover the type of the multi_pass iterator
- // and call is_unique and advance_input.
- template <typename MultiPass>
- static void increment(MultiPass& mp)
- {
- queue_type& queue = mp.shared()->queued_elements;
- typename queue_type::size_type size = queue.size();
- BOOST_ASSERT(mp.queued_position <= size);
- // // do not increment iterator as long as the current token is
- // // invalid
- // if (size > 0 && !MultiPass::input_is_valid(mp, queue[mp.queued_position-1]))
- // return;
- if (mp.queued_position == size)
- {
- // check if this is the only iterator
- if (size >= threshold && MultiPass::is_unique(mp))
- {
- // free up the memory used by the queue. we avoid
- // clearing the queue on every increment, though,
- // because this would be too time consuming
- queue.clear();
- mp.queued_position = 0;
- }
- else
- {
- queue.push_back(MultiPass::get_input(mp));
- ++mp.queued_position;
- }
- MultiPass::advance_input(mp);
- }
- else
- {
- ++mp.queued_position;
- }
- }
- // called to forcibly clear the queue
- template <typename MultiPass>
- static void clear_queue(MultiPass& mp)
- {
- mp.shared()->queued_elements.clear();
- mp.queued_position = 0;
- }
- // called to determine whether the iterator is an eof iterator
- template <typename MultiPass>
- static bool is_eof(MultiPass const& mp)
- {
- return mp.queued_position == mp.shared()->queued_elements.size()
- && MultiPass::input_at_eof(mp);
- }
- // called by operator==
- template <typename MultiPass>
- static bool equal_to(MultiPass const& mp, MultiPass const& x)
- {
- return mp.queued_position == x.queued_position;
- }
- // called by operator<
- template <typename MultiPass>
- static bool less_than(MultiPass const& mp, MultiPass const& x)
- {
- return mp.queued_position < x.queued_position;
- }
- template <typename MultiPass>
- static void destroy(MultiPass&) {}
- protected:
- mutable typename queue_type::size_type queued_position;
- };
- ///////////////////////////////////////////////////////////////////////
- template <typename Value>
- struct shared
- {
- shared()
- {
- queued_elements.reserve(threshold);
- }
- typedef std::vector<Value> queue_type;
- queue_type queued_elements;
- };
- }; // split_std_deque
- }}}
- #endif
|