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

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.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_BUFFERS_VECTOR_DYNAMIC_BUFFER_HPP
      11              : #define BOOST_CAPY_BUFFERS_VECTOR_DYNAMIC_BUFFER_HPP
      12              : 
      13              : #include <boost/capy/detail/config.hpp>
      14              : #include <boost/capy/buffers.hpp>
      15              : #include <boost/capy/detail/except.hpp>
      16              : #include <type_traits>
      17              : #include <vector>
      18              : 
      19              : namespace boost {
      20              : namespace capy {
      21              : 
      22              : /** A dynamic buffer using an underlying vector.
      23              : 
      24              :     This class adapts a `std::vector` of byte-sized elements
      25              :     to satisfy the DynamicBuffer concept. The vector provides
      26              :     automatic memory management and growth.
      27              : 
      28              :     @par Constraints
      29              : 
      30              :     The element type `T` must be a fundamental type with
      31              :     `sizeof( T ) == 1`. This includes `char`, `unsigned char`,
      32              :     `signed char`, and similar byte-sized fundamental types.
      33              : 
      34              :     @par Example
      35              :     @code
      36              :     std::vector<unsigned char> v;
      37              :     vector_dynamic_buffer vb( &v );
      38              : 
      39              :     // Write data
      40              :     auto mb = vb.prepare( 100 );
      41              :     std::memcpy( mb.data(), "hello", 5 );
      42              :     vb.commit( 5 );
      43              : 
      44              :     // Read data
      45              :     auto data = vb.data();
      46              :     // process data...
      47              :     vb.consume( 5 );
      48              :     @endcode
      49              : 
      50              :     @par Thread Safety
      51              :     Distinct objects: Safe.
      52              :     Shared objects: Unsafe.
      53              : 
      54              :     @tparam T The element type. Must be fundamental with sizeof 1.
      55              :     @tparam Allocator The allocator type for the vector.
      56              : 
      57              :     @see flat_dynamic_buffer, circular_dynamic_buffer, string_dynamic_buffer
      58              : */
      59              : template<
      60              :     class T,
      61              :     class Allocator = std::allocator<T>>
      62              :     requires std::is_fundamental_v<T> && (sizeof(T) == 1)
      63              : class basic_vector_dynamic_buffer
      64              : {
      65              :     std::vector<T, Allocator>* v_;
      66              :     std::size_t max_size_;
      67              : 
      68              :     std::size_t in_size_ = 0;
      69              :     std::size_t out_size_ = 0;
      70              : 
      71              : public:
      72              :     /// Indicates this is a DynamicBuffer adapter over external storage.
      73              :     using is_dynamic_buffer_adapter = void;
      74              : 
      75              :     /// The underlying vector type.
      76              :     using vector_type = std::vector<T, Allocator>;
      77              : 
      78              :     /// The ConstBufferSequence type for readable bytes.
      79              :     using const_buffers_type = const_buffer;
      80              : 
      81              :     /// The MutableBufferSequence type for writable bytes.
      82              :     using mutable_buffers_type = mutable_buffer;
      83              : 
      84              :     ~basic_vector_dynamic_buffer() = default;
      85              : 
      86              :     /** Move constructor.
      87              :     */
      88            2 :     basic_vector_dynamic_buffer(
      89              :         basic_vector_dynamic_buffer&& other) noexcept
      90            2 :         : v_(other.v_)
      91            2 :         , max_size_(other.max_size_)
      92            2 :         , in_size_(other.in_size_)
      93            2 :         , out_size_(other.out_size_)
      94              :     {
      95            2 :         other.v_ = nullptr;
      96            2 :     }
      97              : 
      98              :     /** Construct a dynamic buffer over a vector.
      99              : 
     100              :         @param v Pointer to the vector to use as storage.
     101              :         @param max_size Optional maximum size limit. Defaults
     102              :             to the vector's `max_size()`.
     103              :     */
     104              :     explicit
     105          213 :     basic_vector_dynamic_buffer(
     106              :         vector_type* v,
     107              :         std::size_t max_size =
     108              :             std::size_t(-1)) noexcept
     109          213 :         : v_(v)
     110          213 :         , max_size_(
     111          213 :             max_size > v_->max_size()
     112          213 :                 ? v_->max_size()
     113          213 :                 : max_size)
     114              :     {
     115          213 :         if(v_->size() > max_size_)
     116            0 :             v_->resize(max_size_);
     117          213 :         in_size_ = v_->size();
     118          213 :     }
     119              : 
     120              :     /// Copy assignment is deleted.
     121              :     basic_vector_dynamic_buffer& operator=(
     122              :         basic_vector_dynamic_buffer const&) = delete;
     123              : 
     124              :     /// Return the number of readable bytes.
     125              :     std::size_t
     126          820 :     size() const noexcept
     127              :     {
     128          820 :         return in_size_;
     129              :     }
     130              : 
     131              :     /// Return the maximum number of bytes the buffer can hold.
     132              :     std::size_t
     133            2 :     max_size() const noexcept
     134              :     {
     135            2 :         return max_size_;
     136              :     }
     137              : 
     138              :     /// Return the number of writable bytes without reallocation.
     139              :     std::size_t
     140            2 :     capacity() const noexcept
     141              :     {
     142            2 :         if(v_->capacity() <= max_size_)
     143            1 :             return v_->capacity() - in_size_;
     144            1 :         return max_size_ - in_size_;
     145              :     }
     146              : 
     147              :     /// Return a buffer sequence representing the readable bytes.
     148              :     const_buffers_type
     149          147 :     data() const noexcept
     150              :     {
     151          147 :         return const_buffers_type(
     152          294 :             v_->data(), in_size_);
     153              :     }
     154              : 
     155              :     /** Return a buffer sequence for writing.
     156              : 
     157              :         Invalidates buffer sequences previously obtained
     158              :         from @ref prepare.
     159              : 
     160              :         @param n The desired number of writable bytes.
     161              : 
     162              :         @return A mutable buffer sequence of size @p n.
     163              : 
     164              :         @throws std::invalid_argument if `size() + n > max_size()`.
     165              :     */
     166              :     mutable_buffers_type
     167          169 :     prepare(std::size_t n)
     168              :     {
     169          169 :         if(n > max_size_ - in_size_)
     170            1 :             detail::throw_invalid_argument();
     171              : 
     172          168 :         if(v_->size() < in_size_ + n)
     173          167 :             v_->resize(in_size_ + n);
     174          168 :         out_size_ = n;
     175          504 :         return mutable_buffers_type(
     176          168 :             v_->data() + in_size_, out_size_);
     177              :     }
     178              : 
     179              :     /** Move bytes from the output to the input sequence.
     180              : 
     181              :         Invalidates buffer sequences previously obtained
     182              :         from @ref prepare. Buffer sequences from @ref data
     183              :         remain valid.
     184              : 
     185              :         @param n The number of bytes to commit. If greater
     186              :             than the prepared size, all prepared bytes
     187              :             are committed.
     188              :     */
     189              :     void
     190          147 :     commit(std::size_t n) noexcept
     191              :     {
     192          147 :         if(n < out_size_)
     193            1 :             in_size_ += n;
     194              :         else
     195          146 :             in_size_ += out_size_;
     196          147 :         out_size_ = 0;
     197          147 :         v_->resize(in_size_);
     198          147 :     }
     199              : 
     200              :     /** Remove bytes from the beginning of the input sequence.
     201              : 
     202              :         Invalidates buffer sequences previously obtained
     203              :         from @ref data. Buffer sequences from @ref prepare
     204              :         remain valid.
     205              : 
     206              :         @param n The number of bytes to consume. If greater
     207              :             than @ref size(), all readable bytes are consumed.
     208              :     */
     209              :     void
     210          166 :     consume(std::size_t n) noexcept
     211              :     {
     212          166 :         if(n < in_size_)
     213              :         {
     214            1 :             v_->erase(v_->begin(), v_->begin() + n);
     215            1 :             in_size_ -= n;
     216              :         }
     217              :         else
     218              :         {
     219          165 :             v_->clear();
     220          165 :             in_size_ = 0;
     221              :         }
     222          166 :         out_size_ = 0;
     223          166 :     }
     224              : };
     225              : 
     226              : /// A dynamic buffer using `std::vector<unsigned char>`.
     227              : using vector_dynamic_buffer =
     228              :     basic_vector_dynamic_buffer<unsigned char>;
     229              : 
     230              : /** Create a dynamic buffer from a vector.
     231              : 
     232              :     @param v The vector to wrap. Element type must be
     233              :         a fundamental type with sizeof 1.
     234              :     @param max_size Optional maximum size limit.
     235              :     @return A vector_dynamic_buffer wrapping the vector.
     236              : */
     237              : template<class T, class Allocator>
     238              :     requires std::is_fundamental_v<T> && (sizeof(T) == 1)
     239              : basic_vector_dynamic_buffer<T, Allocator>
     240              : dynamic_buffer(
     241              :     std::vector<T, Allocator>& v,
     242              :     std::size_t max_size = std::size_t(-1))
     243              : {
     244              :     return basic_vector_dynamic_buffer<T, Allocator>(&v, max_size);
     245              : }
     246              : 
     247              : } // capy
     248              : } // boost
     249              : 
     250              : #endif
        

Generated by: LCOV version 2.3