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