libs/capy/include/boost/capy/read.hpp

100.0% Lines (6/6) 100.0% Functions (6/6) 100.0% Branches (3/3)
libs/capy/include/boost/capy/read.hpp
Line Branch Hits 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_READ_HPP
11 #define BOOST_CAPY_READ_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/cond.hpp>
15 #include <boost/capy/io_result.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/dynamic_buffer.hpp>
20 #include <boost/capy/concept/read_source.hpp>
21 #include <boost/capy/concept/read_stream.hpp>
22 #include <system_error>
23
24 #include <cstddef>
25
26 namespace boost {
27 namespace capy {
28
29 /** Read data until the buffer sequence is full or an error occurs.
30
31 This function reads data from the stream into the buffer sequence
32 until either the entire buffer sequence is filled or an error
33 occurs (including end-of-file).
34
35 @tparam Stream The stream type, must satisfy @ref ReadStream.
36 @tparam MB The buffer sequence type, must satisfy
37 @ref MutableBufferSequence.
38
39 @param stream The stream to read from.
40 @param buffers The buffer sequence to read into.
41
42 @return A task that yields `(std::error_code, std::size_t)`.
43 On success, `ec` is default-constructed (no error) and `n` is
44 `buffer_size(buffers)`. On error or EOF, `ec` contains the
45 error code and `n` is the total number of bytes written before
46 the error.
47
48 @par Example
49 @code
50 task<void> example(ReadStream auto& stream)
51 {
52 char buf[1024];
53 auto [ec, n] = co_await read(stream, mutable_buffer(buf, sizeof(buf)));
54 if (ec == cond::eof)
55 {
56 // Handle end-of-file
57 }
58 else if (ec)
59 {
60 // Handle other error
61 }
62 // n bytes were read into buf
63 }
64 @endcode
65
66 @see ReadStream, MutableBufferSequence
67 */
68 auto
69
1/1
✓ Branch 1 taken 50 times.
50 read(
70 ReadStream auto& stream,
71 MutableBufferSequence auto const& buffers) ->
72 task<io_result<std::size_t>>
73 {
74 consuming_buffers consuming(buffers);
75 std::size_t const total_size = buffer_size(buffers);
76 std::size_t total_read = 0;
77
78 while(total_read < total_size)
79 {
80 auto [ec, n] = co_await stream.read_some(consuming);
81 if(ec)
82 co_return {ec, total_read};
83 consuming.consume(n);
84 total_read += n;
85 }
86
87 co_return {{}, total_read};
88 100 }
89
90 /** Read data from a stream into a dynamic buffer.
91
92 This function reads data from the stream into the dynamic buffer
93 until end-of-file is reached or an error occurs. Data is appended
94 to the buffer using prepare/commit semantics.
95
96 The buffer grows using a strategy that starts with `initial_amount`
97 bytes and grows by a factor of 1.5 when filled.
98
99 @param stream The stream to read from, must satisfy @ref ReadStream.
100 @param buffers The dynamic buffer to read into.
101 @param initial_amount The initial number of bytes to prepare.
102
103 @return A task that yields `(std::error_code, std::size_t)`.
104 On success (EOF reached), `ec` is default-constructed and `n`
105 is the total number of bytes read. On error, `ec` contains the
106 error code and `n` is the total number of bytes read before
107 the error.
108
109 @par Example
110 @code
111 task<void> example(ReadStream auto& stream)
112 {
113 std::string body;
114 auto [ec, n] = co_await read(stream, string_dynamic_buffer(&body));
115 // body contains n bytes of data
116 }
117 @endcode
118
119 @see ReadStream, DynamicBufferParam
120 */
121 auto
122
1/1
✓ Branch 1 taken 80 times.
80 read(
123 ReadStream auto& stream,
124 DynamicBufferParam auto&& buffers,
125 std::size_t initial_amount = 2048) ->
126 task<io_result<std::size_t>>
127 {
128 std::size_t amount = initial_amount;
129 std::size_t total_read = 0;
130 for(;;)
131 {
132 auto mb = buffers.prepare(amount);
133 auto const mb_size = buffer_size(mb);
134 auto [ec, n] = co_await stream.read_some(mb);
135 buffers.commit(n);
136 total_read += n;
137 if(ec == cond::eof)
138 co_return {{}, total_read};
139 if(ec)
140 co_return {ec, total_read};
141 if(n == mb_size)
142 amount = amount / 2 + amount;
143 }
144 160 }
145
146 /** Read data from a source into a dynamic buffer.
147
148 This function reads data from the source into the dynamic buffer
149 until end-of-file is reached or an error occurs. Data is appended
150 to the buffer using prepare/commit semantics.
151
152 The buffer grows using a strategy that starts with `initial_amount`
153 bytes and grows by a factor of 1.5 when filled.
154
155 @tparam Source The source type, must satisfy @ref ReadSource.
156
157 @param source The source to read from.
158 @param buffers The dynamic buffer to read into.
159 @param initial_amount The initial number of bytes to prepare.
160
161 @return A task that yields `(std::error_code, std::size_t)`.
162 On success (EOF reached), `ec` is default-constructed and `n`
163 is the total number of bytes read. On error, `ec` contains the
164 error code and `n` is the total number of bytes read before
165 the error.
166
167 @par Example
168 @code
169 task<void> example(ReadSource auto& source)
170 {
171 std::string body;
172 auto [ec, n] = co_await read(source, string_buffers(body));
173 if (ec)
174 {
175 // Handle error
176 }
177 // body contains n bytes of data
178 }
179 @endcode
180
181 @see ReadSource, DynamicBufferParam
182 */
183 auto
184
1/1
✓ Branch 1 taken 66 times.
66 read(
185 ReadSource auto& source,
186 DynamicBufferParam auto&& buffers,
187 std::size_t initial_amount = 2048) ->
188 task<io_result<std::size_t>>
189 {
190 std::size_t amount = initial_amount;
191 std::size_t total_read = 0;
192 for(;;)
193 {
194 auto mb = buffers.prepare(amount);
195 auto const mb_size = buffer_size(mb);
196 auto [ec, n] = co_await source.read(mb);
197 buffers.commit(n);
198 total_read += n;
199 if(ec == cond::eof)
200 co_return {{}, total_read};
201 if(ec)
202 co_return {ec, total_read};
203 if(n == mb_size)
204 amount = amount / 2 + amount; // 1.5x growth
205 }
206 132 }
207
208 } // namespace capy
209 } // namespace boost
210
211 #endif
212