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