123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
- // (C) Copyright 2005-2007 Jonathan Turkanis
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
- // See http://www.boost.org/libs/iostreams for documentation.
- #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
- #define BOOST_IOSTREAMS_TEE_HPP_INCLUDED
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <boost/assert.hpp>
- #include <boost/config.hpp> // BOOST_DEDUCE_TYPENAME.
- #include <boost/iostreams/categories.hpp>
- #include <boost/iostreams/detail/adapter/device_adapter.hpp>
- #include <boost/iostreams/detail/adapter/filter_adapter.hpp>
- #include <boost/iostreams/detail/call_traits.hpp>
- #include <boost/iostreams/detail/execute.hpp>
- #include <boost/iostreams/detail/functional.hpp> // call_close_all
- #include <boost/iostreams/operations.hpp>
- #include <boost/iostreams/pipeline.hpp>
- #include <boost/iostreams/traits.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/type_traits/is_convertible.hpp>
- #include <boost/type_traits/is_same.hpp>
- namespace boost { namespace iostreams {
- //
- // Template name: tee_filter.
- // Template parameters:
- // Device - A blocking Sink.
- //
- template<typename Device>
- class tee_filter : public detail::filter_adapter<Device> {
- public:
- typedef typename detail::param_type<Device>::type param_type;
- typedef typename char_type_of<Device>::type char_type;
- struct category
- : dual_use_filter_tag,
- multichar_tag,
- closable_tag,
- flushable_tag,
- localizable_tag,
- optimally_buffered_tag
- { };
- BOOST_STATIC_ASSERT(is_device<Device>::value);
- BOOST_STATIC_ASSERT((
- is_convertible< // Using mode_of causes failures on VC6-7.0.
- BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
- >::value
- ));
- explicit tee_filter(param_type dev)
- : detail::filter_adapter<Device>(dev)
- { }
- template<typename Source>
- std::streamsize read(Source& src, char_type* s, std::streamsize n)
- {
- std::streamsize result = iostreams::read(src, s, n);
- if (result != -1) {
- std::streamsize result2 = iostreams::write(this->component(), s, result);
- (void) result2; // Suppress 'unused variable' warning.
- BOOST_ASSERT(result == result2);
- }
- return result;
- }
- template<typename Sink>
- std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
- {
- std::streamsize result = iostreams::write(snk, s, n);
- std::streamsize result2 = iostreams::write(this->component(), s, result);
- (void) result2; // Suppress 'unused variable' warning.
- BOOST_ASSERT(result == result2);
- return result;
- }
- template<typename Next>
- void close(Next&, BOOST_IOS::openmode)
- {
- detail::close_all(this->component());
- }
- template<typename Sink>
- bool flush(Sink& snk)
- {
- bool r1 = iostreams::flush(snk);
- bool r2 = iostreams::flush(this->component());
- return r1 && r2;
- }
- };
- BOOST_IOSTREAMS_PIPABLE(tee_filter, 1)
- //
- // Template name: tee_device.
- // Template parameters:
- // Device - A blocking Device.
- // Sink - A blocking Sink.
- //
- template<typename Device, typename Sink>
- class tee_device {
- public:
- typedef typename detail::param_type<Device>::type device_param;
- typedef typename detail::param_type<Sink>::type sink_param;
- typedef typename detail::value_type<Device>::type device_value;
- typedef typename detail::value_type<Sink>::type sink_value;
- typedef typename char_type_of<Device>::type char_type;
- typedef typename
- mpl::if_<
- is_convertible<
- BOOST_DEDUCED_TYPENAME
- iostreams::category_of<Device>::type,
- output
- >,
- output,
- input
- >::type mode;
- BOOST_STATIC_ASSERT(is_device<Device>::value);
- BOOST_STATIC_ASSERT(is_device<Sink>::value);
- BOOST_STATIC_ASSERT((
- is_same<
- char_type,
- BOOST_DEDUCED_TYPENAME char_type_of<Sink>::type
- >::value
- ));
- BOOST_STATIC_ASSERT((
- is_convertible<
- BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink>::type,
- output
- >::value
- ));
- struct category
- : mode,
- device_tag,
- closable_tag,
- flushable_tag,
- localizable_tag,
- optimally_buffered_tag
- { };
- tee_device(device_param device, sink_param sink)
- : dev_(device), sink_(sink)
- { }
- std::streamsize read(char_type* s, std::streamsize n)
- {
- BOOST_STATIC_ASSERT((
- is_convertible<
- BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, input
- >::value
- ));
- std::streamsize result1 = iostreams::read(dev_, s, n);
- if (result1 != -1) {
- std::streamsize result2 = iostreams::write(sink_, s, result1);
- (void) result1; // Suppress 'unused variable' warning.
- (void) result2;
- BOOST_ASSERT(result1 == result2);
- }
- return result1;
- }
- std::streamsize write(const char_type* s, std::streamsize n)
- {
- BOOST_STATIC_ASSERT((
- is_convertible<
- BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
- >::value
- ));
- std::streamsize result1 = iostreams::write(dev_, s, n);
- std::streamsize result2 = iostreams::write(sink_, s, n);
- (void) result1; // Suppress 'unused variable' warning.
- (void) result2;
- BOOST_ASSERT(result1 == n && result2 == n);
- return n;
- }
- void close()
- {
- detail::execute_all( detail::call_close_all(dev_),
- detail::call_close_all(sink_) );
- }
- bool flush()
- {
- bool r1 = iostreams::flush(dev_);
- bool r2 = iostreams::flush(sink_);
- return r1 && r2;
- }
- template<typename Locale>
- void imbue(const Locale& loc)
- {
- iostreams::imbue(dev_, loc);
- iostreams::imbue(sink_, loc);
- }
- std::streamsize optimal_buffer_size() const
- {
- return (std::max) ( iostreams::optimal_buffer_size(dev_),
- iostreams::optimal_buffer_size(sink_) );
- }
- private:
- device_value dev_;
- sink_value sink_;
- };
- template<typename Sink>
- tee_filter<Sink> tee(Sink& snk)
- { return tee_filter<Sink>(snk); }
- template<typename Sink>
- tee_filter<Sink> tee(const Sink& snk)
- { return tee_filter<Sink>(snk); }
- template<typename Device, typename Sink>
- tee_device<Device, Sink> tee(Device& dev, Sink& sink)
- { return tee_device<Device, Sink>(dev, sink); }
- template<typename Device, typename Sink>
- tee_device<Device, Sink> tee(const Device& dev, Sink& sink)
- { return tee_device<Device, Sink>(dev, sink); }
- template<typename Device, typename Sink>
- tee_device<Device, Sink> tee(Device& dev, const Sink& sink)
- { return tee_device<Device, Sink>(dev, sink); }
- template<typename Device, typename Sink>
- tee_device<Device, Sink> tee(const Device& dev, const Sink& sink)
- { return tee_device<Device, Sink>(dev, sink); }
- } } // End namespaces iostreams, boost.
- #endif // #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
|