1 | // Boost string_algo library find_iterator.hpp header file ---------------------------// |
2 | |
3 | // Copyright Pavol Droba 2002-2004. |
4 | // |
5 | // Distributed under the Boost Software License, Version 1.0. |
6 | // (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | |
9 | // See http://www.boost.org/ for updates, documentation, and revision history. |
10 | |
11 | #ifndef BOOST_STRING_FIND_ITERATOR_HPP |
12 | #define BOOST_STRING_FIND_ITERATOR_HPP |
13 | |
14 | #include <boost/algorithm/string/config.hpp> |
15 | #include <boost/iterator/iterator_facade.hpp> |
16 | #include <boost/iterator/iterator_categories.hpp> |
17 | |
18 | #include <boost/range/iterator_range_core.hpp> |
19 | #include <boost/range/begin.hpp> |
20 | #include <boost/range/end.hpp> |
21 | #include <boost/range/iterator.hpp> |
22 | #include <boost/range/as_literal.hpp> |
23 | |
24 | #include <boost/algorithm/string/detail/find_iterator.hpp> |
25 | |
26 | /*! \file |
27 | Defines find iterator classes. Find iterator repeatedly applies a Finder |
28 | to the specified input string to search for matches. Dereferencing |
29 | the iterator yields the current match or a range between the last and the current |
30 | match depending on the iterator used. |
31 | */ |
32 | |
33 | namespace boost { |
34 | namespace algorithm { |
35 | |
36 | // find_iterator -----------------------------------------------// |
37 | |
38 | //! find_iterator |
39 | /*! |
40 | Find iterator encapsulates a Finder and allows |
41 | for incremental searching in a string. |
42 | Each increment moves the iterator to the next match. |
43 | |
44 | Find iterator is a readable forward traversal iterator. |
45 | |
46 | Dereferencing the iterator yields an iterator_range delimiting |
47 | the current match. |
48 | */ |
49 | template<typename IteratorT> |
50 | class find_iterator : |
51 | public iterator_facade< |
52 | find_iterator<IteratorT>, |
53 | const iterator_range<IteratorT>, |
54 | forward_traversal_tag >, |
55 | private detail::find_iterator_base<IteratorT> |
56 | { |
57 | private: |
58 | // facade support |
59 | friend class ::boost::iterator_core_access; |
60 | |
61 | private: |
62 | // typedefs |
63 | |
64 | typedef detail::find_iterator_base<IteratorT> base_type; |
65 | typedef BOOST_STRING_TYPENAME |
66 | base_type::input_iterator_type input_iterator_type; |
67 | typedef BOOST_STRING_TYPENAME |
68 | base_type::match_type match_type; |
69 | |
70 | public: |
71 | //! Default constructor |
72 | /*! |
73 | Construct null iterator. All null iterators are equal. |
74 | |
75 | \post eof()==true |
76 | */ |
77 | find_iterator() {} |
78 | |
79 | //! Copy constructor |
80 | /*! |
81 | Construct a copy of the find_iterator |
82 | */ |
83 | find_iterator( const find_iterator& Other ) : |
84 | base_type(Other), |
85 | m_Match(Other.m_Match), |
86 | m_End(Other.m_End) {} |
87 | |
88 | //! Constructor |
89 | /*! |
90 | Construct new find_iterator for a given finder |
91 | and a range. |
92 | */ |
93 | template<typename FinderT> |
94 | find_iterator( |
95 | IteratorT Begin, |
96 | IteratorT End, |
97 | FinderT Finder ) : |
98 | detail::find_iterator_base<IteratorT>(Finder,0), |
99 | m_Match(Begin,Begin), |
100 | m_End(End) |
101 | { |
102 | increment(); |
103 | } |
104 | |
105 | //! Constructor |
106 | /*! |
107 | Construct new find_iterator for a given finder |
108 | and a range. |
109 | */ |
110 | template<typename FinderT, typename RangeT> |
111 | find_iterator( |
112 | RangeT& Col, |
113 | FinderT Finder ) : |
114 | detail::find_iterator_base<IteratorT>(Finder,0) |
115 | { |
116 | iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); |
117 | m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); |
118 | m_End=::boost::end(lit_col); |
119 | |
120 | increment(); |
121 | } |
122 | |
123 | private: |
124 | // iterator operations |
125 | |
126 | // dereference |
127 | const match_type& dereference() const |
128 | { |
129 | return m_Match; |
130 | } |
131 | |
132 | // increment |
133 | void increment() |
134 | { |
135 | m_Match=this->do_find(m_Match.end(),m_End); |
136 | } |
137 | |
138 | // comparison |
139 | bool equal( const find_iterator& Other ) const |
140 | { |
141 | bool bEof=eof(); |
142 | bool bOtherEof=Other.eof(); |
143 | |
144 | return bEof || bOtherEof ? bEof==bOtherEof : |
145 | ( |
146 | m_Match==Other.m_Match && |
147 | m_End==Other.m_End |
148 | ); |
149 | } |
150 | |
151 | public: |
152 | // operations |
153 | |
154 | //! Eof check |
155 | /*! |
156 | Check the eof condition. Eof condition means that |
157 | there is nothing more to be searched i.e. find_iterator |
158 | is after the last match. |
159 | */ |
160 | bool eof() const |
161 | { |
162 | return |
163 | this->is_null() || |
164 | ( |
165 | m_Match.begin() == m_End && |
166 | m_Match.end() == m_End |
167 | ); |
168 | } |
169 | |
170 | private: |
171 | // Attributes |
172 | match_type m_Match; |
173 | input_iterator_type m_End; |
174 | }; |
175 | |
176 | //! find iterator construction helper |
177 | /*! |
178 | * Construct a find iterator to iterate through the specified string |
179 | */ |
180 | template<typename RangeT, typename FinderT> |
181 | inline find_iterator< |
182 | BOOST_STRING_TYPENAME range_iterator<RangeT>::type> |
183 | make_find_iterator( |
184 | RangeT& Collection, |
185 | FinderT Finder) |
186 | { |
187 | return find_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( |
188 | Collection, Finder); |
189 | } |
190 | |
191 | // split iterator -----------------------------------------------// |
192 | |
193 | //! split_iterator |
194 | /*! |
195 | Split iterator encapsulates a Finder and allows |
196 | for incremental searching in a string. |
197 | Unlike the find iterator, split iterator iterates |
198 | through gaps between matches. |
199 | |
200 | Find iterator is a readable forward traversal iterator. |
201 | |
202 | Dereferencing the iterator yields an iterator_range delimiting |
203 | the current match. |
204 | */ |
205 | template<typename IteratorT> |
206 | class split_iterator : |
207 | public iterator_facade< |
208 | split_iterator<IteratorT>, |
209 | const iterator_range<IteratorT>, |
210 | forward_traversal_tag >, |
211 | private detail::find_iterator_base<IteratorT> |
212 | { |
213 | private: |
214 | // facade support |
215 | friend class ::boost::iterator_core_access; |
216 | |
217 | private: |
218 | // typedefs |
219 | |
220 | typedef detail::find_iterator_base<IteratorT> base_type; |
221 | typedef BOOST_STRING_TYPENAME |
222 | base_type::input_iterator_type input_iterator_type; |
223 | typedef BOOST_STRING_TYPENAME |
224 | base_type::match_type match_type; |
225 | |
226 | public: |
227 | //! Default constructor |
228 | /*! |
229 | Construct null iterator. All null iterators are equal. |
230 | |
231 | \post eof()==true |
232 | */ |
233 | split_iterator() : |
234 | m_Next(), |
235 | m_End(), |
236 | m_bEof(true) |
237 | {} |
238 | |
239 | //! Copy constructor |
240 | /*! |
241 | Construct a copy of the split_iterator |
242 | */ |
243 | split_iterator( const split_iterator& Other ) : |
244 | base_type(Other), |
245 | m_Match(Other.m_Match), |
246 | m_Next(Other.m_Next), |
247 | m_End(Other.m_End), |
248 | m_bEof(Other.m_bEof) |
249 | {} |
250 | |
251 | //! Constructor |
252 | /*! |
253 | Construct new split_iterator for a given finder |
254 | and a range. |
255 | */ |
256 | template<typename FinderT> |
257 | split_iterator( |
258 | IteratorT Begin, |
259 | IteratorT End, |
260 | FinderT Finder ) : |
261 | detail::find_iterator_base<IteratorT>(Finder,0), |
262 | m_Match(Begin,Begin), |
263 | m_Next(Begin), |
264 | m_End(End), |
265 | m_bEof(false) |
266 | { |
267 | // force the correct behavior for empty sequences and yield at least one token |
268 | if(Begin!=End) |
269 | { |
270 | increment(); |
271 | } |
272 | } |
273 | //! Constructor |
274 | /*! |
275 | Construct new split_iterator for a given finder |
276 | and a collection. |
277 | */ |
278 | template<typename FinderT, typename RangeT> |
279 | split_iterator( |
280 | RangeT& Col, |
281 | FinderT Finder ) : |
282 | detail::find_iterator_base<IteratorT>(Finder,0), |
283 | m_bEof(false) |
284 | { |
285 | iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); |
286 | m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); |
287 | m_Next=::boost::begin(lit_col); |
288 | m_End=::boost::end(lit_col); |
289 | |
290 | // force the correct behavior for empty sequences and yield at least one token |
291 | if(m_Next!=m_End) |
292 | { |
293 | increment(); |
294 | } |
295 | } |
296 | |
297 | |
298 | private: |
299 | // iterator operations |
300 | |
301 | // dereference |
302 | const match_type& dereference() const |
303 | { |
304 | return m_Match; |
305 | } |
306 | |
307 | // increment |
308 | void increment() |
309 | { |
310 | match_type FindMatch=this->do_find( m_Next, m_End ); |
311 | |
312 | if(FindMatch.begin()==m_End && FindMatch.end()==m_End) |
313 | { |
314 | if(m_Match.end()==m_End) |
315 | { |
316 | // Mark iterator as eof |
317 | m_bEof=true; |
318 | } |
319 | } |
320 | |
321 | m_Match=match_type( m_Next, FindMatch.begin() ); |
322 | m_Next=FindMatch.end(); |
323 | } |
324 | |
325 | // comparison |
326 | bool equal( const split_iterator& Other ) const |
327 | { |
328 | bool bEof=eof(); |
329 | bool bOtherEof=Other.eof(); |
330 | |
331 | return bEof || bOtherEof ? bEof==bOtherEof : |
332 | ( |
333 | m_Match==Other.m_Match && |
334 | m_Next==Other.m_Next && |
335 | m_End==Other.m_End |
336 | ); |
337 | } |
338 | |
339 | public: |
340 | // operations |
341 | |
342 | //! Eof check |
343 | /*! |
344 | Check the eof condition. Eof condition means that |
345 | there is nothing more to be searched i.e. find_iterator |
346 | is after the last match. |
347 | */ |
348 | bool eof() const |
349 | { |
350 | return this->is_null() || m_bEof; |
351 | } |
352 | |
353 | private: |
354 | // Attributes |
355 | match_type m_Match; |
356 | input_iterator_type m_Next; |
357 | input_iterator_type m_End; |
358 | bool m_bEof; |
359 | }; |
360 | |
361 | //! split iterator construction helper |
362 | /*! |
363 | * Construct a split iterator to iterate through the specified collection |
364 | */ |
365 | template<typename RangeT, typename FinderT> |
366 | inline split_iterator< |
367 | BOOST_STRING_TYPENAME range_iterator<RangeT>::type> |
368 | make_split_iterator( |
369 | RangeT& Collection, |
370 | FinderT Finder) |
371 | { |
372 | return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( |
373 | Collection, Finder); |
374 | } |
375 | |
376 | |
377 | } // namespace algorithm |
378 | |
379 | // pull names to the boost namespace |
380 | using algorithm::find_iterator; |
381 | using algorithm::make_find_iterator; |
382 | using algorithm::split_iterator; |
383 | using algorithm::make_split_iterator; |
384 | |
385 | } // namespace boost |
386 | |
387 | |
388 | #endif // BOOST_STRING_FIND_ITERATOR_HPP |
389 | |