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