| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 | // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)// (C) Copyright 2003-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.// Contains: The function template copy, which reads data from a Source // and writes it to a Sink until the end of the sequence is reached, returning // the number of characters transfered.// The implementation is complicated by the need to handle smart adapters// and direct devices.#ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED#define BOOST_IOSTREAMS_COPY_HPP_INCLUDED#if defined(_MSC_VER)# pragma once#endif              #include <boost/config.hpp>                 // Make sure ptrdiff_t is in std.#include <algorithm>                        // copy, min.#include <cstddef>                          // ptrdiff_t.#include <utility>                          // pair.#include <boost/bind.hpp>#include <boost/detail/workaround.hpp>#include <boost/iostreams/chain.hpp>#include <boost/iostreams/constants.hpp>#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>        #include <boost/iostreams/detail/buffer.hpp>#include <boost/iostreams/detail/enable_if_stream.hpp>  #include <boost/iostreams/detail/execute.hpp>#include <boost/iostreams/detail/functional.hpp>#include <boost/iostreams/detail/ios.hpp>   // failure, streamsize.                   #include <boost/iostreams/detail/resolve.hpp>                   #include <boost/iostreams/detail/wrap_unwrap.hpp>#include <boost/iostreams/operations.hpp>  // read, write, close.#include <boost/iostreams/pipeline.hpp>#include <boost/static_assert.hpp>  #include <boost/type_traits/is_same.hpp> namespace boost { namespace iostreams {namespace detail {    // The following four overloads of copy_impl() optimize     // copying in the case that one or both of the two devices    // models Direct (see     // http://www.boost.org/libs/iostreams/doc/index.html?path=4.1.1.4)// Copy from a direct source to a direct sinktemplate<typename Source, typename Sink>std::streamsize copy_impl( Source& src, Sink& snk,                            std::streamsize /* buffer_size */,                           mpl::true_, mpl::true_ ){       using namespace std;    typedef typename char_type_of<Source>::type  char_type;    typedef std::pair<char_type*, char_type*>    pair_type;    pair_type p1 = iostreams::input_sequence(src);    pair_type p2 = iostreams::output_sequence(snk);    std::streamsize total =         static_cast<std::streamsize>(            (std::min)(p1.second - p1.first, p2.second - p2.first)        );    std::copy(p1.first, p1.first + total, p2.first);    return total;}// Copy from a direct source to an indirect sinktemplate<typename Source, typename Sink>std::streamsize copy_impl( Source& src, Sink& snk,                            std::streamsize /* buffer_size */,                           mpl::true_, mpl::false_ ){    using namespace std;    typedef typename char_type_of<Source>::type  char_type;    typedef std::pair<char_type*, char_type*>    pair_type;    pair_type p = iostreams::input_sequence(src);    std::streamsize size, total;    for ( total = 0, size = static_cast<std::streamsize>(p.second - p.first);          total < size; )    {        std::streamsize amt =             iostreams::write(snk, p.first + total, size - total);         total += amt;    }    return total;}// Copy from an indirect source to a direct sinktemplate<typename Source, typename Sink>std::streamsize copy_impl( Source& src, Sink& snk,                            std::streamsize buffer_size,                           mpl::false_, mpl::true_ ){    typedef typename char_type_of<Source>::type  char_type;    typedef std::pair<char_type*, char_type*>    pair_type;    detail::basic_buffer<char_type>  buf(buffer_size);    pair_type                        p = snk.output_sequence();    std::streamsize                  total = 0;    std::ptrdiff_t                   capacity = p.second - p.first;    while (true) {        std::streamsize amt =             iostreams::read(                src,                 buf.data(),                buffer_size < capacity - total ?                    buffer_size :                    static_cast<std::streamsize>(capacity - total)            );        if (amt == -1)            break;        std::copy(buf.data(), buf.data() + amt, p.first + total);        total += amt;    }    return total;}// Copy from an indirect source to an indirect sinktemplate<typename Source, typename Sink>std::streamsize copy_impl( Source& src, Sink& snk,                            std::streamsize buffer_size,                           mpl::false_, mpl::false_ ){     typedef typename char_type_of<Source>::type char_type;    detail::basic_buffer<char_type>  buf(buffer_size);    non_blocking_adapter<Sink>       nb(snk);    std::streamsize                  total = 0;    bool                             done = false;    while (!done) {        std::streamsize amt;        done = (amt = iostreams::read(src, buf.data(), buffer_size)) == -1;        if (amt != -1) {            iostreams::write(nb, buf.data(), amt);            total += amt;        }    }    return total;}    // The following function object is used with     // boost::iostreams::detail::execute() in the primary     // overload of copy_impl(), below// Function object that delegates to one of the above four // overloads of compl_impl()template<typename Source, typename Sink>class copy_operation {public:    typedef std::streamsize result_type;    copy_operation(Source& src, Sink& snk, std::streamsize buffer_size)        : src_(src), snk_(snk), buffer_size_(buffer_size)        { }    std::streamsize operator()()     {        return copy_impl( src_, snk_, buffer_size_,                           is_direct<Source>(), is_direct<Sink>() );    }private:    copy_operation& operator=(const copy_operation&);    Source&          src_;    Sink&            snk_;    std::streamsize  buffer_size_;};// Primary overload of copy_impl. Delegates to one of the above four // overloads of compl_impl(), depending on which of the two given // devices, if any, models Direct (see // http://www.boost.org/libs/iostreams/doc/index.html?path=4.1.1.4)template<typename Source, typename Sink>std::streamsize copy_impl(Source src, Sink snk, std::streamsize buffer_size){    using namespace std;    typedef typename char_type_of<Source>::type  src_char;    typedef typename char_type_of<Sink>::type    snk_char;    BOOST_STATIC_ASSERT((is_same<src_char, snk_char>::value));    return detail::execute_all(               copy_operation<Source, Sink>(src, snk, buffer_size),               detail::call_close_all(src),               detail::call_close_all(snk)           );}} // End namespace detail.                    //------------------Definition of copy----------------------------------------//// Overload of copy() for the case where neither the source nor the sink is// a standard stream or stream buffertemplate<typename Source, typename Sink>std::streamsizecopy( const Source& src, const Sink& snk,      std::streamsize buffer_size = default_device_buffer_size      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source)      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) ){     typedef typename char_type_of<Source>::type char_type;    return detail::copy_impl( detail::resolve<input, char_type>(src),                               detail::resolve<output, char_type>(snk),                               buffer_size ); }// Overload of copy() for the case where the source, but not the sink, is// a standard stream or stream buffertemplate<typename Source, typename Sink>std::streamsizecopy( Source& src, const Sink& snk,      std::streamsize buffer_size = default_device_buffer_size      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source)      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) ) {     typedef typename char_type_of<Source>::type char_type;    return detail::copy_impl( detail::wrap(src),                               detail::resolve<output, char_type>(snk),                               buffer_size );}// Overload of copy() for the case where the sink, but not the source, is// a standard stream or stream buffertemplate<typename Source, typename Sink>std::streamsizecopy( const Source& src, Sink& snk,      std::streamsize buffer_size = default_device_buffer_size      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source)      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) ) {     typedef typename char_type_of<Source>::type char_type;    return detail::copy_impl( detail::resolve<input, char_type>(src),                               detail::wrap(snk), buffer_size );}// Overload of copy() for the case where neither the source nor the sink is// a standard stream or stream buffertemplate<typename Source, typename Sink>std::streamsizecopy( Source& src, Sink& snk,      std::streamsize buffer_size = default_device_buffer_size      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source)      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) ) {     return detail::copy_impl(detail::wrap(src), detail::wrap(snk), buffer_size);}} } // End namespaces iostreams, boost.#endif // #ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED
 |