LCOV - code coverage report
Current view: top level - boost/capy - read.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 6 6
Test Date: 2026-01-30 23:43:15 Functions: 100.0 % 6 6

            Line data    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           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           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           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
        

Generated by: LCOV version 2.3