source: NonGTP/Boost/boost/iostreams/tee.hpp @ 857

Revision 857, 5.5 KB checked in by igarcia, 19 years ago (diff)
Line 
1// (C) Copyright Jonathan Turkanis 2005.
2// Distributed under the Boost Software License, Version 1.0. (See accompanying
3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5// See http://www.boost.org/libs/iostreams for documentation.
6
7#ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
8#define BOOST_IOSTREAMS_TEE_HPP_INCLUDED
9
10#if defined(_MSC_VER) && (_MSC_VER >= 1020)
11# pragma once
12#endif
13
14#include <cassert>
15#include <boost/config.hpp>  // BOOST_DEDUCE_TYPENAME.
16#include <boost/iostreams/categories.hpp>
17#include <boost/iostreams/detail/adapter/basic_adapter.hpp>
18#include <boost/iostreams/detail/call_traits.hpp>
19#include <boost/iostreams/detail/closer.hpp>
20#include <boost/iostreams/operations.hpp>
21#include <boost/iostreams/pipeline.hpp>
22#include <boost/iostreams/traits.hpp>
23#include <boost/static_assert.hpp>
24#include <boost/type_traits/is_convertible.hpp>
25#include <boost/type_traits/is_same.hpp>
26
27namespace boost { namespace iostreams {
28
29//
30// Template name: tee_filter.
31// Template paramters:
32//      Device - A blocking Sink.
33//
34template<typename Device>
35class tee_filter : public detail::basic_adapter<Device> {
36public:
37    typedef typename detail::param_type<Device>::type  param_type;
38    typedef typename char_type_of<Device>::type        char_type;
39    struct category
40        : multichar_output_filter_tag,
41          closable_tag,
42          flushable_tag,
43          localizable_tag,
44          optimally_buffered_tag
45        { };
46
47    BOOST_STATIC_ASSERT((
48        is_convertible< // Using mode_of causes failures on VC6-7.0.
49            BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
50        >::value
51    ));
52
53    explicit tee_filter(param_type dev)
54        : detail::basic_adapter<Device>(dev)
55        { }
56
57    template<typename Sink>
58    std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
59    {
60        std::streamsize result = iostreams::write(snk, s, n);
61        std::streamsize result2 = iostreams::write(this->component(), s, result);
62        (void) result2; // Suppress 'unused variable' warning.
63        assert(result == result2);
64        return result;
65    }
66
67    template<typename Next>
68    void close( Next&,
69                BOOST_IOS::openmode which =
70                    BOOST_IOS::in | BOOST_IOS::out )
71    { iostreams::close(this->component(), which); }
72
73    template<typename Sink>
74    bool flush(Sink& snk)
75    {
76        bool r1 = iostreams::flush(snk);
77        bool r2 = iostreams::flush(this->component());
78        return r1 && r2;
79    }
80};
81BOOST_IOSTREAMS_PIPABLE(tee_filter, 1)
82
83//
84// Template name: tee_device.
85// Template paramters:
86//      Sink1 - A blocking Sink.
87//      Sink2 - A blocking Sink.
88//
89template<typename Sink1, typename Sink2>
90class tee_device {
91public:
92    typedef typename detail::param_type<Sink1>::type  param_type1;
93    typedef typename detail::param_type<Sink2>::type  param_type2;
94    typedef typename detail::value_type<Sink1>::type  value_type1;
95    typedef typename detail::value_type<Sink2>::type  value_type2;
96    typedef typename char_type_of<Sink1>::type        char_type;
97    BOOST_STATIC_ASSERT((
98        is_same<
99            char_type,
100            BOOST_DEDUCED_TYPENAME char_type_of<Sink2>::type
101        >::value
102    ));
103    BOOST_STATIC_ASSERT((
104        is_convertible< // Using mode_of causes failures on VC6-7.0.
105            BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink1>::type, output
106        >::value
107    ));
108    BOOST_STATIC_ASSERT((
109        is_convertible< // Using mode_of causes failures on VC6-7.0.
110            BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink2>::type, output
111        >::value
112    ));
113    struct category
114        : output,
115          device_tag,
116          closable_tag,
117          flushable_tag,
118          localizable_tag,
119          optimally_buffered_tag
120        { };
121    tee_device(param_type1 sink1, param_type2 sink2)
122        : sink1_(sink1), sink2_(sink2)
123        { }
124    std::streamsize write(const char_type* s, std::streamsize n)
125    {
126        std::streamsize result1 = iostreams::write(sink1_, s, n);
127        std::streamsize result2 = iostreams::write(sink2_, s, n);
128        (void) result1; // Suppress 'unused variable' warning.
129        (void) result2;
130        assert(result1 == n && result2 == n);
131        return n;
132    }
133    void close(BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out)
134    {
135        detail::external_closer<Sink2> close2(sink2_, which);
136        detail::external_closer<Sink1> close1(sink1_, which);
137    }
138    bool flush()
139    {
140        bool r1 = iostreams::flush(sink1_);
141        bool r2 = iostreams::flush(sink2_);
142        return r1 && r2;
143    }
144    template<typename Locale>
145    void imbue(const Locale& loc)
146    {
147        iostreams::imbue(sink1_, loc);
148        iostreams::imbue(sink2_, loc);
149    }
150    std::streamsize optimal_buffer_size() const
151    {
152        return (std::max) ( iostreams::optimal_buffer_size(sink1_),
153                            iostreams::optimal_buffer_size(sink2_) );
154    }
155private:
156    value_type1 sink1_;
157    value_type2 sink2_;
158};
159
160template<typename Sink>
161tee_filter<Sink> tee(const Sink& snk)
162{ return tee_filter<Sink>(snk); }
163
164template<typename Sink1, typename Sink2>
165tee_device<Sink1, Sink2> tee(const Sink1& sink1, const Sink2& sink2)
166{ return tee_device<Sink1, Sink2>(sink1, sink2); }
167
168} } // End namespaces iostreams, boost.
169
170#endif // #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.