Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/xpressive/regex_iterator.hpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 7.5 KB
Line 
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 2004 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) && (_MSC_VER >= 1020)
15# pragma once
16#endif
17
18#include <boost/noncopyable.hpp>
19#include <boost/iterator/iterator_traits.hpp>
20#include <boost/xpressive/detail/detail_fwd.hpp>
21#include <boost/xpressive/detail/core/access.hpp>
22
23namespace boost { namespace xpressive { namespace detail
24{
25
26//////////////////////////////////////////////////////////////////////////
27// regex_iterator_impl
28//
29template<typename BidiIter>
30struct regex_iterator_impl
31  : private noncopyable
32{
33    typedef detail::core_access<BidiIter> access;
34
35    regex_iterator_impl
36    (
37        BidiIter begin
38      , BidiIter cur
39      , BidiIter end
40      , basic_regex<BidiIter> const *rex
41      , regex_constants::match_flag_type flags
42      , bool not_null = false
43    )
44      : what_()
45      , state_(begin, end, what_, *access::get_regex_impl(*rex), flags)
46      , rex_(rex)
47      , flags_(flags)
48      , not_null_(not_null)
49    {
50        this->state_.cur_ = cur;
51    }
52
53    bool next()
54    {
55        this->state_.reset(this->what_, *access::get_regex_impl(*this->rex_));
56        if(!regex_search_impl(this->state_, *this->rex_, this->not_null_))
57        {
58            return false;
59        }
60
61        // Report position() correctly by setting the base different from prefix().first
62        access::set_base(this->what_, this->state_.begin_);
63
64        this->state_.cur_ = this->what_[0].second;
65        this->not_null_ = (0 == this->what_.length());
66
67        return true;
68    }
69
70    bool equal_to(regex_iterator_impl<BidiIter> const &that) const
71    {
72        return this->rex_           == that.rex_
73            && this->state_.begin_  == that.state_.begin_
74            && this->state_.cur_    == that.state_.cur_
75            && this->state_.end_    == that.state_.end_
76            && this->flags_         == that.flags_
77            ;
78    }
79
80    match_results<BidiIter> what_;
81    state_type<BidiIter> state_;
82    basic_regex<BidiIter> const *const rex_;
83    regex_constants::match_flag_type const flags_;
84    bool not_null_;
85};
86
87} // namespace detail
88
89//////////////////////////////////////////////////////////////////////////
90// regex_iterator
91//
92template<typename BidiIter>
93struct regex_iterator
94{
95    typedef basic_regex<BidiIter> regex_type;
96    typedef match_results<BidiIter> value_type;
97    typedef typename iterator_difference<BidiIter>::type difference_type;
98    typedef value_type const *pointer;
99    typedef value_type const &reference;
100    typedef std::forward_iterator_tag iterator_category;
101
102    /// INTERNAL ONLY
103    typedef detail::regex_iterator_impl<BidiIter> impl_type_;
104
105    regex_iterator()
106      : impl_()
107    {
108    }
109
110    regex_iterator
111    (
112        BidiIter begin
113      , BidiIter end
114      , basic_regex<BidiIter> const &rex
115      , regex_constants::match_flag_type flags = regex_constants::match_default
116    )
117      : impl_(new impl_type_(begin, begin, end, &rex, flags))
118    {
119        this->next_();
120    }
121
122    regex_iterator(regex_iterator<BidiIter> const &that)
123      : impl_(that.impl_) // COW
124    {
125    }
126
127    regex_iterator<BidiIter> &operator =(regex_iterator<BidiIter> const &that)
128    {
129        this->impl_ = that.impl_; // COW
130        return *this;
131    }
132
133    friend bool operator ==(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right)
134    {
135        if(!left.impl_ || !right.impl_)
136        {
137            return !left.impl_ && !right.impl_;
138        }
139
140        return left.impl_->equal_to(*right.impl_);
141    }
142
143    friend bool operator !=(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right)
144    {
145        return !(left == right);
146    }
147
148    value_type const &operator *() const
149    {
150        return this->impl_->what_;
151    }
152
153    value_type const *operator ->() const
154    {
155        return &this->impl_->what_;
156    }
157
158    /// If what.prefix().first != what[0].second and if the element match_prev_avail is not set in
159    /// flags then sets it. Then behaves as if by calling regex_search(what[0].second, end, what, *pre, flags),
160    /// with the following variation: in the event that the previous match found was of zero length
161    /// (what[0].length() == 0) then attempts to find a non-zero length match starting at what[0].second,
162    /// only if that fails and provided what[0].second != suffix().second does it look for a (possibly
163    /// zero length) match starting from what[0].second + 1.  If no further match is found then sets
164    /// *this equal to the end of sequence iterator.
165    /// \post (*this)-\>size() == pre-\>mark_count()
166    /// \post (*this)-\>empty() == false
167    /// \post (*this)-\>prefix().first == An iterator denoting the end point of the previous match found
168    /// \post (*this)-\>prefix().last == (**this)[0].first
169    /// \post (*this)-\>prefix().matched == (*this)-\>prefix().first != (*this)-\>prefix().second
170    /// \post (*this)-\>suffix().first == (**this)[0].second
171    /// \post (*this)-\>suffix().last == end
172    /// \post (*this)-\>suffix().matched == (*this)-\>suffix().first != (*this)-\>suffix().second
173    /// \post (**this)[0].first == The starting iterator for this match.
174    /// \post (**this)[0].second == The ending iterator for this match.
175    /// \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).
176    /// \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.
177    /// \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.
178    /// \post (**this)[n].matched == For all integers n \< (*this)-\>size(), true if sub-expression n participated in the match, false otherwise.
179    /// \post (*this)-\>position() == The distance from the start of the original sequence being iterated, to the start of this match.
180    regex_iterator<BidiIter> &operator ++()
181    {
182        this->fork_(); // un-share the implementation
183        this->next_();
184        return *this;
185    }
186
187    regex_iterator<BidiIter> operator ++(int)
188    {
189        regex_iterator<BidiIter> tmp(*this);
190        ++*this;
191        return tmp;
192    }
193
194private:
195
196    /// INTERNAL ONLY
197    void fork_()
198    {
199        if(!this->impl_.unique())
200        {
201            this->impl_.reset
202            (
203                new impl_type_
204                (
205                    this->impl_->state_.begin_
206                  , this->impl_->state_.cur_
207                  , this->impl_->state_.end_
208                  , this->impl_->rex_
209                  , this->impl_->flags_
210                  , this->impl_->not_null_
211                )
212            );
213        }
214    }
215
216    /// INTERNAL ONLY
217    void next_()
218    {
219        BOOST_ASSERT(this->impl_ && this->impl_.unique());
220        if(!this->impl_->next())
221        {
222            this->impl_.reset();
223        }
224    }
225
226    shared_ptr<impl_type_> impl_;
227};
228
229}} // namespace boost::xpressive
230
231#endif
Note: See TracBrowser for help on using the repository browser.