Line data Source code
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 : 52 0 : multi_pass() : member_base(static_cast<shared_data_type*>(0)) {} 53 : 54 : explicit multi_pass(T& input) 55 : : member_base(new shared_data_type(input)), policies_base_type(input) {} 56 : 57 0 : explicit multi_pass(T const& input) 58 0 : : member_base(new shared_data_type(input)), policies_base_type(input) {} 59 : 60 0 : multi_pass(multi_pass const& x) 61 0 : : member_base(x.member), policies_base_type(x) 62 : { 63 0 : 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. 73 : multi_pass(int) : member_base(static_cast<shared_data_type*>(0)) {} 74 : #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514) 75 : 76 0 : ~multi_pass() 77 : { 78 0 : if (policies_base_type::release(*this)) { 79 0 : policies_base_type::destroy(*this); 80 0 : delete this->member; 81 : } 82 0 : } 83 : 84 0 : multi_pass& operator=(multi_pass const& x) 85 : { 86 0 : if (this != &x) { 87 0 : multi_pass temp(x); 88 0 : temp.swap(*this); 89 : } 90 0 : return *this; 91 : } 92 : 93 0 : void swap(multi_pass& x) 94 : { 95 0 : boost::swap(this->member, x.member); 96 0 : this->policies_base_type::swap(x); 97 : } 98 : 99 0 : reference operator*() const 100 : { 101 0 : policies_base_type::docheck(*this); 102 0 : return policies_base_type::dereference(*this); 103 : } 104 : pointer operator->() const 105 : { 106 : return &(operator*()); 107 : } 108 : 109 0 : multi_pass& operator++() 110 : { 111 0 : policies_base_type::docheck(*this); 112 0 : policies_base_type::increment(*this); 113 0 : return *this; 114 : } 115 : multi_pass operator++(int) 116 : { 117 : multi_pass tmp(*this); 118 : ++*this; 119 : return tmp; 120 : } 121 : 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 : } 128 : bool inhibit_clear_queue() const 129 : { 130 : return this->member->inhibit_clear_queue_; 131 : } 132 : void inhibit_clear_queue(bool flag) 133 : { 134 : this->member->inhibit_clear_queue_ = flag; 135 : } 136 : 137 0 : bool operator==(multi_pass const& y) const 138 : { 139 0 : if (is_eof()) 140 0 : return y.is_eof(); 141 0 : if (y.is_eof()) 142 : return false; 143 : 144 0 : return policies_base_type::equal_to(*this, y); 145 : } 146 : bool operator<(multi_pass const& y) const 147 : { 148 : return policies_base_type::less_than(*this, y); 149 : } 150 : 151 0 : bool operator!=(multi_pass const& y) const 152 : { 153 0 : return !(*this == y); 154 : } 155 : bool operator>(multi_pass const& y) const 156 : { 157 : return y < *this; 158 : } 159 : bool operator>=(multi_pass const& y) const 160 : { 161 : return !(*this < y); 162 : } 163 : bool operator<=(multi_pass const& y) const 164 : { 165 : return !(y < *this); 166 : } 167 : 168 : // allow access to base member 169 0 : shared_data_type* shared() const { return this->member; } 170 : 171 : private: // helper functions 172 0 : bool is_eof() const 173 : { 174 0 : 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> 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> 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> 197 : make_default_multi_pass(T& i) 198 : { 199 : return multi_pass<T>(i); 200 : } 201 : template <typename T> 202 : inline multi_pass<T> 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 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> 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> 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> 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 :