TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/capy
9 : //
10 :
11 : #ifndef BOOST_CAPY_WRITE_HPP
12 : #define BOOST_CAPY_WRITE_HPP
13 :
14 : #include <boost/capy/detail/config.hpp>
15 : #include <boost/capy/results.hpp>
16 : #include <boost/capy/task.hpp>
17 : #include <boost/capy/buffers.hpp>
18 : #include <boost/capy/buffers/consuming_buffers.hpp>
19 : #include <boost/capy/concept/write_stream.hpp>
20 : #include <system_error>
21 :
22 : #include <cstddef>
23 :
24 : namespace boost {
25 : namespace capy {
26 :
27 : /** Write an entire buffer sequence to a stream.
28 :
29 : @par Await-effects
30 :
31 : Writes the contents of `buffers` to `stream` via awaiting
32 : `stream.write_some` with consecutive portions of data from `buffers`
33 : until:
34 :
35 : @li either the full content of @c buffers is processed,
36 : @li or a contingency in `stream.write_some` occurs.
37 :
38 : If `buffer_size(buffers) == 0` then no awaiting `stream.write_some`
39 : is performed. This is not a contingency.
40 :
41 :
42 : @par Await-returns
43 :
44 : An object of type `results<std::size_t>` destructuring as `[ec, n]`.
45 :
46 : Upon a contingency, `n` represents the number of bytes written
47 : so far.
48 :
49 : Otherwise `n` represents the number of bytes written.
50 :
51 : Contingencies:
52 :
53 : @li The first contingency reported from awaiting @c stream.write_some
54 : while not all bytes have been written. A contingency that accompanies
55 : the write which transfers the last bytes is not reported: a completed
56 : transfer is a success.
57 :
58 : Notable conditions:
59 :
60 : @li @c cond::canceled — Operation was cancelled,
61 : @li @c std::errc::broken_pipe — Peer closed connection.
62 :
63 :
64 : @par Await-postcondition
65 :
66 : If `n == buffer_size(buffers)` the transfer completed and `ec` is
67 : success; otherwise `ec` is set.
68 :
69 :
70 : @param stream The stream to write to. If the lifetime of `stream` ends
71 : before the coroutine finishes, the behavior is undefined.
72 :
73 : @param buffers The buffer sequence to write. If the lifetime of the buffer
74 : sequence represented by `buffers` ends
75 : before the coroutine finishes, the behavior is undefined.
76 :
77 : @return A task yielding `results<std::size_t>` whose second element
78 : is the number of bytes written.
79 :
80 : @par Remarks
81 :
82 : Supports _ContextAwaitable cancellation_.
83 :
84 : @par Example
85 :
86 : @par !example example
87 :
88 :
89 : @see WriteStream, ConstBufferSequence, ContextAwaitable, results, cond.
90 : */
91 : template <WriteStream S, ConstBufferSequence CB>
92 HIT 59 : auto write(S& stream, CB buffers) -> task<results<std::size_t>>
93 : {
94 : consuming_buffers consuming(buffers);
95 : std::size_t const total_size = buffer_size(buffers);
96 : std::size_t total_written = 0;
97 :
98 : while(total_written < total_size)
99 : {
100 : auto [ec, n] = co_await stream.write_some(consuming.data());
101 : consuming.consume(n);
102 : total_written += n;
103 : // A contingency that still completed the transfer is a success:
104 : // report it only when not all bytes were written.
105 : if(ec && total_written < total_size)
106 : co_return {ec, total_written};
107 : }
108 :
109 : co_return {std::error_code(), total_written};
110 118 : }
111 :
112 : } // namespace capy
113 : } // namespace boost
114 :
115 : #endif
|