| 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(__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::streamsizecomposite_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
 |