Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file regex_iterator.hpp Chris@16: /// Contains the definition of the regex_iterator type, an STL-compatible iterator Chris@16: /// for stepping through all the matches in a sequence. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_REGEX_ITERATOR_HPP_EAN_10_04_2005 Chris@16: #define BOOST_XPRESSIVE_REGEX_ITERATOR_HPP_EAN_10_04_2005 Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace xpressive { namespace detail Chris@16: { Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: // regex_iterator_impl Chris@16: // Chris@16: template Chris@16: struct regex_iterator_impl Chris@16: : counted_base > Chris@16: { Chris@16: typedef detail::core_access access; Chris@16: Chris@16: regex_iterator_impl Chris@16: ( Chris@16: BidiIter begin Chris@16: , BidiIter cur Chris@16: , BidiIter end Chris@16: , BidiIter next_search Chris@16: , basic_regex const &rex Chris@16: , regex_constants::match_flag_type flags Chris@16: , bool not_null = false Chris@16: ) Chris@16: : rex_(rex) Chris@16: , what_() Chris@16: , state_(begin, end, what_, *access::get_regex_impl(rex_), flags) Chris@16: , flags_(flags) Chris@16: , not_null_(not_null) Chris@16: { Chris@16: this->state_.cur_ = cur; Chris@16: this->state_.next_search_ = next_search; Chris@16: } Chris@16: Chris@16: bool next() Chris@16: { Chris@16: this->state_.reset(this->what_, *access::get_regex_impl(this->rex_)); Chris@16: if(!regex_search_impl(this->state_, this->rex_, this->not_null_)) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: // Report position() correctly by setting the base different from prefix().first Chris@16: access::set_base(this->what_, this->state_.begin_); Chris@16: Chris@16: this->state_.cur_ = this->state_.next_search_ = this->what_[0].second; Chris@16: this->not_null_ = (0 == this->what_.length()); Chris@16: Chris@16: return true; Chris@16: } Chris@16: Chris@16: bool equal_to(regex_iterator_impl const &that) const Chris@16: { Chris@16: return this->rex_.regex_id() == that.rex_.regex_id() Chris@16: && this->state_.begin_ == that.state_.begin_ Chris@16: && this->state_.cur_ == that.state_.cur_ Chris@16: && this->state_.end_ == that.state_.end_ Chris@16: && this->flags_ == that.flags_ Chris@16: ; Chris@16: } Chris@16: Chris@16: basic_regex rex_; Chris@16: match_results what_; Chris@16: match_state state_; Chris@16: regex_constants::match_flag_type const flags_; Chris@16: bool not_null_; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: // regex_iterator Chris@16: // Chris@16: template Chris@16: struct regex_iterator Chris@16: { Chris@16: typedef basic_regex regex_type; Chris@16: typedef match_results value_type; Chris@16: typedef typename iterator_difference::type difference_type; Chris@16: typedef value_type const *pointer; Chris@16: typedef value_type const &reference; Chris@16: typedef std::forward_iterator_tag iterator_category; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef detail::regex_iterator_impl impl_type_; Chris@16: Chris@16: regex_iterator() Chris@16: : impl_() Chris@16: { Chris@16: } Chris@16: Chris@16: regex_iterator Chris@16: ( Chris@16: BidiIter begin Chris@16: , BidiIter end Chris@16: , basic_regex const &rex Chris@16: , regex_constants::match_flag_type flags = regex_constants::match_default Chris@16: ) Chris@16: : impl_() Chris@16: { Chris@16: if(0 != rex.regex_id()) // Empty regexes are guaranteed to match nothing Chris@16: { Chris@16: this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags); Chris@16: this->next_(); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: regex_iterator Chris@16: ( Chris@16: BidiIter begin Chris@16: , BidiIter end Chris@16: , basic_regex const &rex Chris@16: , detail::let_ const &args Chris@16: , regex_constants::match_flag_type flags = regex_constants::match_default Chris@16: ) Chris@16: : impl_() Chris@16: { Chris@16: if(0 != rex.regex_id()) // Empty regexes are guaranteed to match nothing Chris@16: { Chris@16: this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags); Chris@16: detail::bind_args(args, this->impl_->what_); Chris@16: this->next_(); Chris@16: } Chris@16: } Chris@16: Chris@16: regex_iterator(regex_iterator const &that) Chris@16: : impl_(that.impl_) // COW Chris@16: { Chris@16: } Chris@16: Chris@16: regex_iterator &operator =(regex_iterator const &that) Chris@16: { Chris@16: this->impl_ = that.impl_; // COW Chris@16: return *this; Chris@16: } Chris@16: Chris@16: friend bool operator ==(regex_iterator const &left, regex_iterator const &right) Chris@16: { Chris@16: if(!left.impl_ || !right.impl_) Chris@16: { Chris@16: return !left.impl_ && !right.impl_; Chris@16: } Chris@16: Chris@16: return left.impl_->equal_to(*right.impl_); Chris@16: } Chris@16: Chris@16: friend bool operator !=(regex_iterator const &left, regex_iterator const &right) Chris@16: { Chris@16: return !(left == right); Chris@16: } Chris@16: Chris@16: value_type const &operator *() const Chris@16: { Chris@16: return this->impl_->what_; Chris@16: } Chris@16: Chris@16: value_type const *operator ->() const Chris@16: { Chris@16: return &this->impl_->what_; Chris@16: } Chris@16: Chris@16: /// If what.prefix().first != what[0].second and if the element match_prev_avail is not set in Chris@16: /// flags then sets it. Then behaves as if by calling regex_search(what[0].second, end, what, *pre, flags), Chris@16: /// with the following variation: in the event that the previous match found was of zero length Chris@16: /// (what[0].length() == 0) then attempts to find a non-zero length match starting at what[0].second, Chris@16: /// only if that fails and provided what[0].second != suffix().second does it look for a (possibly Chris@16: /// zero length) match starting from what[0].second + 1. If no further match is found then sets Chris@16: /// *this equal to the end of sequence iterator. Chris@16: /// \post (*this)-\>size() == pre-\>mark_count() + 1 Chris@16: /// \post (*this)-\>empty() == false Chris@16: /// \post (*this)-\>prefix().first == An iterator denoting the end point of the previous match found Chris@16: /// \post (*this)-\>prefix().last == (**this)[0].first Chris@16: /// \post (*this)-\>prefix().matched == (*this)-\>prefix().first != (*this)-\>prefix().second Chris@16: /// \post (*this)-\>suffix().first == (**this)[0].second Chris@16: /// \post (*this)-\>suffix().last == end Chris@16: /// \post (*this)-\>suffix().matched == (*this)-\>suffix().first != (*this)-\>suffix().second Chris@16: /// \post (**this)[0].first == The starting iterator for this match. Chris@16: /// \post (**this)[0].second == The ending iterator for this match. Chris@16: /// \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). Chris@16: /// \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. Chris@16: /// \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. Chris@16: /// \post (**this)[n].matched == For all integers n \< (*this)-\>size(), true if sub-expression n participated in the match, false otherwise. Chris@16: /// \post (*this)-\>position() == The distance from the start of the original sequence being iterated, to the start of this match. Chris@16: regex_iterator &operator ++() Chris@16: { Chris@16: this->fork_(); // un-share the implementation Chris@16: this->next_(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: regex_iterator operator ++(int) Chris@16: { Chris@16: regex_iterator tmp(*this); Chris@16: ++*this; Chris@16: return tmp; Chris@16: } Chris@16: Chris@16: private: Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: void fork_() Chris@16: { Chris@16: if(1 != this->impl_->use_count()) Chris@16: { Chris@16: // This is OK, the use_count is > 1 Chris@16: impl_type_ *that = this->impl_.get(); Chris@16: this->impl_ = new impl_type_ Chris@16: ( Chris@16: that->state_.begin_ Chris@16: , that->state_.cur_ Chris@16: , that->state_.end_ Chris@16: , that->state_.next_search_ Chris@16: , that->rex_ Chris@16: , that->flags_ Chris@16: , that->not_null_ Chris@16: ); Chris@16: detail::core_access::get_action_args(this->impl_->what_) Chris@16: = detail::core_access::get_action_args(that->what_); Chris@16: } Chris@16: } Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: void next_() Chris@16: { Chris@16: BOOST_ASSERT(this->impl_ && 1 == this->impl_->use_count()); Chris@16: if(!this->impl_->next()) Chris@16: { Chris@16: this->impl_ = 0; Chris@16: } Chris@16: } Chris@16: Chris@16: intrusive_ptr impl_; Chris@16: }; Chris@16: Chris@16: }} // namespace boost::xpressive Chris@16: Chris@16: #endif