Line data Source code
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 0 : 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 0 : split_iterator() :
234 : m_Next(),
235 : m_End(),
236 0 : m_bEof(true)
237 : {}
238 :
239 : //! Copy constructor
240 : /*!
241 : Construct a copy of the split_iterator
242 : */
243 0 : 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 0 : 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 0 : 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 0 : m_bEof(false)
266 : {
267 : // force the correct behavior for empty sequences and yield at least one token
268 0 : if(Begin!=End)
269 : {
270 0 : increment();
271 : }
272 0 : }
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 0 : const match_type& dereference() const
303 : {
304 0 : return m_Match;
305 : }
306 :
307 : // increment
308 0 : void increment()
309 : {
310 0 : match_type FindMatch=this->do_find( m_Next, m_End );
311 :
312 0 : if(FindMatch.begin()==m_End && FindMatch.end()==m_End)
313 : {
314 0 : if(m_Match.end()==m_End)
315 : {
316 : // Mark iterator as eof
317 0 : m_bEof=true;
318 : }
319 : }
320 :
321 0 : m_Match=match_type( m_Next, FindMatch.begin() );
322 0 : m_Next=FindMatch.end();
323 0 : }
324 :
325 : // comparison
326 0 : bool equal( const split_iterator& Other ) const
327 : {
328 0 : bool bEof=eof();
329 0 : bool bOtherEof=Other.eof();
330 :
331 0 : return bEof || bOtherEof ? bEof==bOtherEof :
332 : (
333 0 : m_Match==Other.m_Match &&
334 0 : m_Next==Other.m_Next &&
335 0 : m_End==Other.m_End
336 0 : );
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 0 : bool eof() const
349 : {
350 0 : 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
|