]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
37 | 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 | ||
57 | 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 | ||
74 | 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 | ||
109 | regex_iterator() | |
110 | : impl_() | |
111 | { | |
112 | } | |
113 | ||
114 | 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> | |
131 | 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 | ||
149 | regex_iterator(regex_iterator<BidiIter> const &that) | |
150 | : impl_(that.impl_) // COW | |
151 | { | |
152 | } | |
153 | ||
154 | regex_iterator<BidiIter> &operator =(regex_iterator<BidiIter> const &that) | |
155 | { | |
156 | this->impl_ = that.impl_; // COW | |
157 | return *this; | |
158 | } | |
159 | ||
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 | ||
170 | friend bool operator !=(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right) | |
171 | { | |
172 | return !(left == right); | |
173 | } | |
174 | ||
175 | value_type const &operator *() const | |
176 | { | |
177 | return this->impl_->what_; | |
178 | } | |
179 | ||
180 | 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. | |
207 | regex_iterator<BidiIter> &operator ++() | |
208 | { | |
209 | this->fork_(); // un-share the implementation | |
210 | this->next_(); | |
211 | return *this; | |
212 | } | |
213 | ||
214 | 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 | |
224 | 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 | |
246 | 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 |