Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot 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_WRITE_HPP
11 : #define BOOST_CAPY_WRITE_HPP
12 :
13 : #include <boost/capy/detail/config.hpp>
14 : #include <boost/capy/io_result.hpp>
15 : #include <boost/capy/task.hpp>
16 : #include <boost/capy/buffers.hpp>
17 : #include <boost/capy/buffers/consuming_buffers.hpp>
18 : #include <boost/capy/concept/write_stream.hpp>
19 : #include <system_error>
20 :
21 : #include <cstddef>
22 :
23 : namespace boost {
24 : namespace capy {
25 :
26 : /** Asynchronously write the entire buffer sequence.
27 :
28 : Writes data to the stream by calling `write_some` repeatedly
29 : until the entire buffer sequence is written or an error occurs.
30 :
31 : @li The operation completes when:
32 : @li The entire buffer sequence has been written
33 : @li An error occurs
34 : @li The operation is cancelled
35 :
36 : @par Cancellation
37 : Supports cancellation via `stop_token` propagated through the
38 : IoAwaitable protocol. When cancelled, returns with `cond::canceled`.
39 :
40 : @param stream The stream to write to. The caller retains ownership.
41 : @param buffers The buffer sequence to write. The caller retains
42 : ownership and must ensure validity until the operation completes.
43 :
44 : @return An awaitable yielding `(error_code, std::size_t)`.
45 : On success, `n` equals `buffer_size(buffers)`. On error,
46 : `n` is the number of bytes written before the error. Compare
47 : error codes to conditions:
48 : @li `cond::canceled` - Operation was cancelled
49 : @li `std::errc::broken_pipe` - Peer closed connection
50 :
51 : @par Example
52 :
53 : @code
54 : task<> send_response( WriteStream auto& stream, std::string_view body )
55 : {
56 : auto [ec, n] = co_await write( stream, make_buffer( body ) );
57 : if( ec.failed() )
58 : detail::throw_system_error( ec );
59 : // All bytes written successfully
60 : }
61 : @endcode
62 :
63 : @see write_some, WriteStream, ConstBufferSequence
64 : */
65 : auto
66 44 : write(
67 : WriteStream auto& stream,
68 : ConstBufferSequence auto const& buffers) ->
69 : task<io_result<std::size_t>>
70 : {
71 : consuming_buffers consuming(buffers);
72 : std::size_t const total_size = buffer_size(buffers);
73 : std::size_t total_written = 0;
74 :
75 : while(total_written < total_size)
76 : {
77 : auto [ec, n] = co_await stream.write_some(consuming);
78 : if(ec)
79 : co_return {ec, total_written};
80 : consuming.consume(n);
81 : total_written += n;
82 : }
83 :
84 : co_return {{}, total_written};
85 88 : }
86 :
87 : } // namespace capy
88 : } // namespace boost
89 :
90 : #endif
|