1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
6 // See http://www.boost.org/libs/iostreams for documentation.
8 // To do: add support for random-access.
10 #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
11 #define BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
17 #include <boost/config.hpp> // NO_STD_LOCALE, DEDUCED_TYPENAME.
18 #ifndef BOOST_NO_STD_LOCALE
21 #include <boost/iostreams/detail/ios.hpp>
22 #include <boost/iostreams/detail/wrap_unwrap.hpp>
23 #include <boost/iostreams/traits.hpp>
24 #include <boost/iostreams/operations.hpp>
25 #include <boost/mpl/if.hpp>
26 #include <boost/static_assert.hpp>
27 #include <boost/type_traits/is_convertible.hpp>
28 #include <boost/type_traits/is_same.hpp>
31 #include <boost/iostreams/detail/config/disable_warnings.hpp>
33 namespace boost { namespace iostreams {
38 // Template name: combined_device.
39 // Description: Model of Device defined in terms of a Source/Sink pair.
40 // Template parameters:
41 // Source - A model of Source, with the same char_type and traits_type
43 // Sink - A model of Sink, with the same char_type and traits_type
46 template<typename Source, typename Sink>
47 class combined_device {
49 typedef typename category_of<Source>::type in_category;
50 typedef typename category_of<Sink>::type out_category;
51 typedef typename char_type_of<Sink>::type sink_char_type;
53 typedef typename char_type_of<Source>::type char_type;
60 BOOST_STATIC_ASSERT(is_device<Source>::value);
61 BOOST_STATIC_ASSERT(is_device<Sink>::value);
62 BOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
63 BOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
64 BOOST_STATIC_ASSERT((is_same<char_type, sink_char_type>::value));
65 combined_device(const Source& src, const Sink& snk);
66 std::streamsize read(char_type* s, std::streamsize n);
67 std::streamsize write(const char_type* s, std::streamsize n);
68 void close(BOOST_IOS::openmode);
69 #ifndef BOOST_NO_STD_LOCALE
70 void imbue(const std::locale& loc);
78 // Template name: combined_filter.
79 // Description: Model of Device defined in terms of a Source/Sink pair.
80 // Template parameters:
81 // InputFilter - A model of InputFilter, with the same char_type as
83 // OutputFilter - A model of OutputFilter, with the same char_type as
86 template<typename InputFilter, typename OutputFilter>
87 class combined_filter {
89 typedef typename category_of<InputFilter>::type in_category;
90 typedef typename category_of<OutputFilter>::type out_category;
91 typedef typename char_type_of<OutputFilter>::type output_char_type;
93 typedef typename char_type_of<InputFilter>::type char_type;
95 : multichar_bidirectional_filter_tag,
99 BOOST_STATIC_ASSERT(is_filter<InputFilter>::value);
100 BOOST_STATIC_ASSERT(is_filter<OutputFilter>::value);
101 BOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
102 BOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
103 BOOST_STATIC_ASSERT((is_same<char_type, output_char_type>::value));
104 combined_filter(const InputFilter& in, const OutputFilter& out);
106 template<typename Source>
107 std::streamsize read(Source& src, char_type* s, std::streamsize n)
108 { return boost::iostreams::read(in_, src, s, n); }
110 template<typename Sink>
111 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
112 { return boost::iostreams::write(out_, snk, s, n); }
114 template<typename Sink>
115 void close(Sink& snk, BOOST_IOS::openmode which)
117 if (which == BOOST_IOS::in) {
118 if (is_convertible<in_category, dual_use>::value) {
119 iostreams::close(in_, snk, BOOST_IOS::in);
121 detail::close_all(in_, snk);
124 if (which == BOOST_IOS::out) {
125 if (is_convertible<out_category, dual_use>::value) {
126 iostreams::close(out_, snk, BOOST_IOS::out);
128 detail::close_all(out_, snk);
132 #ifndef BOOST_NO_STD_LOCALE
133 void imbue(const std::locale& loc);
140 template<typename In, typename Out>
141 struct combination_traits
145 typename wrapped_type<In>::type,
146 typename wrapped_type<Out>::type
149 typename wrapped_type<In>::type,
150 typename wrapped_type<Out>::type
155 } // End namespace detail.
157 template<typename In, typename Out>
158 struct combination : detail::combination_traits<In, Out>::type {
159 typedef typename detail::combination_traits<In, Out>::type base_type;
160 typedef typename detail::wrapped_type<In>::type in_type;
161 typedef typename detail::wrapped_type<Out>::type out_type;
162 combination(const in_type& in, const out_type& out)
163 : base_type(in, out) { }
168 // Workaround for VC6 ETI bug.
169 template<typename In, typename Out>
170 struct combine_traits {
172 BOOST_DEDUCED_TYPENAME detail::unwrapped_type<In>::type,
173 BOOST_DEDUCED_TYPENAME detail::unwrapped_type<Out>::type
177 } // End namespace detail.
180 // Template name: combine.
181 // Description: Takes a Source/Sink pair or InputFilter/OutputFilter pair and
182 // returns a Source or Filter which performs input using the first member
183 // of the pair and output using the second member of the pair.
184 // Template parameters:
185 // In - A model of Source or InputFilter, with the same char_type as Out.
186 // Out - A model of Sink or OutputFilter, with the same char_type as In.
188 template<typename In, typename Out>
189 typename detail::combine_traits<In, Out>::type
190 combine(const In& in, const Out& out)
192 typedef typename detail::combine_traits<In, Out>::type return_type;
193 return return_type(in, out);
196 //----------------------------------------------------------------------------//
200 //--------------Implementation of combined_device-----------------------------//
202 template<typename Source, typename Sink>
203 inline combined_device<Source, Sink>::combined_device
204 (const Source& src, const Sink& snk)
205 : src_(src), sink_(snk) { }
207 template<typename Source, typename Sink>
208 inline std::streamsize
209 combined_device<Source, Sink>::read(char_type* s, std::streamsize n)
210 { return iostreams::read(src_, s, n); }
212 template<typename Source, typename Sink>
213 inline std::streamsize
214 combined_device<Source, Sink>::write(const char_type* s, std::streamsize n)
215 { return iostreams::write(sink_, s, n); }
217 template<typename Source, typename Sink>
219 combined_device<Source, Sink>::close(BOOST_IOS::openmode which)
221 if (which == BOOST_IOS::in)
222 detail::close_all(src_);
223 if (which == BOOST_IOS::out)
224 detail::close_all(sink_);
227 #ifndef BOOST_NO_STD_LOCALE
228 template<typename Source, typename Sink>
229 void combined_device<Source, Sink>::imbue(const std::locale& loc)
231 iostreams::imbue(src_, loc);
232 iostreams::imbue(sink_, loc);
236 //--------------Implementation of filter_pair---------------------------------//
238 template<typename InputFilter, typename OutputFilter>
239 inline combined_filter<InputFilter, OutputFilter>::combined_filter
240 (const InputFilter& in, const OutputFilter& out) : in_(in), out_(out)
243 #ifndef BOOST_NO_STD_LOCALE
244 template<typename InputFilter, typename OutputFilter>
245 void combined_filter<InputFilter, OutputFilter>::imbue
246 (const std::locale& loc)
248 iostreams::imbue(in_, loc);
249 iostreams::imbue(out_, loc);
254 } // End namespace detail.
256 } } // End namespaces iostreams, boost.
258 #include <boost/iostreams/detail/config/enable_warnings.hpp>
260 #endif // #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED