100.00% Lines (4/4) 100.00% Functions (2/2)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/capy 7   // Official repository: https://github.com/cppalliance/capy
8   // 8   //
9   9  
10   #ifndef BOOST_CAPY_IO_PUSH_TO_HPP 10   #ifndef BOOST_CAPY_IO_PUSH_TO_HPP
11   #define BOOST_CAPY_IO_PUSH_TO_HPP 11   #define BOOST_CAPY_IO_PUSH_TO_HPP
12   12  
13   #include <boost/capy/detail/config.hpp> 13   #include <boost/capy/detail/config.hpp>
14   #include <boost/capy/buffers.hpp> 14   #include <boost/capy/buffers.hpp>
15   #include <boost/capy/cond.hpp> 15   #include <boost/capy/cond.hpp>
16   #include <boost/capy/concept/buffer_source.hpp> 16   #include <boost/capy/concept/buffer_source.hpp>
17   #include <boost/capy/concept/write_sink.hpp> 17   #include <boost/capy/concept/write_sink.hpp>
18   #include <boost/capy/concept/write_stream.hpp> 18   #include <boost/capy/concept/write_stream.hpp>
19   #include <boost/capy/io_task.hpp> 19   #include <boost/capy/io_task.hpp>
20   20  
21   #include <cstddef> 21   #include <cstddef>
22   #include <span> 22   #include <span>
23   23  
24   namespace boost { 24   namespace boost {
25   namespace capy { 25   namespace capy {
26   26  
27   /** Transfer data from a BufferSource to a WriteSink. 27   /** Transfer data from a BufferSource to a WriteSink.
28   28  
29   This function pulls data from the source and writes it to the 29   This function pulls data from the source and writes it to the
30   sink until the source is exhausted or an error occurs. When 30   sink until the source is exhausted or an error occurs. When
31   the source signals completion, `write_eof()` is called on the 31   the source signals completion, `write_eof()` is called on the
32   sink to finalize the transfer. 32   sink to finalize the transfer.
33   33  
34   @tparam Src The source type, must satisfy @ref BufferSource. 34   @tparam Src The source type, must satisfy @ref BufferSource.
35   @tparam Sink The sink type, must satisfy @ref WriteSink. 35   @tparam Sink The sink type, must satisfy @ref WriteSink.
36   36  
37   @param source The source to pull data from. 37   @param source The source to pull data from.
38   @param sink The sink to write data to. 38   @param sink The sink to write data to.
39   39  
40   @return A task that yields `(std::error_code, std::size_t)`. 40   @return A task that yields `(std::error_code, std::size_t)`.
41   On success, `ec` is default-constructed (no error) and `n` is 41   On success, `ec` is default-constructed (no error) and `n` is
42   the total number of bytes transferred. On error, `ec` contains 42   the total number of bytes transferred. On error, `ec` contains
43   the error code and `n` is the total number of bytes transferred 43   the error code and `n` is the total number of bytes transferred
44   before the error. 44   before the error.
45   45  
46   @par Example 46   @par Example
47   @code 47   @code
48   task<void> transfer_body(BufferSource auto& source, WriteSink auto& sink) 48   task<void> transfer_body(BufferSource auto& source, WriteSink auto& sink)
49   { 49   {
50   auto [ec, n] = co_await push_to(source, sink); 50   auto [ec, n] = co_await push_to(source, sink);
51   if (ec) 51   if (ec)
52   { 52   {
53   // Handle error 53   // Handle error
54   } 54   }
55   // n bytes were transferred 55   // n bytes were transferred
56   } 56   }
57   @endcode 57   @endcode
58   58  
59   @see BufferSource, WriteSink 59   @see BufferSource, WriteSink
60   */ 60   */
61   template<BufferSource Src, WriteSink Sink> 61   template<BufferSource Src, WriteSink Sink>
62   io_task<std::size_t> 62   io_task<std::size_t>
HITCBC 63   140 push_to(Src& source, Sink& sink) 63   140 push_to(Src& source, Sink& sink)
64   { 64   {
65   const_buffer arr[detail::max_iovec_]; 65   const_buffer arr[detail::max_iovec_];
66   std::size_t total = 0; 66   std::size_t total = 0;
67   67  
68   for(;;) 68   for(;;)
69   { 69   {
70   auto [ec, bufs] = co_await source.pull(arr); 70   auto [ec, bufs] = co_await source.pull(arr);
71   if(ec == cond::eof) 71   if(ec == cond::eof)
72   { 72   {
73   auto [eof_ec] = co_await sink.write_eof(); 73   auto [eof_ec] = co_await sink.write_eof();
74   co_return {eof_ec, total}; 74   co_return {eof_ec, total};
75   } 75   }
76   if(ec) 76   if(ec)
77   co_return {ec, total}; 77   co_return {ec, total};
78   78  
79   auto [write_ec, n] = co_await sink.write(bufs); 79   auto [write_ec, n] = co_await sink.write(bufs);
80   total += n; 80   total += n;
81   source.consume(n); 81   source.consume(n);
82   if(write_ec) 82   if(write_ec)
83   co_return {write_ec, total}; 83   co_return {write_ec, total};
84   } 84   }
HITCBC 85   280 } 85   280 }
86   86  
87   /** Transfer data from a BufferSource to a WriteStream. 87   /** Transfer data from a BufferSource to a WriteStream.
88   88  
89   This function pulls data from the source and writes it to the 89   This function pulls data from the source and writes it to the
90   stream until the source is exhausted or an error occurs. The 90   stream until the source is exhausted or an error occurs. The
91   stream uses `write_some()` which may perform partial writes, 91   stream uses `write_some()` which may perform partial writes,
92   so this function loops until all pulled data is consumed. 92   so this function loops until all pulled data is consumed.
93   93  
94   Unlike the WriteSink overload, this function does not signal 94   Unlike the WriteSink overload, this function does not signal
95   EOF explicitly since WriteStream does not provide a write_eof 95   EOF explicitly since WriteStream does not provide a write_eof
96   method. The transfer completes when the source is exhausted. 96   method. The transfer completes when the source is exhausted.
97   97  
98   @tparam Src The source type, must satisfy @ref BufferSource. 98   @tparam Src The source type, must satisfy @ref BufferSource.
99   @tparam Stream The stream type, must satisfy @ref WriteStream. 99   @tparam Stream The stream type, must satisfy @ref WriteStream.
100   100  
101   @param source The source to pull data from. 101   @param source The source to pull data from.
102   @param stream The stream to write data to. 102   @param stream The stream to write data to.
103   103  
104   @return A task that yields `(std::error_code, std::size_t)`. 104   @return A task that yields `(std::error_code, std::size_t)`.
105   On success, `ec` is default-constructed (no error) and `n` is 105   On success, `ec` is default-constructed (no error) and `n` is
106   the total number of bytes transferred. On error, `ec` contains 106   the total number of bytes transferred. On error, `ec` contains
107   the error code and `n` is the total number of bytes transferred 107   the error code and `n` is the total number of bytes transferred
108   before the error. 108   before the error.
109   109  
110   @par Example 110   @par Example
111   @code 111   @code
112   task<void> transfer_body(BufferSource auto& source, WriteStream auto& stream) 112   task<void> transfer_body(BufferSource auto& source, WriteStream auto& stream)
113   { 113   {
114   auto [ec, n] = co_await push_to(source, stream); 114   auto [ec, n] = co_await push_to(source, stream);
115   if (ec) 115   if (ec)
116   { 116   {
117   // Handle error 117   // Handle error
118   } 118   }
119   // n bytes were transferred 119   // n bytes were transferred
120   } 120   }
121   @endcode 121   @endcode
122   122  
123   @see BufferSource, WriteStream, pull_from 123   @see BufferSource, WriteStream, pull_from
124   */ 124   */
125   template<BufferSource Src, WriteStream Stream> 125   template<BufferSource Src, WriteStream Stream>
126   requires (!WriteSink<Stream>) 126   requires (!WriteSink<Stream>)
127   io_task<std::size_t> 127   io_task<std::size_t>
HITCBC 128   104 push_to(Src& source, Stream& stream) 128   104 push_to(Src& source, Stream& stream)
129   { 129   {
130   const_buffer arr[detail::max_iovec_]; 130   const_buffer arr[detail::max_iovec_];
131   std::size_t total = 0; 131   std::size_t total = 0;
132   132  
133   for(;;) 133   for(;;)
134   { 134   {
135   auto [ec, bufs] = co_await source.pull(arr); 135   auto [ec, bufs] = co_await source.pull(arr);
136   if(ec == cond::eof) 136   if(ec == cond::eof)
137   co_return {{}, total}; 137   co_return {{}, total};
138   if(ec) 138   if(ec)
139   co_return {ec, total}; 139   co_return {ec, total};
140   140  
141   auto [write_ec, n] = co_await stream.write_some(bufs); 141   auto [write_ec, n] = co_await stream.write_some(bufs);
142   total += n; 142   total += n;
143   source.consume(n); 143   source.consume(n);
144   if(write_ec) 144   if(write_ec)
145   co_return {write_ec, total}; 145   co_return {write_ec, total};
146   } 146   }
HITCBC 147   208 } 147   208 }
148   148  
149   } // namespace capy 149   } // namespace capy
150   } // namespace boost 150   } // namespace boost
151   151  
152   #endif 152   #endif