multi_pass.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright (c) 2001, Daniel C. Nuffer
  2. // Copyright (c) 2001-2011 Hartmut Kaiser
  3. // http://spirit.sourceforge.net/
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM)
  8. #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM
  9. #include <boost/config.hpp>
  10. #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
  11. #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
  12. #include <boost/spirit/home/support/iterators/detail/combine_policies.hpp>
  13. #include <boost/limits.hpp>
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/core/invoke_swap.hpp>
  16. #include <boost/utility/base_from_member.hpp>
  17. namespace boost { namespace spirit
  18. {
  19. ///////////////////////////////////////////////////////////////////////////
  20. // The default multi_pass instantiation uses a ref-counted std_deque scheme.
  21. ///////////////////////////////////////////////////////////////////////////
  22. template<typename T, typename Policies>
  23. class multi_pass
  24. : private boost::base_from_member<
  25. typename Policies::BOOST_NESTED_TEMPLATE shared<T>*>
  26. , public Policies::BOOST_NESTED_TEMPLATE unique<T>
  27. {
  28. private:
  29. // unique and shared data types
  30. typedef typename Policies::BOOST_NESTED_TEMPLATE unique<T>
  31. policies_base_type;
  32. typedef typename Policies::BOOST_NESTED_TEMPLATE shared<T>
  33. shared_data_type;
  34. typedef boost::base_from_member<shared_data_type*> member_base;
  35. // define the types the standard embedded iterator typedefs are taken
  36. // from
  37. typedef typename policies_base_type::input_policy iterator_type;
  38. public:
  39. // standard iterator typedefs
  40. typedef std::forward_iterator_tag iterator_category;
  41. typedef typename iterator_type::value_type value_type;
  42. typedef typename iterator_type::difference_type difference_type;
  43. typedef typename iterator_type::distance_type distance_type;
  44. typedef typename iterator_type::reference reference;
  45. typedef typename iterator_type::pointer pointer;
  46. multi_pass() : member_base(static_cast<shared_data_type*>(0)) {}
  47. explicit multi_pass(T& input)
  48. : member_base(new shared_data_type(input)), policies_base_type(input) {}
  49. explicit multi_pass(T const& input)
  50. : member_base(new shared_data_type(input)), policies_base_type(input) {}
  51. multi_pass(multi_pass const& x)
  52. : member_base(x.member), policies_base_type(x)
  53. {
  54. policies_base_type::clone(*this);
  55. }
  56. #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  57. // The standard library shipped with gcc-3.1 has a bug in
  58. // bits/basic_string.tcc. It tries to use iter::iter(0) to
  59. // construct an iterator. Ironically, this happens in sanity
  60. // checking code that isn't required by the standard.
  61. // The workaround is to provide an additional constructor that
  62. // ignores its int argument and behaves like the default constructor.
  63. multi_pass(int) : member_base(static_cast<shared_data_type*>(0)) {}
  64. #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  65. ~multi_pass()
  66. {
  67. if (policies_base_type::release(*this)) {
  68. policies_base_type::destroy(*this);
  69. delete this->member;
  70. }
  71. }
  72. multi_pass& operator=(multi_pass const& x)
  73. {
  74. if (this != &x) {
  75. multi_pass temp(x);
  76. temp.swap(*this);
  77. }
  78. return *this;
  79. }
  80. void swap(multi_pass& x)
  81. {
  82. boost::core::invoke_swap(this->member, x.member);
  83. this->policies_base_type::swap(x);
  84. }
  85. reference operator*() const
  86. {
  87. policies_base_type::docheck(*this);
  88. return policies_base_type::dereference(*this);
  89. }
  90. pointer operator->() const
  91. {
  92. return &(operator*());
  93. }
  94. multi_pass& operator++()
  95. {
  96. policies_base_type::docheck(*this);
  97. policies_base_type::increment(*this);
  98. return *this;
  99. }
  100. multi_pass operator++(int)
  101. {
  102. multi_pass tmp(*this);
  103. ++*this;
  104. return tmp;
  105. }
  106. void clear_queue(BOOST_SCOPED_ENUM(traits::clear_mode) mode =
  107. traits::clear_mode::clear_if_enabled)
  108. {
  109. if (mode == traits::clear_mode::clear_always || !inhibit_clear_queue())
  110. policies_base_type::clear_queue(*this);
  111. }
  112. bool inhibit_clear_queue() const
  113. {
  114. return this->member->inhibit_clear_queue_;
  115. }
  116. void inhibit_clear_queue(bool flag)
  117. {
  118. this->member->inhibit_clear_queue_ = flag;
  119. }
  120. bool operator==(multi_pass const& y) const
  121. {
  122. if (is_eof())
  123. return y.is_eof();
  124. if (y.is_eof())
  125. return false;
  126. return policies_base_type::equal_to(*this, y);
  127. }
  128. bool operator<(multi_pass const& y) const
  129. {
  130. return policies_base_type::less_than(*this, y);
  131. }
  132. bool operator!=(multi_pass const& y) const
  133. {
  134. return !(*this == y);
  135. }
  136. bool operator>(multi_pass const& y) const
  137. {
  138. return y < *this;
  139. }
  140. bool operator>=(multi_pass const& y) const
  141. {
  142. return !(*this < y);
  143. }
  144. bool operator<=(multi_pass const& y) const
  145. {
  146. return !(y < *this);
  147. }
  148. // allow access to base member
  149. shared_data_type* shared() const { return this->member; }
  150. private: // helper functions
  151. bool is_eof() const
  152. {
  153. return (0 == this->member) || policies_base_type::is_eof(*this);
  154. }
  155. };
  156. ///////////////////////////////////////////////////////////////////////////
  157. // Generator function
  158. ///////////////////////////////////////////////////////////////////////////
  159. template <typename Policies, typename T>
  160. inline multi_pass<T, Policies>
  161. make_multi_pass(T& i)
  162. {
  163. return multi_pass<T, Policies>(i);
  164. }
  165. template <typename Policies, typename T>
  166. inline multi_pass<T, Policies>
  167. make_multi_pass(T const& i)
  168. {
  169. return multi_pass<T, Policies>(i);
  170. }
  171. ///////////////////////////////////////////////////////////////////////////
  172. template <typename T>
  173. inline multi_pass<T>
  174. make_default_multi_pass(T& i)
  175. {
  176. return multi_pass<T>(i);
  177. }
  178. template <typename T>
  179. inline multi_pass<T>
  180. make_default_multi_pass(T const& i)
  181. {
  182. return multi_pass<T>(i);
  183. }
  184. ///////////////////////////////////////////////////////////////////////////
  185. template <typename T, typename Policies>
  186. inline void
  187. swap(multi_pass<T, Policies> &x, multi_pass<T, Policies> &y)
  188. {
  189. x.swap(y);
  190. }
  191. ///////////////////////////////////////////////////////////////////////////
  192. // define special functions allowing to integrate any multi_pass iterator
  193. // with expectation points
  194. namespace traits
  195. {
  196. template <typename T, typename Policies>
  197. void clear_queue(multi_pass<T, Policies>& mp
  198. , BOOST_SCOPED_ENUM(traits::clear_mode) mode)
  199. {
  200. mp.clear_queue(mode);
  201. }
  202. template <typename T, typename Policies>
  203. void inhibit_clear_queue(multi_pass<T, Policies>& mp, bool flag)
  204. {
  205. mp.inhibit_clear_queue(flag);
  206. }
  207. template <typename T, typename Policies>
  208. bool inhibit_clear_queue(multi_pass<T, Policies>& mp)
  209. {
  210. return mp.inhibit_clear_queue();
  211. }
  212. }
  213. }} // namespace boost::spirit
  214. #endif