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/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 sink
- template<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 sink
- template<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 sink
- template<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 sink
- template<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 buffer
- template<typename Source, typename Sink>
- std::streamsize
- copy( 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 buffer
- template<typename Source, typename Sink>
- std::streamsize
- copy( 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 buffer
- template<typename Source, typename Sink>
- std::streamsize
- copy( 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 buffer
- template<typename Source, typename Sink>
- std::streamsize
- copy( 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
|