multi_pass.hpp 7.7 KB

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