123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- // (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.
- // Note: bidirectional streams are not supported.
- #ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
- #define BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <algorithm> // min.
- #include <utility> // pair.
- #include <boost/config.hpp> // DEDUCED_TYPENAME.
- #include <boost/iostreams/categories.hpp>
- #include <boost/iostreams/detail/adapter/direct_adapter.hpp>
- #include <boost/iostreams/detail/call_traits.hpp>
- #include <boost/iostreams/detail/enable_if_stream.hpp>
- #include <boost/iostreams/detail/execute.hpp>
- #include <boost/iostreams/detail/functional.hpp>
- #include <boost/iostreams/operations.hpp>
- #include <boost/iostreams/traits.hpp> // mode_of, is_direct.
- #include <boost/mpl/if.hpp>
- #include <boost/ref.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/type_traits/is_convertible.hpp>
- // Must come last.
- #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
- namespace boost { namespace iostreams {
- namespace detail {
- template< typename First,
- typename Second,
- typename FirstMode =
- BOOST_DEDUCED_TYPENAME mode_of<First>::type,
- typename SecondMode =
- BOOST_DEDUCED_TYPENAME mode_of<Second>::type >
- struct composite_mode
- : select<
- is_convertible<SecondMode, FirstMode>, FirstMode,
- is_convertible<FirstMode, SecondMode>, SecondMode,
- is_convertible<SecondMode, input>, input,
- else_, output
- >
- { };
- //
- // Template name: composite_device.
- // Description: Provides a Device view of a Filter, Device pair.
- // Template parameters:
- // Filter - A model of Filter.
- // Device - An indirect model of Device.
- //
- template< typename Filter,
- typename Device,
- typename Mode =
- BOOST_DEDUCED_TYPENAME composite_mode<Filter, Device>::type >
- class composite_device {
- private:
- typedef typename detail::param_type<Device>::type param_type;
- typedef typename mode_of<Filter>::type filter_mode;
- typedef typename mode_of<Device>::type device_mode;
- typedef typename
- iostreams::select< // Disambiguation for Tru64.
- is_direct<Device>, direct_adapter<Device>,
- is_std_io<Device>, Device&,
- else_, Device
- >::type value_type;
- BOOST_STATIC_ASSERT(is_filter<Filter>::value);
- BOOST_STATIC_ASSERT(is_device<Device>::value);
- public:
- typedef typename char_type_of<Filter>::type char_type;
- struct category
- : Mode,
- device_tag,
- closable_tag,
- flushable_tag,
- localizable_tag,
- optimally_buffered_tag
- { };
- composite_device(const Filter& flt, param_type dev);
- std::streamsize read(char_type* s, std::streamsize n);
- std::streamsize write(const char_type* s, std::streamsize n);
- std::streampos seek( stream_offset off, BOOST_IOS::seekdir way,
- BOOST_IOS::openmode which =
- BOOST_IOS::in | BOOST_IOS::out );
- void close();
- void close(BOOST_IOS::openmode which);
- bool flush();
- std::streamsize optimal_buffer_size() const;
- template<typename Locale> // Avoid dependency on <locale>
- void imbue(const Locale& loc)
- {
- iostreams::imbue(filter_, loc);
- iostreams::imbue(device_, loc);
- }
- Filter& first() { return filter_; }
- Device& second() { return device_; }
- private:
- Filter filter_;
- value_type device_;
- };
- //
- // Template name: composite_device.
- // Description: Provides a Device view of a Filter, Device pair.
- // Template parameters:
- // Filter - A model of Filter.
- // Device - An indirect model of Device.
- //
- template< typename Filter1,
- typename Filter2,
- typename Mode =
- BOOST_DEDUCED_TYPENAME composite_mode<Filter1, Filter2>::type >
- class composite_filter {
- private:
- typedef reference_wrapper<Filter2> filter_ref;
- typedef typename mode_of<Filter1>::type first_mode;
- typedef typename mode_of<Filter2>::type second_mode;
- // A dual-use filter cannot be composed with a read-write filter
- BOOST_STATIC_ASSERT(
- !(is_convertible<first_mode, dual_use>::value) ||
- !(is_convertible<second_mode, input>::value) ||
- !(is_convertible<second_mode, output>::value) ||
- (is_convertible<second_mode, dual_use>::value)
- );
- BOOST_STATIC_ASSERT(
- !(is_convertible<second_mode, dual_use>::value) ||
- !(is_convertible<first_mode, input>::value) ||
- !(is_convertible<first_mode, output>::value) ||
- (is_convertible<first_mode, dual_use>::value)
- );
- BOOST_STATIC_ASSERT(is_filter<Filter1>::value);
- BOOST_STATIC_ASSERT(is_filter<Filter2>::value);
- public:
- typedef typename char_type_of<Filter1>::type char_type;
- struct category
- : Mode,
- filter_tag,
- multichar_tag,
- closable_tag,
- flushable_tag,
- localizable_tag,
- optimally_buffered_tag
- { };
- composite_filter(const Filter1& filter1, const Filter2& filter2)
- : filter1_(filter1), filter2_(filter2)
- { }
- template<typename Source>
- std::streamsize read(Source& src, char_type* s, std::streamsize n)
- {
- composite_device<filter_ref, Source> cmp(boost::ref(filter2_), src);
- return iostreams::read(filter1_, cmp, s, n);
- }
- template<typename Sink>
- std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
- {
- composite_device<filter_ref, Sink> cmp(boost::ref(filter2_), snk);
- return iostreams::write(filter1_, cmp, s, n);
- }
- template<typename Device>
- std::streampos seek( Device& dev, stream_offset off, BOOST_IOS::seekdir way,
- BOOST_IOS::openmode which =
- BOOST_IOS::in | BOOST_IOS::out )
- {
- composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
- return iostreams::seek(filter1_, cmp, off, way, which);
- }
- template<typename Device>
- void close(Device& dev)
- {
- BOOST_STATIC_ASSERT((!is_convertible<category, two_sequence>::value));
- BOOST_STATIC_ASSERT((!is_convertible<category, dual_use>::value));
- // Create a new device by composing the second filter2_ with dev.
- composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
- // Close input sequences in reverse order and output sequences in
- // forward order
- if (!is_convertible<first_mode, dual_use>::value) {
- detail::execute_all(
- detail::call_close(filter2_, dev, BOOST_IOS::in),
- detail::call_close(filter1_, cmp, BOOST_IOS::in),
- detail::call_close(filter1_, cmp, BOOST_IOS::out),
- detail::call_close(filter2_, dev, BOOST_IOS::out)
- );
- } else if (is_convertible<second_mode, input>::value) {
- detail::execute_all(
- detail::call_close(filter2_, dev, BOOST_IOS::in),
- detail::call_close(filter1_, cmp, BOOST_IOS::in)
- );
- } else {
- detail::execute_all(
- detail::call_close(filter1_, cmp, BOOST_IOS::out),
- detail::call_close(filter2_, dev, BOOST_IOS::out)
- );
- }
- }
- template<typename Device>
- void close(Device& dev, BOOST_IOS::openmode which)
- {
- BOOST_STATIC_ASSERT(
- (is_convertible<category, two_sequence>::value) ||
- (is_convertible<category, dual_use>::value)
- );
- // Create a new device by composing the second filter2_ with dev.
- composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
- // Close input sequences in reverse order
- if ( which == BOOST_IOS::in &&
- ( !is_convertible<first_mode, dual_use>::value ||
- is_convertible<second_mode, input>::value ) )
- {
- detail::execute_all(
- detail::call_close(filter2_, dev, BOOST_IOS::in),
- detail::call_close(filter1_, cmp, BOOST_IOS::in)
- );
- }
- // Close output sequences in forward order
- if ( which == BOOST_IOS::out &&
- ( !is_convertible<first_mode, dual_use>::value ||
- is_convertible<second_mode, output>::value ) )
- {
- detail::execute_all(
- detail::call_close(filter1_, cmp, BOOST_IOS::out),
- detail::call_close(filter2_, dev, BOOST_IOS::out)
- );
- }
- }
- template<typename Device>
- bool flush(Device& dev)
- {
- composite_device<Filter2, Device> cmp(filter2_, dev);
- return iostreams::flush(filter1_, cmp);
- }
- std::streamsize optimal_buffer_size() const
- {
- std::streamsize first = iostreams::optimal_buffer_size(filter1_);
- std::streamsize second = iostreams::optimal_buffer_size(filter2_);
- return first < second ? second : first;
- }
- template<typename Locale> // Avoid dependency on <locale>
- void imbue(const Locale& loc)
- { // To do: consider using RAII.
- iostreams::imbue(filter1_, loc);
- iostreams::imbue(filter2_, loc);
- }
- Filter1& first() { return filter1_; }
- Filter2& second() { return filter2_; }
- private:
- Filter1 filter1_;
- Filter2 filter2_;
- };
- template<typename Filter, typename FilterOrDevice>
- struct composite_traits
- : mpl::if_<
- is_device<FilterOrDevice>,
- composite_device<Filter, FilterOrDevice>,
- composite_filter<Filter, FilterOrDevice>
- >
- { };
- } // End namespace detail.
- template<typename Filter, typename FilterOrDevice>
- struct composite : detail::composite_traits<Filter, FilterOrDevice>::type {
- typedef typename detail::param_type<FilterOrDevice>::type param_type;
- typedef typename detail::composite_traits<Filter, FilterOrDevice>::type base;
- composite(const Filter& flt, param_type dev)
- : base(flt, dev)
- { }
- };
- //--------------Implementation of compose-------------------------------------//
- // Note: The following workarounds are patterned after resolve.hpp. It has not
- // yet been confirmed that they are necessary.
- #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //-------------------------//
- # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------//
- template<typename Filter, typename FilterOrDevice>
- composite<Filter, FilterOrDevice>
- compose( const Filter& filter, const FilterOrDevice& fod
- BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
- { return composite<Filter, FilterOrDevice>(filter, fod); }
- template<typename Filter, typename Ch, typename Tr>
- composite< Filter, std::basic_streambuf<Ch, Tr> >
- compose(const Filter& filter, std::basic_streambuf<Ch, Tr>& sb)
- { return composite< Filter, std::basic_streambuf<Ch, Tr> >(filter, sb); }
- template<typename Filter, typename Ch, typename Tr>
- composite< Filter, std::basic_istream<Ch, Tr> >
- compose(const Filter& filter, std::basic_istream<Ch, Tr>& is)
- { return composite< Filter, std::basic_istream<Ch, Tr> >(filter, is); }
- template<typename Filter, typename Ch, typename Tr>
- composite< Filter, std::basic_ostream<Ch, Tr> >
- compose(const Filter& filter, std::basic_ostream<Ch, Tr>& os)
- { return composite< Filter, std::basic_ostream<Ch, Tr> >(filter, os); }
- template<typename Filter, typename Ch, typename Tr>
- composite< Filter, std::basic_iostream<Ch, Tr> >
- compose(const Filter& filter, std::basic_iostream<Ch, Tr>& io)
- { return composite< Filter, std::basic_iostream<Ch, Tr> >(filter, io); }
- # else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------//
- template<typename Filter, typename FilterOrDevice>
- composite<Filter, FilterOrDevice>
- compose( const Filter& filter, const FilterOrDevice& fod
- BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
- { return composite<Filter, FilterOrDevice>(filter, fod); }
- template<typename Filter>
- composite<Filter, std::streambuf>
- compose(const Filter& filter, std::streambuf& sb)
- { return composite<Filter, std::streambuf>(filter, sb); }
- template<typename Filter>
- composite<Filter, std::istream>
- compose(const Filter& filter, std::istream& is)
- { return composite<Filter, std::istream>(filter, is); }
- template<typename Filter>
- composite<Filter, std::ostream>
- compose(const Filter& filter, std::ostream& os)
- { return composite<Filter, std::ostream>(filter, os); }
- template<typename Filter>
- composite<Filter, std::iostream>
- compose(const Filter& filter, std::iostream& io)
- { return composite<Filter, std::iostream>(filter, io); }
- # endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------//
- #else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //----------------//
- template<typename Filter, typename Stream>
- composite<Filter, Stream>
- compose(const Filter& flt, const Stream& strm, mpl::true_)
- { // Bad overload resolution.
- return composite<Filter, Stream>(flt, const_cast<Stream&>(strm));
- }
- template<typename Filter, typename FilterOrDevice>
- composite<Filter, FilterOrDevice>
- compose(const Filter& flt, const FilterOrDevice& fod, mpl::false_)
- { return composite<Filter, FilterOrDevice>(flt, fod); }
- template<typename Filter, typename FilterOrDevice>
- composite<Filter, FilterOrDevice>
- compose( const Filter& flt, const FilterOrDevice& fod
- BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
- { return compose(flt, fod, is_std_io<FilterOrDevice>()); }
- # if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) && \
- !defined(__GNUC__) // ---------------------------------------------------//
- template<typename Filter, typename FilterOrDevice>
- composite<Filter, FilterOrDevice>
- compose (const Filter& filter, FilterOrDevice& fod)
- { return composite<Filter, FilterOrDevice>(filter, fod); }
- # endif // Borland 5.x or GCC //--------------------------------//
- #endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------//
- //----------------------------------------------------------------------------//
- namespace detail {
- //--------------Implementation of composite_device---------------------------//
- template<typename Filter, typename Device, typename Mode>
- composite_device<Filter, Device, Mode>::composite_device
- (const Filter& flt, param_type dev)
- : filter_(flt), device_(dev)
- { }
- template<typename Filter, typename Device, typename Mode>
- inline std::streamsize composite_device<Filter, Device, Mode>::read
- (char_type* s, std::streamsize n)
- { return iostreams::read(filter_, device_, s, n); }
- template<typename Filter, typename Device, typename Mode>
- inline std::streamsize composite_device<Filter, Device, Mode>::write
- (const char_type* s, std::streamsize n)
- { return iostreams::write(filter_, device_, s, n); }
- template<typename Filter, typename Device, typename Mode>
- std::streampos composite_device<Filter, Device, Mode>::seek
- (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
- { return iostreams::seek(filter_, device_, off, way, which); }
- template<typename Filter, typename Device, typename Mode>
- void composite_device<Filter, Device, Mode>::close()
- {
- BOOST_STATIC_ASSERT((!is_convertible<Mode, two_sequence>::value));
- BOOST_STATIC_ASSERT(
- !(is_convertible<filter_mode, dual_use>::value) ||
- !(is_convertible<device_mode, input>::value) ||
- !(is_convertible<device_mode, output>::value)
- );
- // Close input sequences in reverse order and output sequences
- // in forward order
- if (!is_convertible<filter_mode, dual_use>::value) {
- detail::execute_all(
- detail::call_close(device_, BOOST_IOS::in),
- detail::call_close(filter_, device_, BOOST_IOS::in),
- detail::call_close(filter_, device_, BOOST_IOS::out),
- detail::call_close(device_, BOOST_IOS::out)
- );
- } else if (is_convertible<device_mode, input>::value) {
- detail::execute_all(
- detail::call_close(device_, BOOST_IOS::in),
- detail::call_close(filter_, device_, BOOST_IOS::in)
- );
- } else {
- detail::execute_all(
- detail::call_close(filter_, device_, BOOST_IOS::out),
- detail::call_close(device_, BOOST_IOS::out)
- );
- }
- }
- template<typename Filter, typename Device, typename Mode>
- void composite_device<Filter, Device, Mode>::close(BOOST_IOS::openmode which)
- {
- BOOST_STATIC_ASSERT((is_convertible<Mode, two_sequence>::value));
- BOOST_STATIC_ASSERT(!(is_convertible<filter_mode, dual_use>::value));
- // Close input sequences in reverse order
- if (which == BOOST_IOS::in) {
- detail::execute_all(
- detail::call_close(device_, BOOST_IOS::in),
- detail::call_close(filter_, device_, BOOST_IOS::in)
- );
- }
- // Close output sequences in forward order
- if (which == BOOST_IOS::out) {
- detail::execute_all(
- detail::call_close(filter_, device_, BOOST_IOS::out),
- detail::call_close(device_, BOOST_IOS::out)
- );
- }
- }
- template<typename Filter, typename Device, typename Mode>
- bool composite_device<Filter, Device, Mode>::flush()
- {
- bool r1 = iostreams::flush(filter_, device_);
- bool r2 = iostreams::flush(device_);
- return r1 && r2;
- }
- template<typename Filter, typename Device, typename Mode>
- std::streamsize
- composite_device<Filter, Device, Mode>::optimal_buffer_size() const
- { return iostreams::optimal_buffer_size(device_); }
- } // End namespace detail.
- } } // End namespaces iostreams, boost.
- #include <boost/iostreams/detail/config/enable_warnings.hpp>
- #endif // #ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
|