1 //  Boost string_algo library join.hpp header file  ---------------------------//
2 
3 //  Copyright Pavol Droba 2002-2006.
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_JOIN_HPP
12 #define BOOST_STRING_JOIN_HPP
13 
14 #include <boost/algorithm/string/config.hpp>
15 #include <boost/algorithm/string/detail/sequence.hpp>
16 #include <boost/range/value_type.hpp>
17 #include <boost/range/as_literal.hpp>
18 
19 /*! \file
20     Defines join algorithm.
21 
22     Join algorithm is a counterpart to split algorithms.
23     It joins strings from a 'list' by adding user defined separator.
24     Additionally there is a version that allows simple filtering
25     by providing a predicate.
26 */
27 
28 namespace boost {
29     namespace algorithm {
30 
31 //  join --------------------------------------------------------------//
32 
33         //! Join algorithm
34         /*!
35             This algorithm joins all strings in a 'list' into one long string.
36             Segments are concatenated by given separator.
37 
38             \param Input A container that holds the input strings. It must be a container-of-containers.
39             \param Separator A string that will separate the joined segments.
40             \return Concatenated string.
41 
42             \note This function provides the strong exception-safety guarantee
43         */
44         template< typename SequenceSequenceT, typename Range1T>
45         inline typename range_value<SequenceSequenceT>::type
join(const SequenceSequenceT & Input,const Range1T & Separator)46         join(
47             const SequenceSequenceT& Input,
48             const Range1T& Separator)
49         {
50             // Define working types
51             typedef typename range_value<SequenceSequenceT>::type ResultT;
52             typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
53 
54             // Parse input
55             InputIteratorT itBegin=::boost::begin(Input);
56             InputIteratorT itEnd=::boost::end(Input);
57 
58             // Construct container to hold the result
59             ResultT Result;
60 
61             // Append first element
62             if(itBegin!=itEnd)
63             {
64                 detail::insert(Result, ::boost::end(Result), *itBegin);
65                 ++itBegin;
66             }
67 
68             for(;itBegin!=itEnd; ++itBegin)
69             {
70                 // Add separator
71                 detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
72                 // Add element
73                 detail::insert(Result, ::boost::end(Result), *itBegin);
74             }
75 
76             return Result;
77         }
78 
79 // join_if ----------------------------------------------------------//
80 
81         //! Conditional join algorithm
82         /*!
83             This algorithm joins all strings in a 'list' into one long string.
84             Segments are concatenated by given separator. Only segments that
85             satisfy the predicate will be added to the result.
86 
87             \param Input A container that holds the input strings. It must be a container-of-containers.
88             \param Separator A string that will separate the joined segments.
89             \param Pred A segment selection predicate
90             \return Concatenated string.
91 
92             \note This function provides the strong exception-safety guarantee
93         */
94         template< typename SequenceSequenceT, typename Range1T, typename PredicateT>
95         inline typename range_value<SequenceSequenceT>::type
join_if(const SequenceSequenceT & Input,const Range1T & Separator,PredicateT Pred)96         join_if(
97             const SequenceSequenceT& Input,
98             const Range1T& Separator,
99             PredicateT Pred)
100         {
101             // Define working types
102             typedef typename range_value<SequenceSequenceT>::type ResultT;
103             typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
104 
105             // Parse input
106             InputIteratorT itBegin=::boost::begin(Input);
107             InputIteratorT itEnd=::boost::end(Input);
108 
109             // Construct container to hold the result
110             ResultT Result;
111 
112             // Roll to the first element that will be added
113             while(itBegin!=itEnd && !Pred(*itBegin)) ++itBegin;
114             // Add this element
115             if(itBegin!=itEnd)
116             {
117                 detail::insert(Result, ::boost::end(Result), *itBegin);
118                 ++itBegin;
119             }
120 
121             for(;itBegin!=itEnd; ++itBegin)
122             {
123                 if(Pred(*itBegin))
124                 {
125                     // Add separator
126                     detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
127                     // Add element
128                     detail::insert(Result, ::boost::end(Result), *itBegin);
129                 }
130             }
131 
132             return Result;
133         }
134 
135     } // namespace algorithm
136 
137     // pull names to the boost namespace
138     using algorithm::join;
139     using algorithm::join_if;
140 
141 } // namespace boost
142 
143 
144 #endif  // BOOST_STRING_JOIN_HPP
145 
146