fixed_size_queue_policy.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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_FIXED_SIZE_QUEUE_POLICY_MAR_16_2007_1134AM)
  7. #define BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_POLICY_MAR_16_2007_1134AM
  8. #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
  9. #include <boost/spirit/home/support/iterators/detail/fixed_size_queue.hpp>
  10. #include <boost/assert.hpp>
  11. #include <cstdlib>
  12. namespace boost { namespace spirit { namespace iterator_policies
  13. {
  14. ///////////////////////////////////////////////////////////////////////////
  15. // class fixed_size_queue
  16. // Implementation of the StoragePolicy used by multi_pass
  17. // fixed_size_queue keeps a circular buffer (implemented by
  18. // boost::spirit::fixed_size_queue class) that is size N+1 and stores N
  19. // elements.
  20. //
  21. // It is up to the user to ensure that there is enough look ahead for
  22. // their grammar. Currently there is no way to tell if an iterator is
  23. // pointing to forgotten data. The leading iterator will put an item in
  24. // the queue and remove one when it is incremented. No dynamic allocation
  25. // is done, except on creation of the queue (fixed_size_queue constructor).
  26. ///////////////////////////////////////////////////////////////////////////
  27. template <std::size_t N>
  28. struct fixed_size_queue
  29. {
  30. ///////////////////////////////////////////////////////////////////////
  31. template <typename Value>
  32. class unique : public detail::default_storage_policy
  33. {
  34. private:
  35. typedef detail::fixed_size_queue<Value, N> queue_type;
  36. protected:
  37. unique() {}
  38. unique(unique const& x)
  39. : queued_position(x.queued_position) {}
  40. void swap(unique& x)
  41. {
  42. boost::swap(queued_position, x.queued_position);
  43. }
  44. // This is called when the iterator is dereferenced. It's a
  45. // template method so we can recover the type of the multi_pass
  46. // iterator and access the m_input data member.
  47. template <typename MultiPass>
  48. static typename MultiPass::reference
  49. dereference(MultiPass const& mp)
  50. {
  51. if (!mp.queued_position.get_position().is_initialized())
  52. mp.queued_position.get_position().set_queue(&mp.shared()->queued_elements);
  53. if (mp.queued_position == mp.shared()->queued_elements.end())
  54. return MultiPass::get_input(mp);
  55. return *mp.queued_position;
  56. }
  57. // This is called when the iterator is incremented. It's a
  58. // template method so we can recover the type of the multi_pass
  59. // iterator and access the m_input data member.
  60. template <typename MultiPass>
  61. static void increment(MultiPass& mp)
  62. {
  63. if (!mp.queued_position.get_position().is_initialized())
  64. mp.queued_position.get_position().set_queue(&mp.shared()->queued_elements);
  65. if (mp.queued_position == mp.shared()->queued_elements.end())
  66. {
  67. // don't let the queue get larger than N
  68. if (mp.shared()->queued_elements.size() >= N)
  69. mp.shared()->queued_elements.pop_front();
  70. mp.shared()->queued_elements.push_back(
  71. MultiPass::get_input(mp));
  72. MultiPass::advance_input(mp);
  73. }
  74. ++mp.queued_position;
  75. }
  76. // clear_queue is a no-op
  77. // called to determine whether the iterator is an eof iterator
  78. template <typename MultiPass>
  79. static bool is_eof(MultiPass const& mp)
  80. {
  81. return mp.queued_position == mp.shared()->queued_elements.end() &&
  82. MultiPass::input_at_eof(mp);
  83. }
  84. // called by operator==
  85. template <typename MultiPass>
  86. static bool equal_to(MultiPass const& mp, MultiPass const& x)
  87. {
  88. return mp.queued_position == x.queued_position;
  89. }
  90. // called by operator<
  91. template <typename MultiPass>
  92. static bool less_than(MultiPass const& mp, MultiPass const& x)
  93. {
  94. return mp.queued_position < x.queued_position;
  95. }
  96. protected:
  97. mutable typename queue_type::iterator queued_position;
  98. };
  99. ///////////////////////////////////////////////////////////////////////
  100. template <typename Value>
  101. struct shared
  102. {
  103. typedef detail::fixed_size_queue<Value, N> queue_type;
  104. queue_type queued_elements;
  105. };
  106. };
  107. }}}
  108. #endif