File indexing completed on 2025-01-30 09:44:34
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED
0009 #define BOOST_IOSTREAMS_TEE_HPP_INCLUDED
0010
0011 #if defined(_MSC_VER)
0012 # pragma once
0013 #endif
0014
0015 #include <boost/assert.hpp>
0016 #include <boost/config.hpp> // BOOST_DEDUCE_TYPENAME.
0017 #include <boost/iostreams/categories.hpp>
0018 #include <boost/iostreams/detail/adapter/device_adapter.hpp>
0019 #include <boost/iostreams/detail/adapter/filter_adapter.hpp>
0020 #include <boost/iostreams/detail/call_traits.hpp>
0021 #include <boost/iostreams/detail/execute.hpp>
0022 #include <boost/iostreams/detail/functional.hpp> // call_close_all
0023 #include <boost/iostreams/operations.hpp>
0024 #include <boost/iostreams/pipeline.hpp>
0025 #include <boost/iostreams/traits.hpp>
0026 #include <boost/static_assert.hpp>
0027 #include <boost/type_traits/is_convertible.hpp>
0028 #include <boost/type_traits/is_same.hpp>
0029
0030 namespace boost { namespace iostreams {
0031
0032
0033
0034
0035
0036
0037 template<typename Device>
0038 class tee_filter : public detail::filter_adapter<Device> {
0039 public:
0040 typedef typename detail::param_type<Device>::type param_type;
0041 typedef typename char_type_of<Device>::type char_type;
0042 struct category
0043 : dual_use_filter_tag,
0044 multichar_tag,
0045 closable_tag,
0046 flushable_tag,
0047 localizable_tag,
0048 optimally_buffered_tag
0049 { };
0050
0051 BOOST_STATIC_ASSERT(is_device<Device>::value);
0052 BOOST_STATIC_ASSERT((
0053 is_convertible<
0054 BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
0055 >::value
0056 ));
0057
0058 explicit tee_filter(param_type dev)
0059 : detail::filter_adapter<Device>(dev)
0060 { }
0061
0062 template<typename Source>
0063 std::streamsize read(Source& src, char_type* s, std::streamsize n)
0064 {
0065 std::streamsize result = iostreams::read(src, s, n);
0066 if (result != -1) {
0067 std::streamsize result2 = iostreams::write(this->component(), s, result);
0068 (void) result2;
0069 BOOST_ASSERT(result == result2);
0070 }
0071 return result;
0072 }
0073
0074 template<typename Sink>
0075 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
0076 {
0077 std::streamsize result = iostreams::write(snk, s, n);
0078 std::streamsize result2 = iostreams::write(this->component(), s, result);
0079 (void) result2;
0080 BOOST_ASSERT(result == result2);
0081 return result;
0082 }
0083
0084 template<typename Next>
0085 void close(Next&, BOOST_IOS::openmode)
0086 {
0087 detail::close_all(this->component());
0088 }
0089
0090 template<typename Sink>
0091 bool flush(Sink& snk)
0092 {
0093 bool r1 = iostreams::flush(snk);
0094 bool r2 = iostreams::flush(this->component());
0095 return r1 && r2;
0096 }
0097 };
0098 BOOST_IOSTREAMS_PIPABLE(tee_filter, 1)
0099
0100
0101
0102
0103
0104
0105
0106 template<typename Device, typename Sink>
0107 class tee_device {
0108 public:
0109 typedef typename detail::param_type<Device>::type device_param;
0110 typedef typename detail::param_type<Sink>::type sink_param;
0111 typedef typename detail::value_type<Device>::type device_value;
0112 typedef typename detail::value_type<Sink>::type sink_value;
0113 typedef typename char_type_of<Device>::type char_type;
0114 typedef typename
0115 mpl::if_<
0116 is_convertible<
0117 BOOST_DEDUCED_TYPENAME
0118 iostreams::category_of<Device>::type,
0119 output
0120 >,
0121 output,
0122 input
0123 >::type mode;
0124 BOOST_STATIC_ASSERT(is_device<Device>::value);
0125 BOOST_STATIC_ASSERT(is_device<Sink>::value);
0126 BOOST_STATIC_ASSERT((
0127 is_same<
0128 char_type,
0129 BOOST_DEDUCED_TYPENAME char_type_of<Sink>::type
0130 >::value
0131 ));
0132 BOOST_STATIC_ASSERT((
0133 is_convertible<
0134 BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink>::type,
0135 output
0136 >::value
0137 ));
0138 struct category
0139 : mode,
0140 device_tag,
0141 closable_tag,
0142 flushable_tag,
0143 localizable_tag,
0144 optimally_buffered_tag
0145 { };
0146 tee_device(device_param device, sink_param sink)
0147 : dev_(device), sink_(sink)
0148 { }
0149 std::streamsize read(char_type* s, std::streamsize n)
0150 {
0151 BOOST_STATIC_ASSERT((
0152 is_convertible<
0153 BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, input
0154 >::value
0155 ));
0156 std::streamsize result1 = iostreams::read(dev_, s, n);
0157 if (result1 != -1) {
0158 std::streamsize result2 = iostreams::write(sink_, s, result1);
0159 (void) result1;
0160 (void) result2;
0161 BOOST_ASSERT(result1 == result2);
0162 }
0163 return result1;
0164 }
0165 std::streamsize write(const char_type* s, std::streamsize n)
0166 {
0167 BOOST_STATIC_ASSERT((
0168 is_convertible<
0169 BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
0170 >::value
0171 ));
0172 std::streamsize result1 = iostreams::write(dev_, s, n);
0173 std::streamsize result2 = iostreams::write(sink_, s, n);
0174 (void) result1;
0175 (void) result2;
0176 BOOST_ASSERT(result1 == n && result2 == n);
0177 return n;
0178 }
0179 void close()
0180 {
0181 detail::execute_all( detail::call_close_all(dev_),
0182 detail::call_close_all(sink_) );
0183 }
0184 bool flush()
0185 {
0186 bool r1 = iostreams::flush(dev_);
0187 bool r2 = iostreams::flush(sink_);
0188 return r1 && r2;
0189 }
0190 template<typename Locale>
0191 void imbue(const Locale& loc)
0192 {
0193 iostreams::imbue(dev_, loc);
0194 iostreams::imbue(sink_, loc);
0195 }
0196 std::streamsize optimal_buffer_size() const
0197 {
0198 return (std::max) ( iostreams::optimal_buffer_size(dev_),
0199 iostreams::optimal_buffer_size(sink_) );
0200 }
0201 private:
0202 device_value dev_;
0203 sink_value sink_;
0204 };
0205
0206 template<typename Sink>
0207 tee_filter<Sink> tee(Sink& snk)
0208 { return tee_filter<Sink>(snk); }
0209
0210 template<typename Sink>
0211 tee_filter<Sink> tee(const Sink& snk)
0212 { return tee_filter<Sink>(snk); }
0213
0214 template<typename Device, typename Sink>
0215 tee_device<Device, Sink> tee(Device& dev, Sink& sink)
0216 { return tee_device<Device, Sink>(dev, sink); }
0217
0218 template<typename Device, typename Sink>
0219 tee_device<Device, Sink> tee(const Device& dev, Sink& sink)
0220 { return tee_device<Device, Sink>(dev, sink); }
0221
0222 template<typename Device, typename Sink>
0223 tee_device<Device, Sink> tee(Device& dev, const Sink& sink)
0224 { return tee_device<Device, Sink>(dev, sink); }
0225
0226 template<typename Device, typename Sink>
0227 tee_device<Device, Sink> tee(const Device& dev, const Sink& sink)
0228 { return tee_device<Device, Sink>(dev, sink); }
0229
0230 } }
0231
0232 #endif