1 //  Boost string_algo library iter_find.hpp header file  ---------------------------//
2 
3 //  Copyright Pavol Droba 2002-2003.
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_ITER_FIND_HPP
12 #define BOOST_STRING_ITER_FIND_HPP
13 
14 #include <boost/algorithm/string/config.hpp>
15 #include <algorithm>
16 #include <iterator>
17 #include <boost/iterator/transform_iterator.hpp>
18 
19 #include <boost/range/iterator_range_core.hpp>
20 #include <boost/range/begin.hpp>
21 #include <boost/range/end.hpp>
22 #include <boost/range/iterator.hpp>
23 #include <boost/range/value_type.hpp>
24 #include <boost/range/as_literal.hpp>
25 
26 #include <boost/algorithm/string/concept.hpp>
27 #include <boost/algorithm/string/find_iterator.hpp>
28 #include <boost/algorithm/string/detail/util.hpp>
29 
30 /*! \file
31     Defines generic split algorithms. Split algorithms can be
32     used to divide a sequence into several part according
33     to a given criteria. Result is given as a 'container
34     of containers' where elements are copies or references
35     to extracted parts.
36 
37     There are two algorithms provided. One iterates over matching
38     substrings, the other one over the gaps between these matches.
39 */
40 
41 namespace boost {
42     namespace algorithm {
43 
44 //  iterate find ---------------------------------------------------//
45 
46         //! Iter find algorithm
47         /*!
48             This algorithm executes a given finder in iteration on the input,
49             until the end of input is reached, or no match is found.
50             Iteration is done using built-in find_iterator, so the real
51             searching is performed only when needed.
52             In each iteration new match is found and added to the result.
53 
54             \param Result A 'container container' to contain the result of search.
55                 Both outer and inner container must have constructor taking a pair
56                 of iterators as an argument.
57                 Typical type of the result is
58                     \c std::vector<boost::iterator_range<iterator>>
59                 (each element of such a vector will container a range delimiting
60                 a match).
61             \param Input A container which will be searched.
62             \param Finder A Finder object used for searching
63             \return A reference to the result
64 
65             \note Prior content of the result will be overwritten.
66         */
67         template<
68             typename SequenceSequenceT,
69             typename RangeT,
70             typename FinderT >
71         inline SequenceSequenceT&
iter_find(SequenceSequenceT & Result,RangeT & Input,FinderT Finder)72         iter_find(
73             SequenceSequenceT& Result,
74             RangeT& Input,
75             FinderT Finder )
76         {
77             BOOST_CONCEPT_ASSERT((
78                 FinderConcept<
79                     FinderT,
80                     BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
81                 ));
82 
83             iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
84 
85             typedef BOOST_STRING_TYPENAME
86                 range_iterator<RangeT>::type input_iterator_type;
87             typedef find_iterator<input_iterator_type> find_iterator_type;
88             typedef detail::copy_iterator_rangeF<
89                 BOOST_STRING_TYPENAME
90                     range_value<SequenceSequenceT>::type,
91                 input_iterator_type> copy_range_type;
92 
93             input_iterator_type InputEnd=::boost::end(lit_input);
94 
95             typedef transform_iterator<copy_range_type, find_iterator_type>
96                 transform_iter_type;
97 
98             transform_iter_type itBegin=
99                 ::boost::make_transform_iterator(
100                     find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
101                     copy_range_type());
102 
103             transform_iter_type itEnd=
104                 ::boost::make_transform_iterator(
105                     find_iterator_type(),
106                     copy_range_type());
107 
108             SequenceSequenceT Tmp(itBegin, itEnd);
109 
110             Result.swap(Tmp);
111             return Result;
112         }
113 
114 //  iterate split ---------------------------------------------------//
115 
116         //! Split find algorithm
117         /*!
118             This algorithm executes a given finder in iteration on the input,
119             until the end of input is reached, or no match is found.
120             Iteration is done using built-in find_iterator, so the real
121             searching is performed only when needed.
122             Each match is used as a separator of segments. These segments are then
123             returned in the result.
124 
125             \param Result A 'container container' to contain the result of search.
126                 Both outer and inner container must have constructor taking a pair
127                 of iterators as an argument.
128                 Typical type of the result is
129                     \c std::vector<boost::iterator_range<iterator>>
130                 (each element of such a vector will container a range delimiting
131                 a match).
132             \param Input A container which will be searched.
133             \param Finder A finder object used for searching
134             \return A reference to the result
135 
136             \note Prior content of the result will be overwritten.
137         */
138         template<
139             typename SequenceSequenceT,
140             typename RangeT,
141             typename FinderT >
142         inline SequenceSequenceT&
iter_split(SequenceSequenceT & Result,RangeT & Input,FinderT Finder)143         iter_split(
144             SequenceSequenceT& Result,
145             RangeT& Input,
146             FinderT Finder )
147         {
148             BOOST_CONCEPT_ASSERT((
149                 FinderConcept<FinderT,
150                 BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
151                 ));
152 
153             iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
154 
155             typedef BOOST_STRING_TYPENAME
156                 range_iterator<RangeT>::type input_iterator_type;
157             typedef split_iterator<input_iterator_type> find_iterator_type;
158             typedef detail::copy_iterator_rangeF<
159                 BOOST_STRING_TYPENAME
160                     range_value<SequenceSequenceT>::type,
161                 input_iterator_type> copy_range_type;
162 
163             input_iterator_type InputEnd=::boost::end(lit_input);
164 
165             typedef transform_iterator<copy_range_type, find_iterator_type>
166                 transform_iter_type;
167 
168             transform_iter_type itBegin=
169                 ::boost::make_transform_iterator(
170                     find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
171                     copy_range_type() );
172 
173             transform_iter_type itEnd=
174                 ::boost::make_transform_iterator(
175                     find_iterator_type(),
176                     copy_range_type() );
177 
178             SequenceSequenceT Tmp(itBegin, itEnd);
179 
180             Result.swap(Tmp);
181             return Result;
182         }
183 
184     } // namespace algorithm
185 
186     // pull names to the boost namespace
187     using algorithm::iter_find;
188     using algorithm::iter_split;
189 
190 } // namespace boost
191 
192 
193 #endif  // BOOST_STRING_ITER_FIND_HPP
194