]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |