LCOV - code coverage report
Current view: top level - capy/buffers - vector_dynamic_buffer.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 98.0 % 51 50 1
Test Date: 2026-03-09 21:20:58 Functions: 100.0 % 9 9

           TLA  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                 :     /// Destroy the buffer.
      85                 :     ~basic_vector_dynamic_buffer() = default;
      86                 : 
      87                 :     /** Construct by moving.
      88                 :     */
      89 HIT           2 :     basic_vector_dynamic_buffer(
      90                 :         basic_vector_dynamic_buffer&& other) noexcept
      91               2 :         : v_(other.v_)
      92               2 :         , max_size_(other.max_size_)
      93               2 :         , in_size_(other.in_size_)
      94               2 :         , out_size_(other.out_size_)
      95                 :     {
      96               2 :         other.v_ = nullptr;
      97               2 :     }
      98                 : 
      99                 :     /** Construct a dynamic buffer over a vector.
     100                 : 
     101                 :         @param v Pointer to the vector to use as storage.
     102                 :         @param max_size Optional maximum size limit. Defaults
     103                 :             to the vector's `max_size()`.
     104                 :     */
     105                 :     explicit
     106             213 :     basic_vector_dynamic_buffer(
     107                 :         vector_type* v,
     108                 :         std::size_t max_size =
     109                 :             std::size_t(-1)) noexcept
     110             213 :         : v_(v)
     111             213 :         , max_size_(
     112             213 :             max_size > v_->max_size()
     113             213 :                 ? v_->max_size()
     114             213 :                 : max_size)
     115                 :     {
     116             213 :         if(v_->size() > max_size_)
     117 MIS           0 :             v_->resize(max_size_);
     118 HIT         213 :         in_size_ = v_->size();
     119             213 :     }
     120                 : 
     121                 :     /// Copy assignment is deleted.
     122                 :     basic_vector_dynamic_buffer& operator=(
     123                 :         basic_vector_dynamic_buffer const&) = delete;
     124                 : 
     125                 :     /// Return the number of readable bytes.
     126                 :     std::size_t
     127             820 :     size() const noexcept
     128                 :     {
     129             820 :         return in_size_;
     130                 :     }
     131                 : 
     132                 :     /// Return the maximum number of bytes the buffer can hold.
     133                 :     std::size_t
     134               2 :     max_size() const noexcept
     135                 :     {
     136               2 :         return max_size_;
     137                 :     }
     138                 : 
     139                 :     /// Return the number of writable bytes without reallocation.
     140                 :     std::size_t
     141               2 :     capacity() const noexcept
     142                 :     {
     143               2 :         if(v_->capacity() <= max_size_)
     144               1 :             return v_->capacity() - in_size_;
     145               1 :         return max_size_ - in_size_;
     146                 :     }
     147                 : 
     148                 :     /// Return a buffer sequence representing the readable bytes.
     149                 :     const_buffers_type
     150             147 :     data() const noexcept
     151                 :     {
     152             147 :         return const_buffers_type(
     153             294 :             v_->data(), in_size_);
     154                 :     }
     155                 : 
     156                 :     /** Return a buffer sequence for writing.
     157                 : 
     158                 :         Invalidates buffer sequences previously obtained
     159                 :         from @ref prepare.
     160                 : 
     161                 :         @param n The desired number of writable bytes.
     162                 : 
     163                 :         @return A mutable buffer sequence of size @p n.
     164                 : 
     165                 :         @throws std::invalid_argument if `size() + n > max_size()`.
     166                 :     */
     167                 :     mutable_buffers_type
     168             169 :     prepare(std::size_t n)
     169                 :     {
     170             169 :         if(n > max_size_ - in_size_)
     171               1 :             detail::throw_invalid_argument();
     172                 : 
     173             168 :         if(v_->size() < in_size_ + n)
     174             167 :             v_->resize(in_size_ + n);
     175             168 :         out_size_ = n;
     176             504 :         return mutable_buffers_type(
     177             168 :             v_->data() + in_size_, out_size_);
     178                 :     }
     179                 : 
     180                 :     /** Move bytes from the output to the input sequence.
     181                 : 
     182                 :         Invalidates buffer sequences previously obtained
     183                 :         from @ref prepare. Buffer sequences from @ref data
     184                 :         remain valid.
     185                 : 
     186                 :         @param n The number of bytes to commit. If greater
     187                 :             than the prepared size, all prepared bytes
     188                 :             are committed.
     189                 :     */
     190                 :     void
     191             147 :     commit(std::size_t n) noexcept
     192                 :     {
     193             147 :         if(n < out_size_)
     194               1 :             in_size_ += n;
     195                 :         else
     196             146 :             in_size_ += out_size_;
     197             147 :         out_size_ = 0;
     198             147 :         v_->resize(in_size_);
     199             147 :     }
     200                 : 
     201                 :     /** Remove bytes from the beginning of the input sequence.
     202                 : 
     203                 :         Invalidates buffer sequences previously obtained
     204                 :         from @ref data. Buffer sequences from @ref prepare
     205                 :         remain valid.
     206                 : 
     207                 :         @param n The number of bytes to consume. If greater
     208                 :             than @ref size(), all readable bytes are consumed.
     209                 :     */
     210                 :     void
     211             166 :     consume(std::size_t n) noexcept
     212                 :     {
     213             166 :         if(n < in_size_)
     214                 :         {
     215               1 :             v_->erase(v_->begin(), v_->begin() + n);
     216               1 :             in_size_ -= n;
     217                 :         }
     218                 :         else
     219                 :         {
     220             165 :             v_->clear();
     221             165 :             in_size_ = 0;
     222                 :         }
     223             166 :         out_size_ = 0;
     224             166 :     }
     225                 : };
     226                 : 
     227                 : /// A dynamic buffer using `std::vector<unsigned char>`.
     228                 : using vector_dynamic_buffer =
     229                 :     basic_vector_dynamic_buffer<unsigned char>;
     230                 : 
     231                 : /** Create a dynamic buffer from a vector.
     232                 : 
     233                 :     @param v The vector to wrap. Element type must be
     234                 :         a fundamental type with sizeof 1.
     235                 :     @param max_size Optional maximum size limit.
     236                 :     @return A vector_dynamic_buffer wrapping the vector.
     237                 : */
     238                 : template<class T, class Allocator>
     239                 :     requires std::is_fundamental_v<T> && (sizeof(T) == 1)
     240                 : basic_vector_dynamic_buffer<T, Allocator>
     241                 : dynamic_buffer(
     242                 :     std::vector<T, Allocator>& v,
     243                 :     std::size_t max_size = std::size_t(-1))
     244                 : {
     245                 :     return basic_vector_dynamic_buffer<T, Allocator>(&v, max_size);
     246                 : }
     247                 : 
     248                 : } // capy
     249                 : } // boost
     250                 : 
     251                 : #endif
        

Generated by: LCOV version 2.3