@@ -17,8 +17,9 @@ and `write_some()` functions to provide higher-level guarantees.
1717Code snippets assume:
1818[source,cpp]
1919----
20- #include <boost/corosio/read.hpp>
21- #include <boost/corosio/write.hpp>
20+ #include <boost/capy/read.hpp>
21+ #include <boost/capy/write.hpp>
22+ #include <boost/capy/buffers/string_dynamic_buffer.hpp>
2223#include <boost/capy/buffers.hpp>
2324
2425namespace corosio = boost::corosio;
@@ -42,88 +43,82 @@ auto [ec, n] = co_await s.read_some(
4243For many use cases, you need to transfer a specific amount of data. Composed
4344operations provide these guarantees.
4445
45- == corosio ::read()
46+ == capy ::read()
4647
4748The `read()` function reads until the buffer is full or an error occurs:
4849
4950[source,cpp]
5051----
5152char buf[1024];
52- auto [ec, n] = co_await corosio ::read(
53+ auto [ec, n] = co_await capy ::read(
5354 stream, capy::mutable_buffer(buf, sizeof(buf)));
5455
5556// Either:
5657// - n == 1024 and ec is default (success)
57- // - ec is error ::eof and n < 1024 (reached end of stream)
58+ // - ec == capy::cond ::eof and n < 1024 (reached end of stream)
5859// - ec is some other error
5960----
6061
6162=== Signature
6263
6364[source,cpp]
6465----
65- template<capy::mutable_buffer_sequence MutableBufferSequence>
66- capy::task<io_result<std::size_t>>
67- read(io_stream& ios, MutableBufferSequence const& buffers);
66+ auto
67+ read(
68+ ReadStream auto& stream,
69+ MutableBufferSequence auto const& buffers) ->
70+ capy::io_task<std::size_t>;
6871----
6972
7073=== Behavior
7174
72751. Calls `read_some()` repeatedly until all buffers are filled
73- 2. If `read_some()` returns 0 bytes, returns `capy::error:: eof`
74- 3. If an error occurs, returns immediately with bytes read so far
75- 4 . On success, returns total bytes (equals `buffer_size(buffers)`)
76+ 2. If `read_some()` returns an error (including `cond:: eof`), returns
77+ immediately with bytes read so far
78+ 3 . On success, returns total bytes (equals `buffer_size(buffers)`)
7679
77- == corosio ::read() into std::string
80+ == capy ::read() into a dynamic buffer
7881
79- A special overload reads until EOF, growing the string as needed:
82+ A second overload reads until EOF, growing the buffer as needed. Use
83+ `capy::string_dynamic_buffer` to wrap a `std::string`:
8084
8185[source,cpp]
8286----
8387std::string content;
84- auto [ec, n] = co_await corosio::read(stream, content);
88+ auto [ec, n] = co_await capy::read(
89+ stream, capy::string_dynamic_buffer(&content));
8590
86- // Either:
87- // - ec == capy::error::eof (normal termination)
88- // - ec is some error
89- // content contains all data read
91+ // On success (EOF reached): ec is default, n is total bytes read
92+ // On error: ec is the error, n is bytes read before the error
9093----
9194
9295=== Signature
9396
9497[source,cpp]
9598----
96- capy::task<io_result<std::size_t>>
97- read(io_stream& ios, std::string& s);
99+ auto
100+ read(
101+ ReadStream auto& stream,
102+ DynamicBufferParam auto&& buffers,
103+ std::size_t initial_amount = 2048) ->
104+ capy::io_task<std::size_t>;
98105----
99106
100107=== Behavior
101108
102- 1. Preserves existing string content
103- 2. Grows string as needed (starts with 2048 bytes, grows 1.5x)
104- 3. Reads until EOF or error
105- 4. Resizes string to actual data size before returning
106- 5. Returns `n` = new bytes read (not including original content)
107-
108- === Growth Strategy
109-
110- The function uses an efficient growth strategy:
111-
112- * Initial capacity: existing size + 2048
113- * Growth factor: 1.5x when buffer fills
114- * Maximum: `string::max_size()`
115-
116- If the string reaches `max_size()` with more data available, returns
117- `errc::value_too_large`.
109+ 1. Prepares `initial_amount` bytes via `buffers.prepare()`, then reads
110+ 2. Grows 1.5x when the prepared buffer fills completely
111+ 3. On `cond::eof`: returns success with total bytes read
112+ 4. On any other error: returns immediately with bytes read so far
118113
119- == corosio ::write()
114+ == capy ::write()
120115
121116The `write()` function writes all data or fails:
122117
123118[source,cpp]
124119----
125120std::string msg = "Hello, World!";
126- auto [ec, n] = co_await corosio ::write(
121+ auto [ec, n] = co_await capy ::write(
127122 stream, capy::const_buffer(msg.data(), msg.size()));
128123
129124// Either:
@@ -135,17 +130,18 @@ auto [ec, n] = co_await corosio::write(
135130
136131[source,cpp]
137132----
138- template<capy::const_buffer_sequence ConstBufferSequence>
139- capy::task<io_result<std::size_t>>
140- write(io_stream& ios, ConstBufferSequence const& buffers);
133+ auto
134+ write(
135+ WriteStream auto& stream,
136+ ConstBufferSequence auto const& buffers) ->
137+ capy::io_task<std::size_t>;
141138----
142139
143140=== Behavior
144141
1451421. Calls `write_some()` repeatedly until all buffers are written
146- 2. If `write_some()` returns 0 bytes, returns `errc::broken_pipe`
147- 3. If an error occurs, returns immediately with bytes written so far
148- 4. On success, returns total bytes (equals `buffer_size(buffers)`)
143+ 2. If an error occurs, returns immediately with bytes written so far
144+ 3. On success, returns total bytes (equals `buffer_size(buffers)`)
149145
150146== consuming_buffers Helper
151147
@@ -193,10 +189,10 @@ The iterator returns adjusted buffers accounting for consumed bytes.
193189
194190[source,cpp]
195191----
196- auto [ec, n] = co_await corosio ::read(stream, buf);
192+ auto [ec, n] = co_await capy ::read(stream, buf);
197193if (ec)
198194{
199- if (ec == capy::error ::eof)
195+ if (ec == capy::cond ::eof)
200196 std::cout << "End of stream, read " << n << " bytes\n";
201197 else
202198 std::cerr << "Error: " << ec.message() << "\n";
@@ -208,23 +204,25 @@ if (ec)
208204[source,cpp]
209205----
210206// For write (EOF doesn't apply)
211- auto n = (co_await corosio::write(stream, buf)).value();
207+ auto [wec, n] = co_await capy::write(stream, buf);
208+ if (wec)
209+ capy::detail::throw_system_error(wec);
212210
213211// For read (need to handle EOF)
214- auto [ec, n ] = co_await corosio ::read(stream, buf);
215- if (ec && ec != capy::error ::eof)
216- throw boost::system::system_error(ec );
212+ auto [rec, rn ] = co_await capy ::read(stream, buf);
213+ if (rec && rec != capy::cond ::eof)
214+ capy::detail::throw_system_error(rec );
217215----
218216
219217== Cancellation
220218
221219Composed operations support cancellation through the affine protocol. When
222- cancelled, they return with `operation_canceled ` and the partial byte count.
220+ cancelled, they return with `cond::canceled ` and the partial byte count.
223221
224222[source,cpp]
225223----
226- auto [ec, n] = co_await corosio ::read(stream, large_buffer);
227- if (ec == make_error_code(system::errc::operation_canceled) )
224+ auto [ec, n] = co_await capy ::read(stream, large_buffer);
225+ if (ec == capy::cond::canceled )
228226 std::cout << "Cancelled after reading " << n << " bytes\n";
229227----
230228
@@ -238,11 +236,11 @@ For optimal performance with multiple buffers:
238236----
239237// Efficient: single system call per read_some()
240238std::array<capy::mutable_buffer, 2> bufs = {...};
241- co_await corosio ::read(stream, bufs);
239+ co_await capy ::read(stream, bufs);
242240
243241// Less efficient: may require more system calls
244- co_await corosio ::read(stream, buf1);
245- co_await corosio ::read(stream, buf2);
242+ co_await capy ::read(stream, buf1);
243+ co_await capy ::read(stream, buf2);
246244----
247245
248246=== Buffer Sizing
@@ -252,12 +250,12 @@ Choose buffer sizes that match your expected data:
252250* Too small: More system calls
253251* Too large: Memory waste
254252
255- For unknown-length data (like HTTP responses), use the string overload:
253+ For unknown-length data (like HTTP responses), use the dynamic buffer overload:
256254
257255[source,cpp]
258256----
259257std::string response;
260- co_await corosio ::read(stream, response); // Grows as needed
258+ co_await capy ::read(stream, capy::string_dynamic_buffer(& response));
261259----
262260
263261== Example: HTTP Response Reading
@@ -267,11 +265,11 @@ co_await corosio::read(stream, response); // Grows as needed
267265capy::task<std::string> read_http_response(corosio::io_stream& stream)
268266{
269267 std::string response;
270- auto [ec, n] = co_await corosio::read(stream, response);
268+ auto [ec, n] = co_await capy::read(
269+ stream, capy::string_dynamic_buffer(&response));
271270
272- // EOF is expected when server closes connection
273- if (ec && ec != capy::error::eof)
274- throw boost::system::system_error(ec);
271+ if (ec)
272+ capy::detail::throw_system_error(ec);
275273
276274 co_return response;
277275}
0 commit comments