source: NonGTP/Boost/boost/iostreams/copy.hpp @ 857

Revision 857, 7.7 KB checked in by igarcia, 18 years ago (diff)
Line 
1// (C) Copyright Jonathan Turkanis 2003.
2// Distributed under the Boost Software License, Version 1.0. (See accompanying
3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5// See http://www.boost.org/libs/iostreams for documentation.
6
7// Contains: The function template copy, which reads data from a Source
8// and writes it to a Sink until the end of the sequence is reached, returning
9// the number of characters transfered.
10
11// The implementation is complicated by the need to handle smart adapters
12// and direct devices.
13
14#ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED
15#define BOOST_IOSTREAMS_COPY_HPP_INCLUDED
16
17#if defined(_MSC_VER) && (_MSC_VER >= 1020)
18# pragma once
19#endif             
20
21#include <algorithm>                        // copy.
22#include <utility>                          // pair.
23#include <boost/detail/workaround.hpp>
24#include <boost/iostreams/chain.hpp>
25#include <boost/iostreams/constants.hpp>
26#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>       
27#include <boost/iostreams/detail/buffer.hpp>       
28#include <boost/iostreams/detail/closer.hpp>   
29#include <boost/iostreams/detail/enable_if_stream.hpp> 
30#include <boost/iostreams/detail/ios.hpp>   // failure, streamsize.                   
31#include <boost/iostreams/detail/resolve.hpp>                   
32#include <boost/iostreams/detail/wrap_unwrap.hpp>
33#include <boost/iostreams/operations.hpp>  // read, write, close.
34#include <boost/iostreams/pipeline.hpp>
35#include <boost/static_assert.hpp> 
36#include <boost/type_traits/is_same.hpp>
37
38namespace boost { namespace iostreams {
39
40namespace detail {
41
42template<typename Source, typename Sink>
43std::streamsize copy_impl( Source& src, Sink& snk,
44                           std::streamsize /* buffer_size */,
45                           mpl::true_, mpl::true_ )
46{   // Copy from a direct Source to a direct Sink.
47    using namespace std;
48    typedef typename char_type_of<Source>::type  char_type;
49    typedef pair<char_type*, char_type*>         pair_type;
50    pair_type p1 = iostreams::input_sequence(src);
51    pair_type p2 = iostreams::output_sequence(snk);
52    if (p1.second - p1.first < p2.second - p2.first) {
53        std::copy(p1.first, p1.second, p2.first);
54        return static_cast<streamsize>(p1.second - p1.first);
55    } else {
56        throw BOOST_IOSTREAMS_FAILURE("destination too small");
57    }
58}
59
60template<typename Source, typename Sink>
61std::streamsize copy_impl( Source& src, Sink& snk,
62                           std::streamsize /* buffer_size */,
63                           mpl::true_, mpl::false_ )
64{   // Copy from a direct Source to an indirect Sink.
65    using namespace std;
66    typedef typename char_type_of<Source>::type  char_type;
67    typedef pair<char_type*, char_type*>         pair_type;
68    pair_type p = iostreams::input_sequence(src);
69    std::streamsize size, total;
70    for ( total = 0, size = static_cast<streamsize>(p.second - p.first);
71          total < size; )
72    {
73        std::streamsize amt =
74            iostreams::write(snk, p.first + total, size - total);
75        total += amt;
76    }
77    return size;
78}
79
80template<typename Source, typename Sink>
81std::streamsize copy_impl( Source& src, Sink& snk,
82                           std::streamsize buffer_size,
83                           mpl::false_, mpl::true_ )
84{   // Copy from an indirect Source to a direct Sink.
85    using namespace std;
86    typedef typename char_type_of<Source>::type  char_type;
87    typedef pair<char_type*, char_type*>         pair_type;
88    detail::basic_buffer<char_type>  buf(buffer_size);
89    pair_type                        p = snk.output_sequence();
90    streamsize                       total = 0;
91    bool                             done  = false;
92    while (!done) {
93        streamsize amt;
94        done = (amt = iostreams::read(src, buf.data(), buffer_size)) == -1;
95        std::copy(buf.data(), buf.data() + amt, p.first + total);
96        if (amt != -1)
97            total += amt;
98    }
99    return total;
100}
101
102template<typename Source, typename Sink>
103std::streamsize copy_impl( Source& src, Sink& snk,
104                           std::streamsize buffer_size,
105                           mpl::false_, mpl::false_ )
106{   // Copy from an indirect Source to a indirect Sink. This algorithm
107    // can be improved by eliminating the non_blocking_adapter.
108    typedef typename char_type_of<Source>::type char_type;
109    detail::basic_buffer<char_type>  buf(buffer_size);
110    non_blocking_adapter<Sink>       nb(snk);
111    std::streamsize                  total = 0;
112    bool                             done = false;
113    while (!done) {
114        std::streamsize amt;
115        done = (amt = iostreams::read(src, buf.data(), buffer_size)) == -1;
116        if (amt != -1) {
117            iostreams::write(nb, buf.data(), amt);
118            total += amt;
119        }
120    }
121    return total;
122}
123
124template<typename Source, typename Sink>
125std::streamsize copy_impl(Source src, Sink snk, std::streamsize buffer_size)
126{
127    using namespace std;
128    typedef typename char_type_of<Source>::type  src_char;
129    typedef typename char_type_of<Sink>::type    snk_char;
130    BOOST_STATIC_ASSERT((is_same<src_char, snk_char>::value));
131    bool                     nothrow = false;
132    external_closer<Source>  close_source(src, BOOST_IOS::in, nothrow);
133    external_closer<Sink>    close_sink(snk, BOOST_IOS::out, nothrow);
134    streamsize result =
135        copy_impl( src, snk, buffer_size,
136                   is_direct<Source>(), is_direct<Sink>() );
137    return result;
138}
139
140} // End namespace detail.
141                   
142//------------------Definition of copy----------------------------------------//
143
144template<typename Source, typename Sink>
145std::streamsize
146copy( const Source& src, const Sink& snk,
147      std::streamsize buffer_size = default_device_buffer_size
148      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source)
149      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) )
150{
151    typedef typename char_type_of<Source>::type char_type;
152    return detail::copy_impl( detail::resolve<input, char_type>(src),
153                              detail::resolve<output, char_type>(snk),
154                              buffer_size );
155}
156
157#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------//
158
159template<typename Source, typename Sink>
160std::streamsize
161copy( Source& src, const Sink& snk,
162      std::streamsize buffer_size = default_device_buffer_size
163      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source)
164      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) )
165{
166    typedef typename char_type_of<Source>::type char_type;
167    return detail::copy_impl( detail::wrap(src),
168                              detail::resolve<output, char_type>(snk),
169                              buffer_size );
170}
171
172template<typename Source, typename Sink>
173std::streamsize
174copy( const Source& src, Sink& snk,
175      std::streamsize buffer_size = default_device_buffer_size
176      BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source)
177      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) )
178{
179    typedef typename char_type_of<Source>::type char_type;
180    return detail::copy_impl( detail::resolve<input, char_type>(src),
181                              detail::wrap(snk), buffer_size);
182}
183
184template<typename Source, typename Sink>
185std::streamsize
186copy( Source& src, Sink& snk,
187      std::streamsize buffer_size = default_device_buffer_size
188      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source)
189      BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) )
190{
191    return detail::copy_impl(detail::wrap(src), detail::wrap(snk), buffer_size);
192}
193
194#endif // #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //-----------------------//
195
196} } // End namespaces iostreams, boost.
197
198#endif // #ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.