split_std_deque_policy.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (c) 2001 Daniel C. Nuffer
  2. // Copyright (c) 2001-2011 Hartmut Kaiser
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM)
  7. #define BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM
  8. #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
  9. #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
  10. #include <boost/assert.hpp>
  11. #include <vector>
  12. namespace boost { namespace spirit { namespace iterator_policies
  13. {
  14. ///////////////////////////////////////////////////////////////////////////
  15. // class split_std_deque
  16. //
  17. // Implementation of the StoragePolicy used by multi_pass
  18. // This stores all data in a std::vector (despite its name), and keeps an
  19. // offset to the current position. It stores all the data unless there is
  20. // only one iterator using the queue.
  21. //
  22. ///////////////////////////////////////////////////////////////////////////
  23. struct split_std_deque
  24. {
  25. enum { threshold = 16 };
  26. ///////////////////////////////////////////////////////////////////////
  27. template <typename Value>
  28. class unique //: public detail::default_storage_policy
  29. {
  30. private:
  31. typedef std::vector<Value> queue_type;
  32. protected:
  33. unique() : queued_position(0) {}
  34. unique(unique const& x)
  35. : queued_position(x.queued_position) {}
  36. void swap(unique& x)
  37. {
  38. boost::swap(queued_position, x.queued_position);
  39. }
  40. // This is called when the iterator is dereferenced. It's a
  41. // template method so we can recover the type of the multi_pass
  42. // iterator and call advance_input and input_is_valid.
  43. template <typename MultiPass>
  44. static typename MultiPass::reference
  45. dereference(MultiPass const& mp)
  46. {
  47. queue_type& queue = mp.shared()->queued_elements;
  48. typename queue_type::size_type size = queue.size();
  49. BOOST_ASSERT(mp.queued_position <= size);
  50. if (mp.queued_position == size)
  51. {
  52. // check if this is the only iterator
  53. if (size >= threshold && MultiPass::is_unique(mp))
  54. {
  55. // free up the memory used by the queue.
  56. queue.clear();
  57. mp.queued_position = 0;
  58. }
  59. return MultiPass::get_input(mp);
  60. }
  61. return queue[mp.queued_position];
  62. }
  63. // This is called when the iterator is incremented. It's a template
  64. // method so we can recover the type of the multi_pass iterator
  65. // and call is_unique and advance_input.
  66. template <typename MultiPass>
  67. static void increment(MultiPass& mp)
  68. {
  69. queue_type& queue = mp.shared()->queued_elements;
  70. typename queue_type::size_type size = queue.size();
  71. BOOST_ASSERT(mp.queued_position <= size);
  72. // // do not increment iterator as long as the current token is
  73. // // invalid
  74. // if (size > 0 && !MultiPass::input_is_valid(mp, queue[mp.queued_position-1]))
  75. // return;
  76. if (mp.queued_position == size)
  77. {
  78. // check if this is the only iterator
  79. if (size >= threshold && MultiPass::is_unique(mp))
  80. {
  81. // free up the memory used by the queue. we avoid
  82. // clearing the queue on every increment, though,
  83. // because this would be too time consuming
  84. queue.clear();
  85. mp.queued_position = 0;
  86. }
  87. else
  88. {
  89. queue.push_back(MultiPass::get_input(mp));
  90. ++mp.queued_position;
  91. }
  92. MultiPass::advance_input(mp);
  93. }
  94. else
  95. {
  96. ++mp.queued_position;
  97. }
  98. }
  99. // called to forcibly clear the queue
  100. template <typename MultiPass>
  101. static void clear_queue(MultiPass& mp)
  102. {
  103. mp.shared()->queued_elements.clear();
  104. mp.queued_position = 0;
  105. }
  106. // called to determine whether the iterator is an eof iterator
  107. template <typename MultiPass>
  108. static bool is_eof(MultiPass const& mp)
  109. {
  110. return mp.queued_position == mp.shared()->queued_elements.size()
  111. && MultiPass::input_at_eof(mp);
  112. }
  113. // called by operator==
  114. template <typename MultiPass>
  115. static bool equal_to(MultiPass const& mp, MultiPass const& x)
  116. {
  117. return mp.queued_position == x.queued_position;
  118. }
  119. // called by operator<
  120. template <typename MultiPass>
  121. static bool less_than(MultiPass const& mp, MultiPass const& x)
  122. {
  123. return mp.queued_position < x.queued_position;
  124. }
  125. template <typename MultiPass>
  126. static void destroy(MultiPass&) {}
  127. protected:
  128. mutable typename queue_type::size_type queued_position;
  129. };
  130. ///////////////////////////////////////////////////////////////////////
  131. template <typename Value>
  132. struct shared
  133. {
  134. shared()
  135. {
  136. queued_elements.reserve(threshold);
  137. }
  138. typedef std::vector<Value> queue_type;
  139. queue_type queued_elements;
  140. };
  141. }; // split_std_deque
  142. }}}
  143. #endif