1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2005-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 #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_TEE_HPP_INCLUDED
15 #include <boost/assert.hpp>
16 #include <boost/config.hpp> // BOOST_DEDUCE_TYPENAME.
17 #include <boost/iostreams/categories.hpp>
18 #include <boost/iostreams/detail/adapter/device_adapter.hpp>
19 #include <boost/iostreams/detail/adapter/filter_adapter.hpp>
20 #include <boost/iostreams/detail/call_traits.hpp>
21 #include <boost/iostreams/detail/execute.hpp>
22 #include <boost/iostreams/detail/functional.hpp> // call_close_all
23 #include <boost/iostreams/operations.hpp>
24 #include <boost/iostreams/pipeline.hpp>
25 #include <boost/iostreams/traits.hpp>
26 #include <boost/static_assert.hpp>
27 #include <boost/type_traits/is_convertible.hpp>
28 #include <boost/type_traits/is_same.hpp>
30 namespace boost { namespace iostreams {
33 // Template name: tee_filter.
34 // Template parameters:
35 // Device - A blocking Sink.
37 template<typename Device>
38 class tee_filter : public detail::filter_adapter<Device> {
40 typedef typename detail::param_type<Device>::type param_type;
41 typedef typename char_type_of<Device>::type char_type;
43 : dual_use_filter_tag,
48 optimally_buffered_tag
51 BOOST_STATIC_ASSERT(is_device<Device>::value);
53 is_convertible< // Using mode_of causes failures on VC6-7.0.
54 BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
58 explicit tee_filter(param_type dev)
59 : detail::filter_adapter<Device>(dev)
62 template<typename Source>
63 std::streamsize read(Source& src, char_type* s, std::streamsize n)
65 std::streamsize result = iostreams::read(src, s, n);
67 std::streamsize result2 = iostreams::write(this->component(), s, result);
68 (void) result2; // Suppress 'unused variable' warning.
69 BOOST_ASSERT(result == result2);
74 template<typename Sink>
75 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
77 std::streamsize result = iostreams::write(snk, s, n);
78 std::streamsize result2 = iostreams::write(this->component(), s, result);
79 (void) result2; // Suppress 'unused variable' warning.
80 BOOST_ASSERT(result == result2);
84 template<typename Next>
85 void close(Next&, BOOST_IOS::openmode)
87 detail::close_all(this->component());
90 template<typename Sink>
93 bool r1 = iostreams::flush(snk);
94 bool r2 = iostreams::flush(this->component());
98 BOOST_IOSTREAMS_PIPABLE(tee_filter, 1)
101 // Template name: tee_device.
102 // Template parameters:
103 // Device - A blocking Device.
104 // Sink - A blocking Sink.
106 template<typename Device, typename Sink>
109 typedef typename detail::param_type<Device>::type device_param;
110 typedef typename detail::param_type<Sink>::type sink_param;
111 typedef typename detail::value_type<Device>::type device_value;
112 typedef typename detail::value_type<Sink>::type sink_value;
113 typedef typename char_type_of<Device>::type char_type;
117 BOOST_DEDUCED_TYPENAME
118 iostreams::category_of<Device>::type,
124 BOOST_STATIC_ASSERT(is_device<Device>::value);
125 BOOST_STATIC_ASSERT(is_device<Sink>::value);
126 BOOST_STATIC_ASSERT((
129 BOOST_DEDUCED_TYPENAME char_type_of<Sink>::type
132 BOOST_STATIC_ASSERT((
134 BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink>::type,
144 optimally_buffered_tag
146 tee_device(device_param device, sink_param sink)
147 : dev_(device), sink_(sink)
149 std::streamsize read(char_type* s, std::streamsize n)
151 BOOST_STATIC_ASSERT((
153 BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, input
156 std::streamsize result1 = iostreams::read(dev_, s, n);
158 std::streamsize result2 = iostreams::write(sink_, s, result1);
159 (void) result1; // Suppress 'unused variable' warning.
161 BOOST_ASSERT(result1 == result2);
165 std::streamsize write(const char_type* s, std::streamsize n)
167 BOOST_STATIC_ASSERT((
169 BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
172 std::streamsize result1 = iostreams::write(dev_, s, n);
173 std::streamsize result2 = iostreams::write(sink_, s, n);
174 (void) result1; // Suppress 'unused variable' warning.
176 BOOST_ASSERT(result1 == n && result2 == n);
181 detail::execute_all( detail::call_close_all(dev_),
182 detail::call_close_all(sink_) );
186 bool r1 = iostreams::flush(dev_);
187 bool r2 = iostreams::flush(sink_);
190 template<typename Locale>
191 void imbue(const Locale& loc)
193 iostreams::imbue(dev_, loc);
194 iostreams::imbue(sink_, loc);
196 std::streamsize optimal_buffer_size() const
198 return (std::max) ( iostreams::optimal_buffer_size(dev_),
199 iostreams::optimal_buffer_size(sink_) );
206 template<typename Sink>
207 tee_filter<Sink> tee(Sink& snk)
208 { return tee_filter<Sink>(snk); }
210 template<typename Sink>
211 tee_filter<Sink> tee(const Sink& snk)
212 { return tee_filter<Sink>(snk); }
214 template<typename Device, typename Sink>
215 tee_device<Device, Sink> tee(Device& dev, Sink& sink)
216 { return tee_device<Device, Sink>(dev, sink); }
218 template<typename Device, typename Sink>
219 tee_device<Device, Sink> tee(const Device& dev, Sink& sink)
220 { return tee_device<Device, Sink>(dev, sink); }
222 template<typename Device, typename Sink>
223 tee_device<Device, Sink> tee(Device& dev, const Sink& sink)
224 { return tee_device<Device, Sink>(dev, sink); }
226 template<typename Device, typename Sink>
227 tee_device<Device, Sink> tee(const Device& dev, const Sink& sink)
228 { return tee_device<Device, Sink>(dev, sink); }
230 } } // End namespaces iostreams, boost.
232 #endif // #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED