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