Chris@16
|
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
Chris@16
|
2 // (C) Copyright 2003-2007 Jonathan Turkanis
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
|
Chris@16
|
5
|
Chris@16
|
6 // See http://www.boost.org/libs/iostreams for documentation.
|
Chris@16
|
7
|
Chris@16
|
8 // To do: add support for random-access.
|
Chris@16
|
9
|
Chris@16
|
10 #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
|
Chris@16
|
11 #define BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
|
Chris@16
|
12
|
Chris@16
|
13 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
Chris@16
|
14 # pragma once
|
Chris@16
|
15 #endif
|
Chris@16
|
16
|
Chris@16
|
17 #include <boost/config.hpp> // NO_STD_LOCALE, DEDUCED_TYPENAME.
|
Chris@16
|
18 #ifndef BOOST_NO_STD_LOCALE
|
Chris@16
|
19 # include <locale>
|
Chris@16
|
20 #endif
|
Chris@16
|
21 #include <boost/iostreams/detail/ios.hpp>
|
Chris@16
|
22 #include <boost/iostreams/detail/wrap_unwrap.hpp>
|
Chris@16
|
23 #include <boost/iostreams/traits.hpp>
|
Chris@16
|
24 #include <boost/iostreams/operations.hpp>
|
Chris@16
|
25 #include <boost/mpl/if.hpp>
|
Chris@16
|
26 #include <boost/static_assert.hpp>
|
Chris@16
|
27 #include <boost/type_traits/is_convertible.hpp>
|
Chris@16
|
28 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 // Must come last.
|
Chris@16
|
31 #include <boost/iostreams/detail/config/disable_warnings.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost { namespace iostreams {
|
Chris@16
|
34
|
Chris@16
|
35 namespace detail {
|
Chris@16
|
36
|
Chris@16
|
37 //
|
Chris@16
|
38 // Template name: combined_device.
|
Chris@16
|
39 // Description: Model of Device defined in terms of a Source/Sink pair.
|
Chris@16
|
40 // Template parameters:
|
Chris@16
|
41 // Source - A model of Source, with the same char_type and traits_type
|
Chris@16
|
42 // as Sink.
|
Chris@16
|
43 // Sink - A model of Sink, with the same char_type and traits_type
|
Chris@16
|
44 // as Source.
|
Chris@16
|
45 //
|
Chris@16
|
46 template<typename Source, typename Sink>
|
Chris@16
|
47 class combined_device {
|
Chris@16
|
48 private:
|
Chris@16
|
49 typedef typename category_of<Source>::type in_category;
|
Chris@16
|
50 typedef typename category_of<Sink>::type out_category;
|
Chris@16
|
51 typedef typename char_type_of<Sink>::type sink_char_type;
|
Chris@16
|
52 public:
|
Chris@16
|
53 typedef typename char_type_of<Source>::type char_type;
|
Chris@16
|
54 struct category
|
Chris@16
|
55 : bidirectional,
|
Chris@16
|
56 device_tag,
|
Chris@16
|
57 closable_tag,
|
Chris@16
|
58 localizable_tag
|
Chris@16
|
59 { };
|
Chris@16
|
60 BOOST_STATIC_ASSERT(is_device<Source>::value);
|
Chris@16
|
61 BOOST_STATIC_ASSERT(is_device<Sink>::value);
|
Chris@16
|
62 BOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
|
Chris@16
|
63 BOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
|
Chris@16
|
64 BOOST_STATIC_ASSERT((is_same<char_type, sink_char_type>::value));
|
Chris@16
|
65 combined_device(const Source& src, const Sink& snk);
|
Chris@16
|
66 std::streamsize read(char_type* s, std::streamsize n);
|
Chris@16
|
67 std::streamsize write(const char_type* s, std::streamsize n);
|
Chris@16
|
68 void close(BOOST_IOS::openmode);
|
Chris@16
|
69 #ifndef BOOST_NO_STD_LOCALE
|
Chris@16
|
70 void imbue(const std::locale& loc);
|
Chris@16
|
71 #endif
|
Chris@16
|
72 private:
|
Chris@16
|
73 Source src_;
|
Chris@16
|
74 Sink sink_;
|
Chris@16
|
75 };
|
Chris@16
|
76
|
Chris@16
|
77 //
|
Chris@16
|
78 // Template name: combined_filter.
|
Chris@16
|
79 // Description: Model of Device defined in terms of a Source/Sink pair.
|
Chris@16
|
80 // Template parameters:
|
Chris@16
|
81 // InputFilter - A model of InputFilter, with the same char_type as
|
Chris@16
|
82 // OutputFilter.
|
Chris@16
|
83 // OutputFilter - A model of OutputFilter, with the same char_type as
|
Chris@16
|
84 // InputFilter.
|
Chris@16
|
85 //
|
Chris@16
|
86 template<typename InputFilter, typename OutputFilter>
|
Chris@16
|
87 class combined_filter {
|
Chris@16
|
88 private:
|
Chris@16
|
89 typedef typename category_of<InputFilter>::type in_category;
|
Chris@16
|
90 typedef typename category_of<OutputFilter>::type out_category;
|
Chris@16
|
91 typedef typename char_type_of<OutputFilter>::type output_char_type;
|
Chris@16
|
92 public:
|
Chris@16
|
93 typedef typename char_type_of<InputFilter>::type char_type;
|
Chris@16
|
94 struct category
|
Chris@16
|
95 : multichar_bidirectional_filter_tag,
|
Chris@16
|
96 closable_tag,
|
Chris@16
|
97 localizable_tag
|
Chris@16
|
98 { };
|
Chris@16
|
99 BOOST_STATIC_ASSERT(is_filter<InputFilter>::value);
|
Chris@16
|
100 BOOST_STATIC_ASSERT(is_filter<OutputFilter>::value);
|
Chris@16
|
101 BOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
|
Chris@16
|
102 BOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
|
Chris@16
|
103 BOOST_STATIC_ASSERT((is_same<char_type, output_char_type>::value));
|
Chris@16
|
104 combined_filter(const InputFilter& in, const OutputFilter& out);
|
Chris@16
|
105
|
Chris@16
|
106 template<typename Source>
|
Chris@16
|
107 std::streamsize read(Source& src, char_type* s, std::streamsize n)
|
Chris@16
|
108 { return boost::iostreams::read(in_, src, s, n); }
|
Chris@16
|
109
|
Chris@16
|
110 template<typename Sink>
|
Chris@16
|
111 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
|
Chris@16
|
112 { return boost::iostreams::write(out_, snk, s, n); }
|
Chris@16
|
113
|
Chris@16
|
114 template<typename Sink>
|
Chris@16
|
115 void close(Sink& snk, BOOST_IOS::openmode which)
|
Chris@16
|
116 {
|
Chris@16
|
117 if (which == BOOST_IOS::in) {
|
Chris@16
|
118 if (is_convertible<in_category, dual_use>::value) {
|
Chris@16
|
119 iostreams::close(in_, snk, BOOST_IOS::in);
|
Chris@16
|
120 } else {
|
Chris@16
|
121 detail::close_all(in_, snk);
|
Chris@16
|
122 }
|
Chris@16
|
123 }
|
Chris@16
|
124 if (which == BOOST_IOS::out) {
|
Chris@16
|
125 if (is_convertible<out_category, dual_use>::value) {
|
Chris@16
|
126 iostreams::close(out_, snk, BOOST_IOS::out);
|
Chris@16
|
127 } else {
|
Chris@16
|
128 detail::close_all(out_, snk);
|
Chris@16
|
129 }
|
Chris@16
|
130 }
|
Chris@16
|
131 }
|
Chris@16
|
132 #ifndef BOOST_NO_STD_LOCALE
|
Chris@16
|
133 void imbue(const std::locale& loc);
|
Chris@16
|
134 #endif
|
Chris@16
|
135 private:
|
Chris@16
|
136 InputFilter in_;
|
Chris@16
|
137 OutputFilter out_;
|
Chris@16
|
138 };
|
Chris@16
|
139
|
Chris@16
|
140 template<typename In, typename Out>
|
Chris@16
|
141 struct combination_traits
|
Chris@16
|
142 : mpl::if_<
|
Chris@16
|
143 is_device<In>,
|
Chris@16
|
144 combined_device<
|
Chris@16
|
145 typename wrapped_type<In>::type,
|
Chris@16
|
146 typename wrapped_type<Out>::type
|
Chris@16
|
147 >,
|
Chris@16
|
148 combined_filter<
|
Chris@16
|
149 typename wrapped_type<In>::type,
|
Chris@16
|
150 typename wrapped_type<Out>::type
|
Chris@16
|
151 >
|
Chris@16
|
152 >
|
Chris@16
|
153 { };
|
Chris@16
|
154
|
Chris@16
|
155 } // End namespace detail.
|
Chris@16
|
156
|
Chris@16
|
157 template<typename In, typename Out>
|
Chris@16
|
158 struct combination : detail::combination_traits<In, Out>::type {
|
Chris@16
|
159 typedef typename detail::combination_traits<In, Out>::type base_type;
|
Chris@16
|
160 typedef typename detail::wrapped_type<In>::type in_type;
|
Chris@16
|
161 typedef typename detail::wrapped_type<Out>::type out_type;
|
Chris@16
|
162 combination(const in_type& in, const out_type& out)
|
Chris@16
|
163 : base_type(in, out) { }
|
Chris@16
|
164 };
|
Chris@16
|
165
|
Chris@16
|
166 namespace detail {
|
Chris@16
|
167
|
Chris@16
|
168 // Workaround for VC6 ETI bug.
|
Chris@16
|
169 template<typename In, typename Out>
|
Chris@16
|
170 struct combine_traits {
|
Chris@16
|
171 typedef combination<
|
Chris@16
|
172 BOOST_DEDUCED_TYPENAME detail::unwrapped_type<In>::type,
|
Chris@16
|
173 BOOST_DEDUCED_TYPENAME detail::unwrapped_type<Out>::type
|
Chris@16
|
174 > type;
|
Chris@16
|
175 };
|
Chris@16
|
176
|
Chris@16
|
177 } // End namespace detail.
|
Chris@16
|
178
|
Chris@16
|
179 //
|
Chris@16
|
180 // Template name: combine.
|
Chris@16
|
181 // Description: Takes a Source/Sink pair or InputFilter/OutputFilter pair and
|
Chris@16
|
182 // returns a Source or Filter which performs input using the first member
|
Chris@16
|
183 // of the pair and output using the second member of the pair.
|
Chris@16
|
184 // Template parameters:
|
Chris@16
|
185 // In - A model of Source or InputFilter, with the same char_type as Out.
|
Chris@16
|
186 // Out - A model of Sink or OutputFilter, with the same char_type as In.
|
Chris@16
|
187 //
|
Chris@16
|
188 template<typename In, typename Out>
|
Chris@16
|
189 typename detail::combine_traits<In, Out>::type
|
Chris@16
|
190 combine(const In& in, const Out& out)
|
Chris@16
|
191 {
|
Chris@16
|
192 typedef typename detail::combine_traits<In, Out>::type return_type;
|
Chris@16
|
193 return return_type(in, out);
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 //----------------------------------------------------------------------------//
|
Chris@16
|
197
|
Chris@16
|
198 namespace detail {
|
Chris@16
|
199
|
Chris@16
|
200 //--------------Implementation of combined_device-----------------------------//
|
Chris@16
|
201
|
Chris@16
|
202 template<typename Source, typename Sink>
|
Chris@16
|
203 inline combined_device<Source, Sink>::combined_device
|
Chris@16
|
204 (const Source& src, const Sink& snk)
|
Chris@16
|
205 : src_(src), sink_(snk) { }
|
Chris@16
|
206
|
Chris@16
|
207 template<typename Source, typename Sink>
|
Chris@16
|
208 inline std::streamsize
|
Chris@16
|
209 combined_device<Source, Sink>::read(char_type* s, std::streamsize n)
|
Chris@16
|
210 { return iostreams::read(src_, s, n); }
|
Chris@16
|
211
|
Chris@16
|
212 template<typename Source, typename Sink>
|
Chris@16
|
213 inline std::streamsize
|
Chris@16
|
214 combined_device<Source, Sink>::write(const char_type* s, std::streamsize n)
|
Chris@16
|
215 { return iostreams::write(sink_, s, n); }
|
Chris@16
|
216
|
Chris@16
|
217 template<typename Source, typename Sink>
|
Chris@16
|
218 inline void
|
Chris@16
|
219 combined_device<Source, Sink>::close(BOOST_IOS::openmode which)
|
Chris@16
|
220 {
|
Chris@16
|
221 if (which == BOOST_IOS::in)
|
Chris@16
|
222 detail::close_all(src_);
|
Chris@16
|
223 if (which == BOOST_IOS::out)
|
Chris@16
|
224 detail::close_all(sink_);
|
Chris@16
|
225 }
|
Chris@16
|
226
|
Chris@16
|
227 #ifndef BOOST_NO_STD_LOCALE
|
Chris@16
|
228 template<typename Source, typename Sink>
|
Chris@16
|
229 void combined_device<Source, Sink>::imbue(const std::locale& loc)
|
Chris@16
|
230 {
|
Chris@16
|
231 iostreams::imbue(src_, loc);
|
Chris@16
|
232 iostreams::imbue(sink_, loc);
|
Chris@16
|
233 }
|
Chris@16
|
234 #endif
|
Chris@16
|
235
|
Chris@16
|
236 //--------------Implementation of filter_pair---------------------------------//
|
Chris@16
|
237
|
Chris@16
|
238 template<typename InputFilter, typename OutputFilter>
|
Chris@16
|
239 inline combined_filter<InputFilter, OutputFilter>::combined_filter
|
Chris@16
|
240 (const InputFilter& in, const OutputFilter& out) : in_(in), out_(out)
|
Chris@16
|
241 { }
|
Chris@16
|
242
|
Chris@16
|
243 #ifndef BOOST_NO_STD_LOCALE
|
Chris@16
|
244 template<typename InputFilter, typename OutputFilter>
|
Chris@16
|
245 void combined_filter<InputFilter, OutputFilter>::imbue
|
Chris@16
|
246 (const std::locale& loc)
|
Chris@16
|
247 {
|
Chris@16
|
248 iostreams::imbue(in_, loc);
|
Chris@16
|
249 iostreams::imbue(out_, loc);
|
Chris@16
|
250 }
|
Chris@16
|
251 #endif
|
Chris@16
|
252
|
Chris@16
|
253
|
Chris@16
|
254 } // End namespace detail.
|
Chris@16
|
255
|
Chris@16
|
256 } } // End namespaces iostreams, boost.
|
Chris@16
|
257
|
Chris@16
|
258 #include <boost/iostreams/detail/config/enable_warnings.hpp>
|
Chris@16
|
259
|
Chris@16
|
260 #endif // #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
|