1// Boost.Range library
2//
3// Copyright Neil Groves 2014.
4// Use, modification and distribution is subject to the Boost Software
5// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//
8// For more information, see http://www.boost.org/libs/range/
9//
10#ifndef BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED
11#define BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED
12
13#include <boost/config.hpp>
14#include <boost/range/concepts.hpp>
15#include <boost/range/begin.hpp>
16#include <boost/range/end.hpp>
17#include <boost/range/iterator.hpp>
18#include <boost/range/iterator_range_core.hpp>
19#include <boost/mpl/if.hpp>
20#include <boost/type_traits/is_array.hpp>
21#include <boost/type_traits/remove_extent.hpp>
22#include <ostream>
23
24namespace boost
25{
26 namespace range_detail
27 {
28
29template<typename Sep, typename Prefix, typename Postfix>
30struct formatted_holder
31{
32 typedef typename boost::mpl::if_<
33 boost::is_array<Sep>,
34 const typename boost::remove_extent<Sep>::type*,
35 Sep
36 >::type separator_t;
37
38 typedef typename boost::mpl::if_<
39 boost::is_array<Prefix>,
40 const typename boost::remove_extent<Prefix>::type*,
41 Prefix
42 >::type prefix_t;
43
44 typedef typename boost::mpl::if_<
45 boost::is_array<Postfix>,
46 const typename boost::remove_extent<Postfix>::type*,
47 Postfix
48 >::type postfix_t;
49
50 formatted_holder(
51 const separator_t& sep,
52 const prefix_t& prefix,
53 const postfix_t& postfix)
54 : m_sep(sep)
55 , m_prefix(prefix)
56 , m_postfix(postfix)
57 {
58 }
59
60 separator_t m_sep;
61 prefix_t m_prefix;
62 postfix_t m_postfix;
63};
64
65template<typename Iter, typename Sep, typename Prefix, typename Postfix>
66class formatted_range
67 : public boost::iterator_range<Iter>
68{
69 typedef formatted_holder<Sep,Prefix,Postfix> holder_t;
70public:
71 formatted_range(Iter first, Iter last, const holder_t& holder)
72 : boost::iterator_range<Iter>(first, last)
73 , m_holder(holder)
74 {
75 }
76
77 template<typename OStream>
78 void write(OStream& out) const
79 {
80 Iter it(this->begin());
81 out << m_holder.m_prefix;
82 if (it != this->end())
83 {
84 out << *it;
85 for (++it; it != this->end(); ++it)
86 {
87 out << m_holder.m_sep << *it;
88 }
89 }
90 out << m_holder.m_postfix;
91 }
92
93private:
94 holder_t m_holder;
95};
96
97template<
98 typename SinglePassRange,
99 typename Sep,
100 typename Prefix,
101 typename Postfix
102>
103inline range_detail::formatted_range<
104 typename range_iterator<const SinglePassRange>::type, Sep, Prefix, Postfix
105>
106operator|(
107 const SinglePassRange& rng,
108 const range_detail::formatted_holder<Sep,Prefix,Postfix>& holder
109)
110{
111 typedef typename range_iterator<const SinglePassRange>::type iterator;
112 return range_detail::formatted_range<iterator, Sep, Prefix, Postfix>(
113 boost::begin(rng), boost::end(rng), holder);
114}
115
116template<typename Char, typename Traits, typename Iter, typename Sep,
117 typename Prefix, typename Postfix>
118std::basic_ostream<Char, Traits>&
119operator<<(
120 std::basic_ostream<Char, Traits>& out,
121 const formatted_range<Iter, Sep, Prefix, Postfix>& writer)
122{
123 writer.write(out);
124 return out;
125}
126
127 } // namespace range_detail
128
129 namespace adaptors
130 {
131
132template<typename Sep, typename Prefix, typename Postfix>
133range_detail::formatted_holder<Sep, Prefix, Postfix>
134formatted(const Sep& sep, const Prefix& prefix, const Postfix& postfix)
135{
136 return range_detail::formatted_holder<Sep,Prefix,Postfix>(
137 sep, prefix, postfix);
138}
139
140template<typename Sep, typename Prefix>
141range_detail::formatted_holder<Sep, Prefix, char>
142formatted(const Sep& sep, const Prefix& prefix)
143{
144 return range_detail::formatted_holder<Sep, Prefix, char>(sep, prefix, '}');
145}
146
147template<typename Sep>
148range_detail::formatted_holder<Sep, char, char>
149formatted(const Sep& sep)
150{
151 return range_detail::formatted_holder<Sep, char, char>(sep, '{', '}');
152}
153
154inline range_detail::formatted_holder<char, char, char>
155formatted()
156{
157 return range_detail::formatted_holder<char, char, char>(',', '{', '}');
158}
159
160using range_detail::formatted_range;
161
162template<typename SinglePassRange, typename Sep, typename Prefix,
163 typename Postfix>
164inline boost::range_detail::formatted_range<
165 typename boost::range_iterator<const SinglePassRange>::type,
166 Sep, Prefix, Postfix
167>
168format(
169 const SinglePassRange& rng,
170 const Sep& sep,
171 const Prefix& prefix,
172 const Postfix& postfix
173)
174{
175 typedef typename boost::range_iterator<const SinglePassRange>::type
176 iterator_t;
177
178 typedef boost::range_detail::formatted_range<
179 iterator_t, Sep, Prefix, Postfix> result_t;
180
181 typedef boost::range_detail::formatted_holder<Sep, Prefix, Postfix>
182 holder_t;
183
184 return result_t(boost::begin(rng), boost::end(rng),
185 holder_t(sep, prefix, postfix));
186}
187
188template<typename SinglePassRange, typename Sep, typename Prefix>
189inline boost::range_detail::formatted_range<
190 typename boost::range_iterator<const SinglePassRange>::type,
191 Sep, Prefix, char
192>
193format(
194 const SinglePassRange& rng,
195 const Sep& sep,
196 const Prefix& prefix)
197{
198 return adaptors::format<SinglePassRange, Sep, Prefix, char>(rng, sep, prefix, '}');
199}
200
201template<typename SinglePassRange, typename Sep>
202inline boost::range_detail::formatted_range<
203 typename boost::range_iterator<const SinglePassRange>::type,
204 Sep, char, char
205>
206format(const SinglePassRange& rng, const Sep& sep)
207{
208 return adaptors::format<SinglePassRange, Sep, char, char>(rng, sep, '{', '}');
209}
210
211template<typename SinglePassRange>
212inline boost::range_detail::formatted_range<
213 typename boost::range_iterator<const SinglePassRange>::type,
214 char, char, char
215>
216format(const SinglePassRange& rng)
217{
218 return adaptors::format<SinglePassRange, char, char, char>(rng, ',', '{', '}');
219}
220
221 } // namespace adaptors
222
223 namespace range
224 {
225 using boost::range_detail::formatted_range;
226 } // namespace range
227} // namespace boost
228
229#endif // include guard
230