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