From 102f726adc141b1e2fe6bfe0354146a39e4c54a0 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 28 May 2026 22:08:51 +0200 Subject: [PATCH 1/4] Docs: update specification of capy::read --- doc/modules/ROOT/nav.adoc | 3 + .../A.specification-methods/A.intro.adoc | 16 ++ .../Ab.cancellation.adoc | 19 ++ .../Ac.contingencies.adoc | 33 +++ doc/mrdocs.yml | 3 + include/boost/capy/read.hpp | 211 +++++++++++------- include/boost/capy/write.hpp | 15 +- 7 files changed, 209 insertions(+), 91 deletions(-) create mode 100644 doc/modules/ROOT/pages/A.specification-methods/A.intro.adoc create mode 100644 doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc create mode 100644 doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index 7cd9d363a..e6e195b7b 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -71,4 +71,7 @@ ** xref:9.design/9m.WhyNotCobalt.adoc[Why Not Cobalt?] ** xref:9.design/9n.WhyNotCobaltConcepts.adoc[Why Not Cobalt Concepts?] ** xref:9.design/9o.WhyNotTMC.adoc[Why Not TooManyCooks?] +* xref:A.specification-methods/A.intro.adoc[Methods of API Description] +** xref:A.specification-methods/Ab.cancellation.adoc[Cancellation] +** xref:A.specification-methods/Ac.contingencies.adoc[Contingencies] * xref:reference:boost/capy.adoc[Reference] diff --git a/doc/modules/ROOT/pages/A.specification-methods/A.intro.adoc b/doc/modules/ROOT/pages/A.specification-methods/A.intro.adoc new file mode 100644 index 000000000..83184b6ef --- /dev/null +++ b/doc/modules/ROOT/pages/A.specification-methods/A.intro.adoc @@ -0,0 +1,16 @@ +// +// Copyright (c) 2026 Andrzej Krzemieński (akrzemi1@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + += Methods of API Description + + + +This section describes the conventions used to specify the API of this library in the following +xref:reference:boost/capy.adoc[Reference] section. + diff --git a/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc b/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc new file mode 100644 index 000000000..246a89c95 --- /dev/null +++ b/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc @@ -0,0 +1,19 @@ +// +// Copyright (c) 2026 Andrzej Krzemieński (akrzemi1@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + += Cancellation + +A function is said to _support IoAwaitable cancellation_ when its return type +models concept `IoAwaitable` and this return object `a` controls a coroutine which +can be prematuerly stopped using the `std::stop_token` propagated through the +`IoAwaitable` protocol. Additionally, If the result type of expression `co_await a` +in the context of a Capy-coroutine is a specialization of `io_result` then the cancelling of operation is +considered a contingency represented by condition `cond::canceled`. + + diff --git a/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc b/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc new file mode 100644 index 000000000..35b51b30c --- /dev/null +++ b/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc @@ -0,0 +1,33 @@ +// +// Copyright (c) 2026 Andrzej Krzemieński (akrzemi1@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + += Contingencies + +A _contingency_ is any situation caused by the state of streams, +occurring during the operation on these objects that prevents them form reading or +writing the requested number of bytes. + +These situations do not violate the postconditions of the corresponding operations, +as their postconditions never say that the requested number of bytes will indeed be +processed. + +Each stream operation that may encounter a contingency await-returns +a type which is a specialization of `capy::io_result`. These objects can be _destructured_ +using a structured binding. The first binding of such destructuring is of type +`std::error_code`. This subobject, call it `ec`, is used to signal if and which +contingency occured: + + * If `ec == std::error_code{}`, no contingency occurred. + * Otherwise a contingency ocurred. In order to determine which contingency ocurred, + compare `ec` to error conditions, in particular to `capy::cond`. + +NOTE: The stream operations can still throw exceptions to indicate conditions + unrelated to stream state that prevent these operations from satisfying + their postconditions, such as failures to grow a buffer, or failure to + allocate a coroutine frame. \ No newline at end of file diff --git a/doc/mrdocs.yml b/doc/mrdocs.yml index 7a5365349..2560be736 100644 --- a/doc/mrdocs.yml +++ b/doc/mrdocs.yml @@ -26,4 +26,7 @@ multipage: true # use-system-libc: true # use-system-stdlib: true +# Automation +auto-function-metadata: false + cmake: '-DCMAKE_CXX_STANDARD=20 -DBOOST_CAPY_MRDOCS_BUILD=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF' diff --git a/include/boost/capy/read.hpp b/include/boost/capy/read.hpp index 95fcdc8b6..b5d8a93db 100644 --- a/include/boost/capy/read.hpp +++ b/include/boost/capy/read.hpp @@ -25,52 +25,69 @@ namespace boost { namespace capy { -/** Asynchronously read until the buffer sequence is full. +/** Read data from a stream until the buffer sequence is full. - Reads data from the stream by calling `read_some` repeatedly - until the entire buffer sequence is filled or an error occurs. + @par Await-effects - @li The operation completes when: - @li The buffer sequence is completely filled - @li An error occurs (including `cond::eof`) - @li The operation is cancelled + Reads data from `stream` via awaiting `stream.read_some` repeatedly + until: - @par Cancellation - Supports cancellation via `stop_token` propagated through the - IoAwaitable protocol. When cancelled, returns with `cond::canceled`. + @li either the entire buffer sequence @c buffers is filled, + @li or a contingency occurs. - @param stream The stream to read from. The caller retains ownership. - @param buffers The buffer sequence to fill. The caller retains - ownership and must ensure validity until the operation completes. + If `buffer_size(buffers) == 0` then no awaiting `stream.read_some` + is performed. This is not a contingency. + + @par Await-returns + An object of type `io_result` destructuring as `[ec, n]`. + + Upon a contingency, `n` represents the number of bytes read so far. + + Contingencies: + + @li The first contingency reported from awaiting @c stream.read_some . + + Notable conditions: + + @li @c cond::canceled — Operation was cancelled, + @li @c cond::eof — Stream reached end before `buffers` was filled. + + @par Await-postcondition + `ec || n == buffer_size(buffers)`. + + @param stream The stream to read from. If the lifetime of `stream` ends + before the coroutine finishes, the behavior is undefined. + + @param buffers The buffer sequence to fill. If the lifetime of the buffer + sequence represented by `buffers` ends before the coroutine finishes, the behavior is undefined. + + + @par Remarks + Supports _IoAwaitable cancellation_. - @return An awaitable that await-returns `(error_code, std::size_t)`. - On success, `n` equals `buffer_size(buffers)`. On error, - `n` is the number of bytes read before the error. Compare - error codes to conditions: - @li `cond::eof` - Stream reached end before buffer was filled - @li `cond::canceled` - Operation was cancelled @par Example @code - task<> read_message( ReadStream auto& stream ) + capy::task<> process_message(capy::ReadStream auto& stream) { - char header[16]; - auto [ec, n] = co_await read( stream, mutable_buffer( header ) ); - if( ec == cond::eof ) + std::vector header(16); // known header size for some protocol + auto [ec, n] = co_await capy::read(stream, capy::mutable_buffer(header)); + if (ec == capy::cond::eof) co_return; // Connection closed - if( ec ) - detail::throw_system_error( ec ); - // header contains exactly 16 bytes + if (ec) + throw std::system_error(ec); + + // at this point `header` contains exactly 16 bytes } @endcode - @see read_some, ReadStream, MutableBufferSequence + @see ReadStream, MutableBufferSequence */ +template + requires ReadStream && MutableBufferSequence auto -read( - ReadStream auto& stream, - MutableBufferSequence auto buffers) -> +read(S& stream, MB buffers) -> io_task { auto consuming = buffer_slice(buffers); @@ -89,51 +106,66 @@ read( co_return {{}, total_read}; } -/** Asynchronously read all data from a stream into a dynamic buffer. +/** Read all data from a stream into a dynamic buffer. + + @par Await-effects - Reads data by calling `read_some` repeatedly until EOF is reached - or an error occurs. Data is appended using prepare/commit semantics. + Reads data from `stream` via awaiting `stream.read_some` repeatedly + and appending the results to `dynbuf`, + until a contingency occurs. + + Data is appended using prepare/commit semantics. The buffer grows with 1.5x factor when filled. - @li The operation completes when: - @li End-of-stream is reached (`cond::eof`) - @li An error occurs - @li The operation is cancelled + @par Await-returns + + An object of type `io_result` destructuring as `[ec, n]`. - @par Cancellation - Supports cancellation via `stop_token` propagated through the - IoAwaitable protocol. When cancelled, returns with `cond::canceled`. + Upon a contingency, `n` represents the number of bytes read so far. + + Otherwise `n` represents the number of bytes read until the first + contingency from awaiting `stream.read_some` matching to `cond::eof`. + + Contingencies: + + @li The first contingency, other than one maching to @c cond::eof, reported from awaiting @c stream.read_some . + + @par Await-throws + `std::bad_alloc` when append to `dynbuf` fails. + + @param stream The stream to read from. If the lifetime of `stream` ends + before the coroutine finishes, the behavior is undefined. + + @param dynbuf The dynamic buffer to append data to. If the lifetime of the buffer + sequence represented by `dynbuf` ends before the coroutine finishes, the behavior is undefined. - @param stream The stream to read from. The caller retains ownership. - @param buffers The dynamic buffer to append data to. Must remain - valid until the operation completes. @param initial_amount Initial bytes to prepare (default 2048). - @return An awaitable that await-returns `(error_code, std::size_t)`. - On success (EOF), `ec` is clear and `n` is total bytes read. - On error, `n` is bytes read before the error. Compare error - codes to conditions: - @li `cond::canceled` - Operation was cancelled + + @par Remarks + Supports _IoAwaitable cancellation_. @par Example @code - task read_body( ReadStream auto& stream ) + capy::task read_body(capy::ReadStream auto& stream) { std::string body; - auto [ec, n] = co_await read( stream, string_dynamic_buffer( &body ) ); - if( ec ) - detail::throw_system_error( ec ); + auto [ec, n] = co_await read(stream, capy::dynamic_buffer(body)); + if (ec) + throw std::system_error(ec); return body; } @endcode @see read_some, ReadStream, DynamicBufferParam */ +template + requires ReadStream && DynamicBufferParam auto read( - ReadStream auto& stream, - DynamicBufferParam auto&& buffers, + S& stream, + DB&& dynbuf, std::size_t initial_amount = 2048) -> io_task { @@ -141,10 +173,10 @@ read( std::size_t total_read = 0; for(;;) { - auto mb = buffers.prepare(amount); + auto mb = dynbuf.prepare(amount); auto const mb_size = buffer_size(mb); auto [ec, n] = co_await stream.read_some(mb); - buffers.commit(n); + dynbuf.commit(n); total_read += n; if(ec == cond::eof) co_return {{}, total_read}; @@ -155,51 +187,66 @@ read( } } -/** Asynchronously read all data from a source into a dynamic buffer. +/** Read all data from a source into a dynamic buffer. - Reads data by calling `source.read` repeatedly until EOF is reached - or an error occurs. Data is appended using prepare/commit semantics. + @par Await-effects + + Reads data from `stream` by calling `source.read` repeatedly + and appending it to `dynbuf` until a contingency occurs. + + Data is appended using prepare/commit semantics. The buffer grows with 1.5x factor when filled. - @li The operation completes when: - @li End-of-stream is reached (`cond::eof`) - @li An error occurs - @li The operation is cancelled + @par Await-returns + + An object of type `io_result` destructuring as `[ec, n]`. + + Upon a contingency, `n` represents the number of bytes read so far. + + Otherwise `n` represents the number of bytes read until the first + contingency from awaiting `stream.read_some` matching to `cond::eof`. + + Contingencies: + + @li The first contingency, other than one maching to @c cond::eof, reported from awaiting @c stream.read_some . + + @par Await-throws + + `std::bad_alloc` when append to `dynbuf` fails. + + @param source The source to read from. If the lifetime of `source` ends + before the coroutine finishes, the behavior is undefined. - @par Cancellation - Supports cancellation via `stop_token` propagated through the - IoAwaitable protocol. When cancelled, returns with `cond::canceled`. + @param dynbuf The dynamic buffer to append data to. If the lifetime of the + buffer sequence represented by `dynbuf` ends before the coroutine finishes, + the behavior is undefined. - @param source The source to read from. The caller retains ownership. - @param buffers The dynamic buffer to append data to. Must remain - valid until the operation completes. @param initial_amount Initial bytes to prepare (default 2048). - @return An awaitable that await-returns `(error_code, std::size_t)`. - On success (EOF), `ec` is clear and `n` is total bytes read. - On error, `n` is bytes read before the error. Compare error - codes to conditions: - @li `cond::canceled` - Operation was cancelled + @par Remarks + Supports _IoAwaitable cancellation_. @par Example @code - task read_body( ReadSource auto& source ) + capy::task read_body(capy::ReadSource auto& source) { std::string body; - auto [ec, n] = co_await read( source, string_dynamic_buffer( &body ) ); - if( ec ) - detail::throw_system_error( ec ); + auto [ec, n] = co_await capy::read(source, capy::dynamic_buffer(body)); + if (ec) + throw std::system_error(ec); return body; } @endcode @see ReadSource, DynamicBufferParam */ +template + requires ReadSource && DynamicBufferParam auto read( - ReadSource auto& source, - DynamicBufferParam auto&& buffers, + S& source, + DB&& dynbuf, std::size_t initial_amount = 2048) -> io_task { @@ -207,10 +254,10 @@ read( std::size_t total_read = 0; for(;;) { - auto mb = buffers.prepare(amount); + auto mb = dynbuf.prepare(amount); auto const mb_size = buffer_size(mb); auto [ec, n] = co_await source.read(mb); - buffers.commit(n); + dynbuf.commit(n); total_read += n; if(ec == cond::eof) co_return {{}, total_read}; diff --git a/include/boost/capy/write.hpp b/include/boost/capy/write.hpp index e3ff3e1e9..70256af32 100644 --- a/include/boost/capy/write.hpp +++ b/include/boost/capy/write.hpp @@ -26,14 +26,14 @@ namespace capy { @par Await-effects - Writes the contents of `buffers` to `stream` via awaiting on + Writes the contents of `buffers` to `stream` via awaiting `stream.write_some` with consecutive portions of data from `buffers` until: @li either the full content of @c buffers is processed, @li or a contingency occurs. - If `buffer_size(buffers) == 0` then no awaiting on `stream.write_some` + If `buffer_size(buffers) == 0` then no awaiting `stream.write_some` is performed. This is not a contingency. @@ -49,7 +49,7 @@ namespace capy { Contingencies: @li The first contingency reported from - awaiting on @c stream.write_some . + awaiting @c stream.write_some . Notable conditions: @@ -62,10 +62,6 @@ namespace capy { `ec || n == buffer_size(buffers)`. - @par Cancellation - Supports cancellation via `stop_token` propagated through the - `IoAwaitable` protocol. When cancelled, returns with `cond::canceled`. - @param stream The stream to write to. If the lifetime of `stream` ends before the coroutine finishes, the behavior is undefined. @@ -73,6 +69,9 @@ namespace capy { sequence represented by `buffers` ends before the coroutine finishes, the behavior is undefined. + @par Remarks + + Supports _IoAwaitable cancellation_. @par Example @@ -87,8 +86,6 @@ namespace capy { } @endcode - @return - @see WriteStream, ConstBufferSequence, IoAwaitable, io_result, cond. */ template From b31565ad504f6849482fd2dbfb2ccc19f4a8d76d Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 29 May 2026 07:27:04 +0200 Subject: [PATCH 2/4] grammar fixes --- .../Ab.cancellation.adoc | 4 ++-- .../Ac.contingencies.adoc | 17 +++++++++++------ include/boost/capy/read.hpp | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc b/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc index 246a89c95..6ff6760e4 100644 --- a/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc +++ b/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc @@ -11,8 +11,8 @@ A function is said to _support IoAwaitable cancellation_ when its return type models concept `IoAwaitable` and this return object `a` controls a coroutine which -can be prematuerly stopped using the `std::stop_token` propagated through the -`IoAwaitable` protocol. Additionally, If the result type of expression `co_await a` +can be prematurely stopped using the `std::stop_token` propagated through the +`IoAwaitable` protocol. Additionally, if the result type of expression `co_await a` in the context of a Capy-coroutine is a specialization of `io_result` then the cancelling of operation is considered a contingency represented by condition `cond::canceled`. diff --git a/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc b/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc index 35b51b30c..80bd4e67d 100644 --- a/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc +++ b/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc @@ -9,9 +9,9 @@ = Contingencies -A _contingency_ is any situation caused by the state of streams, -occurring during the operation on these objects that prevents them form reading or -writing the requested number of bytes. +A _contingency_ is any situation caused by the state of a stream, +occurring during the operation on the stream that prevents them +from reading or writing the requested number of bytes. These situations do not violate the postconditions of the corresponding operations, as their postconditions never say that the requested number of bytes will indeed be @@ -24,10 +24,15 @@ using a structured binding. The first binding of such destructuring is of type contingency occured: * If `ec == std::error_code{}`, no contingency occurred. - * Otherwise a contingency ocurred. In order to determine which contingency ocurred, + * Otherwise a contingency occurred. In order to determine which contingency occurred, compare `ec` to error conditions, in particular to `capy::cond`. +NOTE: Reaching the end of stream is also a contingency + (which can be interpeted as preventing an infinnite read + from proceeding). So is the cancelling an operation + by the invoker. + NOTE: The stream operations can still throw exceptions to indicate conditions unrelated to stream state that prevent these operations from satisfying - their postconditions, such as failures to grow a buffer, or failure to - allocate a coroutine frame. \ No newline at end of file + their postconditions, such as failures to grow a buffer, or + failure to allocate a coroutine frame. diff --git a/include/boost/capy/read.hpp b/include/boost/capy/read.hpp index b5d8a93db..5b149dd7f 100644 --- a/include/boost/capy/read.hpp +++ b/include/boost/capy/read.hpp @@ -128,7 +128,7 @@ read(S& stream, MB buffers) -> Contingencies: - @li The first contingency, other than one maching to @c cond::eof, reported from awaiting @c stream.read_some . + @li The first contingency, other than one matching to @c cond::eof, reported from awaiting @c stream.read_some . @par Await-throws `std::bad_alloc` when append to `dynbuf` fails. @@ -151,7 +151,7 @@ read(S& stream, MB buffers) -> capy::task read_body(capy::ReadStream auto& stream) { std::string body; - auto [ec, n] = co_await read(stream, capy::dynamic_buffer(body)); + auto [ec, n] = co_await capy::read(stream, capy::dynamic_buffer(body)); if (ec) throw std::system_error(ec); return body; @@ -208,7 +208,7 @@ read( Contingencies: - @li The first contingency, other than one maching to @c cond::eof, reported from awaiting @c stream.read_some . + @li The first contingency, other than one matching to @c cond::eof, reported from awaiting @c stream.read_some . @par Await-throws From 8ca33aefb51a573a181096055aa50a7362e43280 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 29 May 2026 23:20:21 +0200 Subject: [PATCH 3/4] third fix round --- .../Ab.cancellation.adoc | 3 ++- .../Ac.contingencies.adoc | 18 ++++++++++++------ include/boost/capy/read.hpp | 12 +++++++----- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc b/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc index 6ff6760e4..145b7b1c4 100644 --- a/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc +++ b/doc/modules/ROOT/pages/A.specification-methods/Ab.cancellation.adoc @@ -13,7 +13,8 @@ A function is said to _support IoAwaitable cancellation_ when its return type models concept `IoAwaitable` and this return object `a` controls a coroutine which can be prematurely stopped using the `std::stop_token` propagated through the `IoAwaitable` protocol. Additionally, if the result type of expression `co_await a` -in the context of a Capy-coroutine is a specialization of `io_result` then the cancelling of operation is +in the context of a Capy-coroutine is a specialization of `io_result` +then the cancelling of an operation is considered a contingency represented by condition `cond::canceled`. diff --git a/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc b/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc index 80bd4e67d..54ccc9caa 100644 --- a/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc +++ b/doc/modules/ROOT/pages/A.specification-methods/Ac.contingencies.adoc @@ -9,8 +9,8 @@ = Contingencies -A _contingency_ is any situation caused by the state of a stream, -occurring during the operation on the stream that prevents them +A _contingency_ is any situation occurring during an operation +on a stream, caused by the stream's state, that prevents this operation from reading or writing the requested number of bytes. These situations do not violate the postconditions of the corresponding operations, @@ -20,7 +20,7 @@ processed. Each stream operation that may encounter a contingency await-returns a type which is a specialization of `capy::io_result`. These objects can be _destructured_ using a structured binding. The first binding of such destructuring is of type -`std::error_code`. This subobject, call it `ec`, is used to signal if and which +`std::error_code`. This binding, call it `ec`, is used to signal if and which contingency occured: * If `ec == std::error_code{}`, no contingency occurred. @@ -28,11 +28,17 @@ contingency occured: compare `ec` to error conditions, in particular to `capy::cond`. NOTE: Reaching the end of stream is also a contingency - (which can be interpeted as preventing an infinnite read - from proceeding). So is the cancelling an operation - by the invoker. + (which can be interpreted as preventing an infinite read + from proceeding). NOTE: The stream operations can still throw exceptions to indicate conditions unrelated to stream state that prevent these operations from satisfying their postconditions, such as failures to grow a buffer, or failure to allocate a coroutine frame. + +NOTE: Operations on streams often await-return `capy::io_result` + destructuring to `[ec, n]`, where `n` represents the number of processed bytes. + Upon a reported contingency, a non-zero `n` indicates the state of the partial + or sometimes even a full read. When an inner operation reports a contingency, + the outer operation usually processes its partial results before reporting + the contingency itself. \ No newline at end of file diff --git a/include/boost/capy/read.hpp b/include/boost/capy/read.hpp index 5b149dd7f..db9d35262 100644 --- a/include/boost/capy/read.hpp +++ b/include/boost/capy/read.hpp @@ -41,7 +41,8 @@ namespace capy { @par Await-returns An object of type `io_result` destructuring as `[ec, n]`. - Upon a contingency, `n` represents the number of bytes read so far. + Upon a contingency, `n` represents the number of bytes read so far, + inclusive of the last partial read. Contingencies: @@ -121,7 +122,8 @@ read(S& stream, MB buffers) -> An object of type `io_result` destructuring as `[ec, n]`. - Upon a contingency, `n` represents the number of bytes read so far. + Upon a contingency, `n` represents the number of bytes read so far, + inclusive of the last partial read. Otherwise `n` represents the number of bytes read until the first contingency from awaiting `stream.read_some` matching to `cond::eof`. @@ -193,6 +195,7 @@ read( Reads data from `stream` by calling `source.read` repeatedly and appending it to `dynbuf` until a contingency occurs. + The last, potenitally partial, read is also appended. Data is appended using prepare/commit semantics. The buffer grows with 1.5x factor when filled. @@ -201,10 +204,9 @@ read( An object of type `io_result` destructuring as `[ec, n]`. - Upon a contingency, `n` represents the number of bytes read so far. + `n` represents the number of bytes read so far, + inclusive of the last partial read. - Otherwise `n` represents the number of bytes read until the first - contingency from awaiting `stream.read_some` matching to `cond::eof`. Contingencies: From 2b1951ca32c5c6f16bb7bac040401eed11c0e377 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 29 May 2026 23:31:52 +0200 Subject: [PATCH 4/4] one more fix --- include/boost/capy/read.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/include/boost/capy/read.hpp b/include/boost/capy/read.hpp index db9d35262..4a85aa9cd 100644 --- a/include/boost/capy/read.hpp +++ b/include/boost/capy/read.hpp @@ -122,12 +122,9 @@ read(S& stream, MB buffers) -> An object of type `io_result` destructuring as `[ec, n]`. - Upon a contingency, `n` represents the number of bytes read so far, + `n` represents the total number of bytes read, inclusive of the last partial read. - Otherwise `n` represents the number of bytes read until the first - contingency from awaiting `stream.read_some` matching to `cond::eof`. - Contingencies: @li The first contingency, other than one matching to @c cond::eof, reported from awaiting @c stream.read_some . @@ -204,7 +201,7 @@ read( An object of type `io_result` destructuring as `[ec, n]`. - `n` represents the number of bytes read so far, + `n` represents the total number of bytes read, inclusive of the last partial read.