File indexing completed on 2025-01-18 09:38:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
0011 #define BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
0012
0013 #if defined(_MSC_VER)
0014 # pragma once
0015 #endif
0016
0017 #include <algorithm> // min.
0018 #include <utility> // pair.
0019 #include <boost/config.hpp> // DEDUCED_TYPENAME.
0020 #include <boost/iostreams/categories.hpp>
0021 #include <boost/iostreams/detail/adapter/direct_adapter.hpp>
0022 #include <boost/iostreams/detail/call_traits.hpp>
0023 #include <boost/iostreams/detail/enable_if_stream.hpp>
0024 #include <boost/iostreams/detail/execute.hpp>
0025 #include <boost/iostreams/detail/functional.hpp>
0026 #include <boost/iostreams/operations.hpp>
0027 #include <boost/iostreams/traits.hpp> // mode_of, is_direct.
0028 #include <boost/mpl/if.hpp>
0029 #include <boost/ref.hpp>
0030 #include <boost/static_assert.hpp>
0031 #include <boost/type_traits/is_convertible.hpp>
0032
0033
0034 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
0035
0036 namespace boost { namespace iostreams {
0037
0038 namespace detail {
0039
0040 template< typename First,
0041 typename Second,
0042 typename FirstMode =
0043 BOOST_DEDUCED_TYPENAME mode_of<First>::type,
0044 typename SecondMode =
0045 BOOST_DEDUCED_TYPENAME mode_of<Second>::type >
0046 struct composite_mode
0047 : select<
0048 is_convertible<SecondMode, FirstMode>, FirstMode,
0049 is_convertible<FirstMode, SecondMode>, SecondMode,
0050 is_convertible<SecondMode, input>, input,
0051 else_, output
0052 >
0053 { };
0054
0055
0056
0057
0058
0059
0060
0061
0062 template< typename Filter,
0063 typename Device,
0064 typename Mode =
0065 BOOST_DEDUCED_TYPENAME composite_mode<Filter, Device>::type >
0066 class composite_device {
0067 private:
0068 typedef typename detail::param_type<Device>::type param_type;
0069 typedef typename mode_of<Filter>::type filter_mode;
0070 typedef typename mode_of<Device>::type device_mode;
0071 typedef typename
0072 iostreams::select<
0073 is_direct<Device>, direct_adapter<Device>,
0074 is_std_io<Device>, Device&,
0075 else_, Device
0076 >::type value_type;
0077 BOOST_STATIC_ASSERT(is_filter<Filter>::value);
0078 BOOST_STATIC_ASSERT(is_device<Device>::value);
0079 public:
0080 typedef typename char_type_of<Filter>::type char_type;
0081 struct category
0082 : Mode,
0083 device_tag,
0084 closable_tag,
0085 flushable_tag,
0086 localizable_tag,
0087 optimally_buffered_tag
0088 { };
0089 composite_device(const Filter& flt, param_type dev);
0090 std::streamsize read(char_type* s, std::streamsize n);
0091 std::streamsize write(const char_type* s, std::streamsize n);
0092 std::streampos seek( stream_offset off, BOOST_IOS::seekdir way,
0093 BOOST_IOS::openmode which =
0094 BOOST_IOS::in | BOOST_IOS::out );
0095
0096 void close();
0097 void close(BOOST_IOS::openmode which);
0098 bool flush();
0099 std::streamsize optimal_buffer_size() const;
0100
0101 template<typename Locale>
0102 void imbue(const Locale& loc)
0103 {
0104 iostreams::imbue(filter_, loc);
0105 iostreams::imbue(device_, loc);
0106 }
0107
0108 Filter& first() { return filter_; }
0109 Device& second() { return device_; }
0110 private:
0111 Filter filter_;
0112 value_type device_;
0113 };
0114
0115
0116
0117
0118
0119
0120
0121
0122 template< typename Filter1,
0123 typename Filter2,
0124 typename Mode =
0125 BOOST_DEDUCED_TYPENAME composite_mode<Filter1, Filter2>::type >
0126 class composite_filter {
0127 private:
0128 typedef reference_wrapper<Filter2> filter_ref;
0129 typedef typename mode_of<Filter1>::type first_mode;
0130 typedef typename mode_of<Filter2>::type second_mode;
0131
0132
0133 BOOST_STATIC_ASSERT(
0134 !(is_convertible<first_mode, dual_use>::value) ||
0135 !(is_convertible<second_mode, input>::value) ||
0136 !(is_convertible<second_mode, output>::value) ||
0137 (is_convertible<second_mode, dual_use>::value)
0138 );
0139 BOOST_STATIC_ASSERT(
0140 !(is_convertible<second_mode, dual_use>::value) ||
0141 !(is_convertible<first_mode, input>::value) ||
0142 !(is_convertible<first_mode, output>::value) ||
0143 (is_convertible<first_mode, dual_use>::value)
0144 );
0145 BOOST_STATIC_ASSERT(is_filter<Filter1>::value);
0146 BOOST_STATIC_ASSERT(is_filter<Filter2>::value);
0147 public:
0148 typedef typename char_type_of<Filter1>::type char_type;
0149 struct category
0150 : Mode,
0151 filter_tag,
0152 multichar_tag,
0153 closable_tag,
0154 flushable_tag,
0155 localizable_tag,
0156 optimally_buffered_tag
0157 { };
0158 composite_filter(const Filter1& filter1, const Filter2& filter2)
0159 : filter1_(filter1), filter2_(filter2)
0160 { }
0161
0162 template<typename Source>
0163 std::streamsize read(Source& src, char_type* s, std::streamsize n)
0164 {
0165 composite_device<filter_ref, Source> cmp(boost::ref(filter2_), src);
0166 return iostreams::read(filter1_, cmp, s, n);
0167 }
0168
0169 template<typename Sink>
0170 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
0171 {
0172 composite_device<filter_ref, Sink> cmp(boost::ref(filter2_), snk);
0173 return iostreams::write(filter1_, cmp, s, n);
0174 }
0175
0176 template<typename Device>
0177 std::streampos seek( Device& dev, stream_offset off, BOOST_IOS::seekdir way,
0178 BOOST_IOS::openmode which =
0179 BOOST_IOS::in | BOOST_IOS::out )
0180 {
0181 composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
0182 return iostreams::seek(filter1_, cmp, off, way, which);
0183 }
0184
0185 template<typename Device>
0186 void close(Device& dev)
0187 {
0188 BOOST_STATIC_ASSERT((!is_convertible<category, two_sequence>::value));
0189 BOOST_STATIC_ASSERT((!is_convertible<category, dual_use>::value));
0190
0191
0192 composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
0193
0194
0195
0196 if (!is_convertible<first_mode, dual_use>::value) {
0197 detail::execute_all(
0198 detail::call_close(filter2_, dev, BOOST_IOS::in),
0199 detail::call_close(filter1_, cmp, BOOST_IOS::in),
0200 detail::call_close(filter1_, cmp, BOOST_IOS::out),
0201 detail::call_close(filter2_, dev, BOOST_IOS::out)
0202 );
0203 } else if (is_convertible<second_mode, input>::value) {
0204 detail::execute_all(
0205 detail::call_close(filter2_, dev, BOOST_IOS::in),
0206 detail::call_close(filter1_, cmp, BOOST_IOS::in)
0207 );
0208 } else {
0209 detail::execute_all(
0210 detail::call_close(filter1_, cmp, BOOST_IOS::out),
0211 detail::call_close(filter2_, dev, BOOST_IOS::out)
0212 );
0213 }
0214 }
0215
0216 template<typename Device>
0217 void close(Device& dev, BOOST_IOS::openmode which)
0218 {
0219 BOOST_STATIC_ASSERT(
0220 (is_convertible<category, two_sequence>::value) ||
0221 (is_convertible<category, dual_use>::value)
0222 );
0223
0224
0225 composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
0226
0227
0228 if ( which == BOOST_IOS::in &&
0229 ( !is_convertible<first_mode, dual_use>::value ||
0230 is_convertible<second_mode, input>::value ) )
0231 {
0232 detail::execute_all(
0233 detail::call_close(filter2_, dev, BOOST_IOS::in),
0234 detail::call_close(filter1_, cmp, BOOST_IOS::in)
0235 );
0236 }
0237
0238
0239 if ( which == BOOST_IOS::out &&
0240 ( !is_convertible<first_mode, dual_use>::value ||
0241 is_convertible<second_mode, output>::value ) )
0242 {
0243 detail::execute_all(
0244 detail::call_close(filter1_, cmp, BOOST_IOS::out),
0245 detail::call_close(filter2_, dev, BOOST_IOS::out)
0246 );
0247 }
0248 }
0249
0250 template<typename Device>
0251 bool flush(Device& dev)
0252 {
0253 composite_device<Filter2, Device> cmp(filter2_, dev);
0254 return iostreams::flush(filter1_, cmp);
0255 }
0256
0257 std::streamsize optimal_buffer_size() const
0258 {
0259 std::streamsize first = iostreams::optimal_buffer_size(filter1_);
0260 std::streamsize second = iostreams::optimal_buffer_size(filter2_);
0261 return first < second ? second : first;
0262 }
0263
0264 template<typename Locale>
0265 void imbue(const Locale& loc)
0266 {
0267 iostreams::imbue(filter1_, loc);
0268 iostreams::imbue(filter2_, loc);
0269 }
0270
0271 Filter1& first() { return filter1_; }
0272 Filter2& second() { return filter2_; }
0273 private:
0274 Filter1 filter1_;
0275 Filter2 filter2_;
0276 };
0277
0278 template<typename Filter, typename FilterOrDevice>
0279 struct composite_traits
0280 : mpl::if_<
0281 is_device<FilterOrDevice>,
0282 composite_device<Filter, FilterOrDevice>,
0283 composite_filter<Filter, FilterOrDevice>
0284 >
0285 { };
0286
0287 }
0288
0289 template<typename Filter, typename FilterOrDevice>
0290 struct composite : detail::composite_traits<Filter, FilterOrDevice>::type {
0291 typedef typename detail::param_type<FilterOrDevice>::type param_type;
0292 typedef typename detail::composite_traits<Filter, FilterOrDevice>::type base;
0293 composite(const Filter& flt, param_type dev)
0294 : base(flt, dev)
0295 { }
0296 };
0297
0298
0299
0300
0301
0302
0303 #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION
0304 # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
0305
0306 template<typename Filter, typename FilterOrDevice>
0307 composite<Filter, FilterOrDevice>
0308 compose( const Filter& filter, const FilterOrDevice& fod
0309 BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
0310 { return composite<Filter, FilterOrDevice>(filter, fod); }
0311
0312 template<typename Filter, typename Ch, typename Tr>
0313 composite< Filter, std::basic_streambuf<Ch, Tr> >
0314 compose(const Filter& filter, std::basic_streambuf<Ch, Tr>& sb)
0315 { return composite< Filter, std::basic_streambuf<Ch, Tr> >(filter, sb); }
0316
0317 template<typename Filter, typename Ch, typename Tr>
0318 composite< Filter, std::basic_istream<Ch, Tr> >
0319 compose(const Filter& filter, std::basic_istream<Ch, Tr>& is)
0320 { return composite< Filter, std::basic_istream<Ch, Tr> >(filter, is); }
0321
0322 template<typename Filter, typename Ch, typename Tr>
0323 composite< Filter, std::basic_ostream<Ch, Tr> >
0324 compose(const Filter& filter, std::basic_ostream<Ch, Tr>& os)
0325 { return composite< Filter, std::basic_ostream<Ch, Tr> >(filter, os); }
0326
0327 template<typename Filter, typename Ch, typename Tr>
0328 composite< Filter, std::basic_iostream<Ch, Tr> >
0329 compose(const Filter& filter, std::basic_iostream<Ch, Tr>& io)
0330 { return composite< Filter, std::basic_iostream<Ch, Tr> >(filter, io); }
0331
0332 # else
0333
0334 template<typename Filter, typename FilterOrDevice>
0335 composite<Filter, FilterOrDevice>
0336 compose( const Filter& filter, const FilterOrDevice& fod
0337 BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
0338 { return composite<Filter, FilterOrDevice>(filter, fod); }
0339
0340 template<typename Filter>
0341 composite<Filter, std::streambuf>
0342 compose(const Filter& filter, std::streambuf& sb)
0343 { return composite<Filter, std::streambuf>(filter, sb); }
0344
0345 template<typename Filter>
0346 composite<Filter, std::istream>
0347 compose(const Filter& filter, std::istream& is)
0348 { return composite<Filter, std::istream>(filter, is); }
0349
0350 template<typename Filter>
0351 composite<Filter, std::ostream>
0352 compose(const Filter& filter, std::ostream& os)
0353 { return composite<Filter, std::ostream>(filter, os); }
0354
0355 template<typename Filter>
0356 composite<Filter, std::iostream>
0357 compose(const Filter& filter, std::iostream& io)
0358 { return composite<Filter, std::iostream>(filter, io); }
0359
0360 # endif
0361 #else
0362
0363 template<typename Filter, typename Stream>
0364 composite<Filter, Stream>
0365 compose(const Filter& flt, const Stream& strm, mpl::true_)
0366 {
0367 return composite<Filter, Stream>(flt, const_cast<Stream&>(strm));
0368 }
0369
0370 template<typename Filter, typename FilterOrDevice>
0371 composite<Filter, FilterOrDevice>
0372 compose(const Filter& flt, const FilterOrDevice& fod, mpl::false_)
0373 { return composite<Filter, FilterOrDevice>(flt, fod); }
0374
0375 template<typename Filter, typename FilterOrDevice>
0376 composite<Filter, FilterOrDevice>
0377 compose( const Filter& flt, const FilterOrDevice& fod
0378 BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
0379 { return compose(flt, fod, is_std_io<FilterOrDevice>()); }
0380
0381 # if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) && \
0382 !defined(__GNUC__)
0383
0384 template<typename Filter, typename FilterOrDevice>
0385 composite<Filter, FilterOrDevice>
0386 compose (const Filter& filter, FilterOrDevice& fod)
0387 { return composite<Filter, FilterOrDevice>(filter, fod); }
0388
0389 # endif
0390 #endif
0391
0392
0393
0394 namespace detail {
0395
0396
0397
0398 template<typename Filter, typename Device, typename Mode>
0399 composite_device<Filter, Device, Mode>::composite_device
0400 (const Filter& flt, param_type dev)
0401 : filter_(flt), device_(dev)
0402 { }
0403
0404 template<typename Filter, typename Device, typename Mode>
0405 inline std::streamsize composite_device<Filter, Device, Mode>::read
0406 (char_type* s, std::streamsize n)
0407 { return iostreams::read(filter_, device_, s, n); }
0408
0409 template<typename Filter, typename Device, typename Mode>
0410 inline std::streamsize composite_device<Filter, Device, Mode>::write
0411 (const char_type* s, std::streamsize n)
0412 { return iostreams::write(filter_, device_, s, n); }
0413
0414 template<typename Filter, typename Device, typename Mode>
0415 std::streampos composite_device<Filter, Device, Mode>::seek
0416 (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
0417 { return iostreams::seek(filter_, device_, off, way, which); }
0418
0419 template<typename Filter, typename Device, typename Mode>
0420 void composite_device<Filter, Device, Mode>::close()
0421 {
0422 BOOST_STATIC_ASSERT((!is_convertible<Mode, two_sequence>::value));
0423 BOOST_STATIC_ASSERT(
0424 !(is_convertible<filter_mode, dual_use>::value) ||
0425 !(is_convertible<device_mode, input>::value) ||
0426 !(is_convertible<device_mode, output>::value)
0427 );
0428
0429
0430
0431 if (!is_convertible<filter_mode, dual_use>::value) {
0432 detail::execute_all(
0433 detail::call_close(device_, BOOST_IOS::in),
0434 detail::call_close(filter_, device_, BOOST_IOS::in),
0435 detail::call_close(filter_, device_, BOOST_IOS::out),
0436 detail::call_close(device_, BOOST_IOS::out)
0437 );
0438 } else if (is_convertible<device_mode, input>::value) {
0439 detail::execute_all(
0440 detail::call_close(device_, BOOST_IOS::in),
0441 detail::call_close(filter_, device_, BOOST_IOS::in)
0442 );
0443 } else {
0444 detail::execute_all(
0445 detail::call_close(filter_, device_, BOOST_IOS::out),
0446 detail::call_close(device_, BOOST_IOS::out)
0447 );
0448 }
0449 }
0450
0451 template<typename Filter, typename Device, typename Mode>
0452 void composite_device<Filter, Device, Mode>::close(BOOST_IOS::openmode which)
0453 {
0454 BOOST_STATIC_ASSERT((is_convertible<Mode, two_sequence>::value));
0455 BOOST_STATIC_ASSERT(!(is_convertible<filter_mode, dual_use>::value));
0456
0457
0458 if (which == BOOST_IOS::in) {
0459 detail::execute_all(
0460 detail::call_close(device_, BOOST_IOS::in),
0461 detail::call_close(filter_, device_, BOOST_IOS::in)
0462 );
0463 }
0464
0465
0466 if (which == BOOST_IOS::out) {
0467 detail::execute_all(
0468 detail::call_close(filter_, device_, BOOST_IOS::out),
0469 detail::call_close(device_, BOOST_IOS::out)
0470 );
0471 }
0472 }
0473
0474 template<typename Filter, typename Device, typename Mode>
0475 bool composite_device<Filter, Device, Mode>::flush()
0476 {
0477 bool r1 = iostreams::flush(filter_, device_);
0478 bool r2 = iostreams::flush(device_);
0479 return r1 && r2;
0480 }
0481
0482 template<typename Filter, typename Device, typename Mode>
0483 std::streamsize
0484 composite_device<Filter, Device, Mode>::optimal_buffer_size() const
0485 { return iostreams::optimal_buffer_size(device_); }
0486
0487 }
0488
0489 } }
0490
0491 #include <boost/iostreams/detail/config/enable_warnings.hpp>
0492
0493 #endif