0.00% Lines (0/0) 0.00% Functions (0/0)
TLA Baseline Branch
Line Hits Code Line Hits Code
1 - //  
2 - // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)  
3 - //  
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)  
6 - //  
7 - // Official repository: https://github.com/cppalliance/capy  
8 - //  
9 -  
10 - #ifndef BOOST_CAPY_IO_PULL_FROM_HPP  
11 - #define BOOST_CAPY_IO_PULL_FROM_HPP  
12 -  
13 - #include <boost/capy/detail/config.hpp>  
14 - #include <boost/capy/buffers.hpp>  
15 - #include <boost/capy/cond.hpp>  
16 - #include <boost/capy/concept/buffer_sink.hpp>  
17 - #include <boost/capy/concept/read_source.hpp>  
18 - #include <boost/capy/concept/read_stream.hpp>  
19 - #include <boost/capy/io_task.hpp>  
20 -  
21 - #include <cstddef>  
22 - #include <span>  
23 -  
24 - namespace boost {  
25 - namespace capy {  
26 -  
27 - /** Transfer data from a ReadSource to a BufferSink.  
28 -  
29 - This function reads data from the source directly into the sink's  
30 - internal buffers using the callee-owns-buffers model. The sink  
31 - provides writable buffers via `prepare()`, the source reads into  
32 - them, and the sink commits the data. When the source signals EOF,  
33 - `commit_eof()` is called on the sink to finalize the transfer.  
34 -  
35 - @tparam Src The source type, must satisfy @ref ReadSource.  
36 - @tparam Sink The sink type, must satisfy @ref BufferSink.  
37 -  
38 - @param source The source to read data from.  
39 - @param sink The sink to write data to.  
40 -  
41 - @return A task that yields `(std::error_code, std::size_t)`.  
42 - On success, `ec` is default-constructed (no error) and `n` is  
43 - the total number of bytes transferred. On error, `ec` contains  
44 - the error code and `n` is the total number of bytes transferred  
45 - before the error.  
46 -  
47 - @par Example  
48 - @code  
49 - task<void> transfer_body(ReadSource auto& source, BufferSink auto& sink)  
50 - {  
51 - auto [ec, n] = co_await pull_from(source, sink);  
52 - if (ec)  
53 - {  
54 - // Handle error  
55 - }  
56 - // n bytes were transferred  
57 - }  
58 - @endcode  
59 -  
60 - @see ReadSource, BufferSink, push_to  
61 - */  
62 - template<ReadSource Src, BufferSink Sink>  
63 - io_task<std::size_t>  
DCB 64 - 136 pull_from(Src& source, Sink& sink)  
65 - {  
66 - mutable_buffer dst_arr[detail::max_iovec_];  
67 - std::size_t total = 0;  
68 -  
69 - for(;;)  
70 - {  
71 - auto dst_bufs = sink.prepare(dst_arr);  
72 - if(dst_bufs.empty())  
73 - {  
74 - // No buffer space available; commit nothing to flush  
75 - auto [flush_ec] = co_await sink.commit(0);  
76 - if(flush_ec)  
77 - co_return {flush_ec, total};  
78 - continue;  
79 - }  
80 -  
81 - auto [ec, n] = co_await source.read(  
82 - std::span<mutable_buffer const>(dst_bufs));  
83 -  
84 - auto [commit_ec] = co_await sink.commit(n);  
85 - total += n;  
86 -  
87 - if(commit_ec)  
88 - co_return {commit_ec, total};  
89 -  
90 - if(ec == cond::eof)  
91 - {  
92 - auto [eof_ec] = co_await sink.commit_eof(0);  
93 - co_return {eof_ec, total};  
94 - }  
95 -  
96 - if(ec)  
97 - co_return {ec, total};  
98 - }  
DCB 99 - 272 }  
100 -  
101 - /** Transfer data from a ReadStream to a BufferSink.  
102 -  
103 - This function reads data from the stream directly into the sink's  
104 - internal buffers using the callee-owns-buffers model. The sink  
105 - provides writable buffers via `prepare()`, the stream reads into  
106 - them using `read_some()`, and the sink commits the data. When the  
107 - stream signals EOF, `commit_eof()` is called on the sink to  
108 - finalize the transfer.  
109 -  
110 - This overload handles partial reads from the stream, committing  
111 - data incrementally as it arrives. It loops until EOF is encountered  
112 - or an error occurs.  
113 -  
114 - @tparam Src The stream type, must satisfy @ref ReadStream.  
115 - @tparam Sink The sink type, must satisfy @ref BufferSink.  
116 -  
117 - @param source The stream to read data from.  
118 - @param sink The sink to write data to.  
119 -  
120 - @return A task that yields `(std::error_code, std::size_t)`.  
121 - On success, `ec` is default-constructed (no error) and `n` is  
122 - the total number of bytes transferred. On error, `ec` contains  
123 - the error code and `n` is the total number of bytes transferred  
124 - before the error.  
125 -  
126 - @par Example  
127 - @code  
128 - task<void> transfer_body(ReadStream auto& stream, BufferSink auto& sink)  
129 - {  
130 - auto [ec, n] = co_await pull_from(stream, sink);  
131 - if (ec)  
132 - {  
133 - // Handle error  
134 - }  
135 - // n bytes were transferred  
136 - }  
137 - @endcode  
138 -  
139 - @see ReadStream, BufferSink, push_to  
140 - */  
141 - template<ReadStream Src, BufferSink Sink>  
142 - requires (!ReadSource<Src>)  
143 - io_task<std::size_t>  
DCB 144 - 226 pull_from(Src& source, Sink& sink)  
145 - {  
146 - mutable_buffer dst_arr[detail::max_iovec_];  
147 - std::size_t total = 0;  
148 -  
149 - for(;;)  
150 - {  
151 - // Prepare destination buffers from the sink  
152 - auto dst_bufs = sink.prepare(dst_arr);  
153 - if(dst_bufs.empty())  
154 - {  
155 - // No buffer space available; commit nothing to flush  
156 - auto [flush_ec] = co_await sink.commit(0);  
157 - if(flush_ec)  
158 - co_return {flush_ec, total};  
159 - continue;  
160 - }  
161 -  
162 - // Read data from the stream into the sink's buffers  
163 - auto [ec, n] = co_await source.read_some(  
164 - std::span<mutable_buffer const>(dst_bufs));  
165 -  
166 - auto [commit_ec] = co_await sink.commit(n);  
167 - total += n;  
168 -  
169 - if(commit_ec)  
170 - co_return {commit_ec, total};  
171 -  
172 - if(ec == cond::eof)  
173 - {  
174 - auto [eof_ec] = co_await sink.commit_eof(0);  
175 - co_return {eof_ec, total};  
176 - }  
177 -  
178 - // Check for other errors  
179 - if(ec)  
180 - co_return {ec, total};  
181 - }  
DCB 182 - 452 }  
183 -  
184 - } // namespace capy  
185 - } // namespace boost  
186 -  
187 - #endif