PageRenderTime 57ms CodeModel.GetById 13ms app.highlight 38ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/iostreams/tee.hpp

http://hadesmem.googlecode.com/
C++ Header | 216 lines | 183 code | 17 blank | 16 comment | 13 complexity | 9a5157d18c11a1fb04a0f9d476973eb3 MD5 | raw file
  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.)
  5
  6// See http://www.boost.org/libs/iostreams for documentation.
  7
  8#ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
  9#define BOOST_IOSTREAMS_TEE_HPP_INCLUDED
 10
 11#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 12# pragma once
 13#endif
 14
 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>
 29
 30namespace boost { namespace iostreams {
 31
 32//
 33// Template name: tee_filter.
 34// Template paramters:
 35//      Device - A blocking Sink.
 36//
 37template<typename Device>
 38class tee_filter : public detail::filter_adapter<Device> {
 39public:
 40    typedef typename detail::param_type<Device>::type  param_type;
 41    typedef typename char_type_of<Device>::type        char_type;
 42    struct category
 43        : dual_use_filter_tag,
 44          multichar_tag,
 45          closable_tag,
 46          flushable_tag,
 47          localizable_tag,
 48          optimally_buffered_tag
 49        { };
 50
 51    BOOST_STATIC_ASSERT(is_device<Device>::value);
 52    BOOST_STATIC_ASSERT((
 53        is_convertible< // Using mode_of causes failures on VC6-7.0.
 54            BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
 55        >::value
 56    ));
 57
 58    explicit tee_filter(param_type dev) 
 59        : detail::filter_adapter<Device>(dev) 
 60        { }
 61
 62    template<typename Source>
 63    std::streamsize read(Source& src, char_type* s, std::streamsize n)
 64    {
 65        std::streamsize result = iostreams::read(src, s, n);
 66        if (result != -1) {
 67            std::streamsize result2 = iostreams::write(this->component(), s, result);
 68            (void) result2; // Suppress 'unused variable' warning.
 69            BOOST_ASSERT(result == result2);
 70        }
 71        return result;
 72    }
 73
 74    template<typename Sink>
 75    std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
 76    {
 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);
 81        return result;
 82    }
 83
 84    template<typename Next>
 85    void close(Next&, BOOST_IOS::openmode)
 86    { 
 87        detail::close_all(this->component());
 88    }
 89
 90    template<typename Sink>
 91    bool flush(Sink& snk)
 92    {
 93        bool r1 = iostreams::flush(snk);
 94        bool r2 = iostreams::flush(this->component());
 95        return r1 && r2;
 96    }
 97};
 98BOOST_IOSTREAMS_PIPABLE(tee_filter, 1)
 99
100//
101// Template name: tee_device.
102// Template paramters:
103//      Device - A blocking Device.
104//      Sink - A blocking Sink.
105//
106template<typename Device, typename Sink>
107class tee_device {
108public:
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;
114    typedef typename
115            mpl::if_<
116                 is_convertible<
117                     BOOST_DEDUCED_TYPENAME 
118                         iostreams::category_of<Device>::type, 
119                     output
120                 >,
121                 output,
122                 input
123            >::type                                    mode;
124    BOOST_STATIC_ASSERT(is_device<Device>::value);
125    BOOST_STATIC_ASSERT(is_device<Sink>::value);
126    BOOST_STATIC_ASSERT((
127        is_same<
128            char_type, 
129            BOOST_DEDUCED_TYPENAME char_type_of<Sink>::type
130        >::value
131    ));
132    BOOST_STATIC_ASSERT((
133        is_convertible<
134            BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink>::type, 
135            output
136        >::value
137    ));
138    struct category
139        : mode,
140          device_tag,
141          closable_tag,
142          flushable_tag,
143          localizable_tag,
144          optimally_buffered_tag
145        { };
146    tee_device(device_param device, sink_param sink) 
147        : dev_(device), sink_(sink)
148        { }
149    std::streamsize read(char_type* s, std::streamsize n)
150    {
151        BOOST_STATIC_ASSERT((
152            is_convertible<
153                BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, input
154            >::value
155        ));
156        std::streamsize result1 = iostreams::read(dev_, s, n);
157        if (result1 != -1) {
158            std::streamsize result2 = iostreams::write(sink_, s, result1);
159            (void) result1; // Suppress 'unused variable' warning.
160            (void) result2;
161            BOOST_ASSERT(result1 == result2);
162        }
163        return result1;
164    }
165    std::streamsize write(const char_type* s, std::streamsize n)
166    {
167        BOOST_STATIC_ASSERT((
168            is_convertible<
169                BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
170            >::value
171        ));
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.
175        (void) result2;
176        BOOST_ASSERT(result1 == n && result2 == n);
177        return n;
178    }
179    void close()
180    {
181        detail::execute_all( detail::call_close_all(dev_),
182                             detail::call_close_all(sink_) );
183    }
184    bool flush()
185    {
186        bool r1 = iostreams::flush(dev_);
187        bool r2 = iostreams::flush(sink_);
188        return r1 && r2;
189    }
190    template<typename Locale>
191    void imbue(const Locale& loc)
192    {
193        iostreams::imbue(dev_, loc);
194        iostreams::imbue(sink_, loc);
195    }
196    std::streamsize optimal_buffer_size() const 
197    {
198        return (std::max) ( iostreams::optimal_buffer_size(dev_), 
199                            iostreams::optimal_buffer_size(sink_) );
200    }
201private:
202    device_value  dev_;
203    sink_value    sink_;
204};
205
206template<typename Sink>
207tee_filter<Sink> tee(const Sink& snk) 
208{ return tee_filter<Sink>(snk); }
209
210template<typename Device, typename Sink>
211tee_device<Device, Sink> tee(const Device& dev, const Sink& sink) 
212{ return tee_device<Device, Sink>(dev, sink); }
213
214} } // End namespaces iostreams, boost.
215
216#endif // #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED