File indexing completed on 2025-01-18 09:38:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED
0016 #define BOOST_IOSTREAMS_COPY_HPP_INCLUDED
0017
0018 #if defined(_MSC_VER)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/config.hpp> // Make sure ptrdiff_t is in std.
0023 #include <algorithm> // copy, min.
0024 #include <cstddef> // ptrdiff_t.
0025 #include <utility> // pair.
0026
0027 #include <boost/detail/workaround.hpp>
0028 #include <boost/iostreams/chain.hpp>
0029 #include <boost/iostreams/constants.hpp>
0030 #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
0031 #include <boost/iostreams/detail/buffer.hpp>
0032 #include <boost/iostreams/detail/enable_if_stream.hpp>
0033 #include <boost/iostreams/detail/execute.hpp>
0034 #include <boost/iostreams/detail/functional.hpp>
0035 #include <boost/iostreams/detail/ios.hpp> // failure, streamsize.
0036 #include <boost/iostreams/detail/resolve.hpp>
0037 #include <boost/iostreams/detail/wrap_unwrap.hpp>
0038 #include <boost/iostreams/operations.hpp> // read, write, close.
0039 #include <boost/iostreams/pipeline.hpp>
0040 #include <boost/static_assert.hpp>
0041 #include <boost/type_traits/is_same.hpp>
0042
0043 namespace boost { namespace iostreams {
0044
0045 namespace detail {
0046
0047
0048
0049
0050
0051
0052
0053 template<typename Source, typename Sink>
0054 std::streamsize copy_impl( Source& src, Sink& snk,
0055 std::streamsize ,
0056 mpl::true_, mpl::true_ )
0057 {
0058 using namespace std;
0059 typedef typename char_type_of<Source>::type char_type;
0060 typedef std::pair<char_type*, char_type*> pair_type;
0061 pair_type p1 = iostreams::input_sequence(src);
0062 pair_type p2 = iostreams::output_sequence(snk);
0063 std::streamsize total =
0064 static_cast<std::streamsize>(
0065 (std::min)(p1.second - p1.first, p2.second - p2.first)
0066 );
0067 std::copy(p1.first, p1.first + total, p2.first);
0068 return total;
0069 }
0070
0071
0072 template<typename Source, typename Sink>
0073 std::streamsize copy_impl( Source& src, Sink& snk,
0074 std::streamsize ,
0075 mpl::true_, mpl::false_ )
0076 {
0077 using namespace std;
0078 typedef typename char_type_of<Source>::type char_type;
0079 typedef std::pair<char_type*, char_type*> pair_type;
0080 pair_type p = iostreams::input_sequence(src);
0081 std::streamsize size, total;
0082 for ( total = 0, size = static_cast<std::streamsize>(p.second - p.first);
0083 total < size; )
0084 {
0085 std::streamsize amt =
0086 iostreams::write(snk, p.first + total, size - total);
0087 total += amt;
0088 }
0089 return total;
0090 }
0091
0092
0093 template<typename Source, typename Sink>
0094 std::streamsize copy_impl( Source& src, Sink& snk,
0095 std::streamsize buffer_size,
0096 mpl::false_, mpl::true_ )
0097 {
0098 typedef typename char_type_of<Source>::type char_type;
0099 typedef std::pair<char_type*, char_type*> pair_type;
0100 detail::basic_buffer<char_type> buf(buffer_size);
0101 pair_type p = snk.output_sequence();
0102 std::streamsize total = 0;
0103 std::ptrdiff_t capacity = p.second - p.first;
0104 while (true) {
0105 std::streamsize amt =
0106 iostreams::read(
0107 src,
0108 buf.data(),
0109 buffer_size < capacity - total ?
0110 buffer_size :
0111 static_cast<std::streamsize>(capacity - total)
0112 );
0113 if (amt == -1)
0114 break;
0115 std::copy(buf.data(), buf.data() + amt, p.first + total);
0116 total += amt;
0117 }
0118 return total;
0119 }
0120
0121
0122 template<typename Source, typename Sink>
0123 std::streamsize copy_impl( Source& src, Sink& snk,
0124 std::streamsize buffer_size,
0125 mpl::false_, mpl::false_ )
0126 {
0127 typedef typename char_type_of<Source>::type char_type;
0128 detail::basic_buffer<char_type> buf(buffer_size);
0129 non_blocking_adapter<Sink> nb(snk);
0130 std::streamsize total = 0;
0131 bool done = false;
0132 while (!done) {
0133 std::streamsize amt;
0134 done = (amt = iostreams::read(src, buf.data(), buffer_size)) == -1;
0135 if (amt != -1) {
0136 iostreams::write(nb, buf.data(), amt);
0137 total += amt;
0138 }
0139 }
0140 return total;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149 template<typename Source, typename Sink>
0150 class copy_operation {
0151 public:
0152 typedef std::streamsize result_type;
0153 copy_operation(Source& src, Sink& snk, std::streamsize buffer_size)
0154 : src_(src), snk_(snk), buffer_size_(buffer_size)
0155 { }
0156 std::streamsize operator()()
0157 {
0158 return copy_impl( src_, snk_, buffer_size_,
0159 is_direct<Source>(), is_direct<Sink>() );
0160 }
0161 private:
0162 copy_operation& operator=(const copy_operation&);
0163 Source& src_;
0164 Sink& snk_;
0165 std::streamsize buffer_size_;
0166 };
0167
0168
0169
0170
0171
0172 template<typename Source, typename Sink>
0173 std::streamsize copy_impl(Source src, Sink snk, std::streamsize buffer_size)
0174 {
0175 using namespace std;
0176 typedef typename char_type_of<Source>::type src_char;
0177 typedef typename char_type_of<Sink>::type snk_char;
0178 BOOST_STATIC_ASSERT((is_same<src_char, snk_char>::value));
0179 return detail::execute_all(
0180 copy_operation<Source, Sink>(src, snk, buffer_size),
0181 detail::call_close_all(src),
0182 detail::call_close_all(snk)
0183 );
0184 }
0185
0186 }
0187
0188
0189
0190
0191
0192 template<typename Source, typename Sink>
0193 std::streamsize
0194 copy( const Source& src, const Sink& snk,
0195 std::streamsize buffer_size = default_device_buffer_size
0196 BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source)
0197 BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) )
0198 {
0199 typedef typename char_type_of<Source>::type char_type;
0200 return detail::copy_impl( detail::resolve<input, char_type>(src),
0201 detail::resolve<output, char_type>(snk),
0202 buffer_size );
0203 }
0204
0205
0206
0207 template<typename Source, typename Sink>
0208 std::streamsize
0209 copy( Source& src, const Sink& snk,
0210 std::streamsize buffer_size = default_device_buffer_size
0211 BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source)
0212 BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) )
0213 {
0214 typedef typename char_type_of<Source>::type char_type;
0215 return detail::copy_impl( detail::wrap(src),
0216 detail::resolve<output, char_type>(snk),
0217 buffer_size );
0218 }
0219
0220
0221
0222 template<typename Source, typename Sink>
0223 std::streamsize
0224 copy( const Source& src, Sink& snk,
0225 std::streamsize buffer_size = default_device_buffer_size
0226 BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source)
0227 BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) )
0228 {
0229 typedef typename char_type_of<Source>::type char_type;
0230 return detail::copy_impl( detail::resolve<input, char_type>(src),
0231 detail::wrap(snk), buffer_size );
0232 }
0233
0234
0235
0236 template<typename Source, typename Sink>
0237 std::streamsize
0238 copy( Source& src, Sink& snk,
0239 std::streamsize buffer_size = default_device_buffer_size
0240 BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source)
0241 BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) )
0242 {
0243 return detail::copy_impl(detail::wrap(src), detail::wrap(snk), buffer_size);
0244 }
0245
0246 } }
0247
0248 #endif