1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file regex_iterator.hpp 3 /// Contains the definition of the regex_iterator type, an STL-compatible iterator 4 /// for stepping through all the matches in a sequence. 5 // 6 // Copyright 2008 Eric Niebler. Distributed under the Boost 7 // Software License, Version 1.0. (See accompanying file 8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 10 #ifndef BOOST_XPRESSIVE_REGEX_ITERATOR_HPP_EAN_10_04_2005 11 #define BOOST_XPRESSIVE_REGEX_ITERATOR_HPP_EAN_10_04_2005 12 13 // MS compatible compilers support #pragma once 14 #if defined(_MSC_VER) 15 # pragma once 16 #endif 17 18 #include <boost/noncopyable.hpp> 19 #include <boost/intrusive_ptr.hpp> 20 #include <boost/iterator/iterator_traits.hpp> 21 #include <boost/xpressive/detail/detail_fwd.hpp> 22 #include <boost/xpressive/detail/core/access.hpp> 23 #include <boost/xpressive/detail/utility/counted_base.hpp> 24 25 namespace boost { namespace xpressive { namespace detail 26 { 27 28 ////////////////////////////////////////////////////////////////////////// 29 // regex_iterator_impl 30 // 31 template<typename BidiIter> 32 struct regex_iterator_impl 33 : counted_base<regex_iterator_impl<BidiIter> > 34 { 35 typedef detail::core_access<BidiIter> access; 36 regex_iterator_implboost::xpressive::detail::regex_iterator_impl37 regex_iterator_impl 38 ( 39 BidiIter begin 40 , BidiIter cur 41 , BidiIter end 42 , BidiIter next_search 43 , basic_regex<BidiIter> const &rex 44 , regex_constants::match_flag_type flags 45 , bool not_null = false 46 ) 47 : rex_(rex) 48 , what_() 49 , state_(begin, end, what_, *access::get_regex_impl(rex_), flags) 50 , flags_(flags) 51 , not_null_(not_null) 52 { 53 this->state_.cur_ = cur; 54 this->state_.next_search_ = next_search; 55 } 56 nextboost::xpressive::detail::regex_iterator_impl57 bool next() 58 { 59 this->state_.reset(this->what_, *access::get_regex_impl(this->rex_)); 60 if(!regex_search_impl(this->state_, this->rex_, this->not_null_)) 61 { 62 return false; 63 } 64 65 // Report position() correctly by setting the base different from prefix().first 66 access::set_base(this->what_, this->state_.begin_); 67 68 this->state_.cur_ = this->state_.next_search_ = this->what_[0].second; 69 this->not_null_ = (0 == this->what_.length()); 70 71 return true; 72 } 73 equal_toboost::xpressive::detail::regex_iterator_impl74 bool equal_to(regex_iterator_impl<BidiIter> const &that) const 75 { 76 return this->rex_.regex_id() == that.rex_.regex_id() 77 && this->state_.begin_ == that.state_.begin_ 78 && this->state_.cur_ == that.state_.cur_ 79 && this->state_.end_ == that.state_.end_ 80 && this->flags_ == that.flags_ 81 ; 82 } 83 84 basic_regex<BidiIter> rex_; 85 match_results<BidiIter> what_; 86 match_state<BidiIter> state_; 87 regex_constants::match_flag_type const flags_; 88 bool not_null_; 89 }; 90 91 } // namespace detail 92 93 ////////////////////////////////////////////////////////////////////////// 94 // regex_iterator 95 // 96 template<typename BidiIter> 97 struct regex_iterator 98 { 99 typedef basic_regex<BidiIter> regex_type; 100 typedef match_results<BidiIter> value_type; 101 typedef typename iterator_difference<BidiIter>::type difference_type; 102 typedef value_type const *pointer; 103 typedef value_type const &reference; 104 typedef std::forward_iterator_tag iterator_category; 105 106 /// INTERNAL ONLY 107 typedef detail::regex_iterator_impl<BidiIter> impl_type_; 108 regex_iteratorboost::xpressive::regex_iterator109 regex_iterator() 110 : impl_() 111 { 112 } 113 regex_iteratorboost::xpressive::regex_iterator114 regex_iterator 115 ( 116 BidiIter begin 117 , BidiIter end 118 , basic_regex<BidiIter> const &rex 119 , regex_constants::match_flag_type flags = regex_constants::match_default 120 ) 121 : impl_() 122 { 123 if(0 != rex.regex_id()) // Empty regexes are guaranteed to match nothing 124 { 125 this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags); 126 this->next_(); 127 } 128 } 129 130 template<typename LetExpr> regex_iteratorboost::xpressive::regex_iterator131 regex_iterator 132 ( 133 BidiIter begin 134 , BidiIter end 135 , basic_regex<BidiIter> const &rex 136 , detail::let_<LetExpr> const &args 137 , regex_constants::match_flag_type flags = regex_constants::match_default 138 ) 139 : impl_() 140 { 141 if(0 != rex.regex_id()) // Empty regexes are guaranteed to match nothing 142 { 143 this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags); 144 detail::bind_args(args, this->impl_->what_); 145 this->next_(); 146 } 147 } 148 regex_iteratorboost::xpressive::regex_iterator149 regex_iterator(regex_iterator<BidiIter> const &that) 150 : impl_(that.impl_) // COW 151 { 152 } 153 operator =boost::xpressive::regex_iterator154 regex_iterator<BidiIter> &operator =(regex_iterator<BidiIter> const &that) 155 { 156 this->impl_ = that.impl_; // COW 157 return *this; 158 } 159 operator ==(regex_iterator<BidiIter> const & left,regex_iterator<BidiIter> const & right)160 friend bool operator ==(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right) 161 { 162 if(!left.impl_ || !right.impl_) 163 { 164 return !left.impl_ && !right.impl_; 165 } 166 167 return left.impl_->equal_to(*right.impl_); 168 } 169 operator !=(regex_iterator<BidiIter> const & left,regex_iterator<BidiIter> const & right)170 friend bool operator !=(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right) 171 { 172 return !(left == right); 173 } 174 operator *boost::xpressive::regex_iterator175 value_type const &operator *() const 176 { 177 return this->impl_->what_; 178 } 179 operator ->boost::xpressive::regex_iterator180 value_type const *operator ->() const 181 { 182 return &this->impl_->what_; 183 } 184 185 /// If what.prefix().first != what[0].second and if the element match_prev_avail is not set in 186 /// flags then sets it. Then behaves as if by calling regex_search(what[0].second, end, what, *pre, flags), 187 /// with the following variation: in the event that the previous match found was of zero length 188 /// (what[0].length() == 0) then attempts to find a non-zero length match starting at what[0].second, 189 /// only if that fails and provided what[0].second != suffix().second does it look for a (possibly 190 /// zero length) match starting from what[0].second + 1. If no further match is found then sets 191 /// *this equal to the end of sequence iterator. 192 /// \post (*this)-\>size() == pre-\>mark_count() + 1 193 /// \post (*this)-\>empty() == false 194 /// \post (*this)-\>prefix().first == An iterator denoting the end point of the previous match found 195 /// \post (*this)-\>prefix().last == (**this)[0].first 196 /// \post (*this)-\>prefix().matched == (*this)-\>prefix().first != (*this)-\>prefix().second 197 /// \post (*this)-\>suffix().first == (**this)[0].second 198 /// \post (*this)-\>suffix().last == end 199 /// \post (*this)-\>suffix().matched == (*this)-\>suffix().first != (*this)-\>suffix().second 200 /// \post (**this)[0].first == The starting iterator for this match. 201 /// \post (**this)[0].second == The ending iterator for this match. 202 /// \post (**this)[0].matched == true if a full match was found, and false if it was a partial match (found as a result of the match_partial flag being set). 203 /// \post (**this)[n].first == For all integers n \< (*this)-\>size(), the start of the sequence that matched sub-expression n. Alternatively, if sub-expression n did not participate in the match, then end. 204 /// \post (**this)[n].second == For all integers n \< (*this)-\>size(), the end of the sequence that matched sub-expression n. Alternatively, if sub-expression n did not participate in the match, then end. 205 /// \post (**this)[n].matched == For all integers n \< (*this)-\>size(), true if sub-expression n participated in the match, false otherwise. 206 /// \post (*this)-\>position() == The distance from the start of the original sequence being iterated, to the start of this match. operator ++boost::xpressive::regex_iterator207 regex_iterator<BidiIter> &operator ++() 208 { 209 this->fork_(); // un-share the implementation 210 this->next_(); 211 return *this; 212 } 213 operator ++boost::xpressive::regex_iterator214 regex_iterator<BidiIter> operator ++(int) 215 { 216 regex_iterator<BidiIter> tmp(*this); 217 ++*this; 218 return tmp; 219 } 220 221 private: 222 223 /// INTERNAL ONLY fork_boost::xpressive::regex_iterator224 void fork_() 225 { 226 if(1 != this->impl_->use_count()) 227 { 228 // This is OK, the use_count is > 1 229 impl_type_ *that = this->impl_.get(); 230 this->impl_ = new impl_type_ 231 ( 232 that->state_.begin_ 233 , that->state_.cur_ 234 , that->state_.end_ 235 , that->state_.next_search_ 236 , that->rex_ 237 , that->flags_ 238 , that->not_null_ 239 ); 240 detail::core_access<BidiIter>::get_action_args(this->impl_->what_) 241 = detail::core_access<BidiIter>::get_action_args(that->what_); 242 } 243 } 244 245 /// INTERNAL ONLY next_boost::xpressive::regex_iterator246 void next_() 247 { 248 BOOST_ASSERT(this->impl_ && 1 == this->impl_->use_count()); 249 if(!this->impl_->next()) 250 { 251 this->impl_ = 0; 252 } 253 } 254 255 intrusive_ptr<impl_type_> impl_; 256 }; 257 258 }} // namespace boost::xpressive 259 260 #endif 261