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-02-17 18:14:47 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                 :     ~basic_vector_dynamic_buffer() = default;
      85                 : 
      86                 :     /** Move constructor.
      87                 :     */
      88 HIT           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 MIS           0 :             v_->resize(max_size_);
     117 HIT         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