100.00% Lines (35/35) 100.00% Functions (8/8)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/capy 7   // Official repository: https://github.com/cppalliance/capy
8   // 8   //
9   9  
10   #ifndef BOOST_CAPY_BUFFERS_FLAT_DYNAMIC_BUFFER_HPP 10   #ifndef BOOST_CAPY_BUFFERS_FLAT_DYNAMIC_BUFFER_HPP
11   #define BOOST_CAPY_BUFFERS_FLAT_DYNAMIC_BUFFER_HPP 11   #define BOOST_CAPY_BUFFERS_FLAT_DYNAMIC_BUFFER_HPP
12   12  
13   #include <boost/capy/detail/config.hpp> 13   #include <boost/capy/detail/config.hpp>
14   #include <boost/capy/buffers.hpp> 14   #include <boost/capy/buffers.hpp>
15   #include <boost/capy/detail/except.hpp> 15   #include <boost/capy/detail/except.hpp>
16   16  
17   namespace boost { 17   namespace boost {
18   namespace capy { 18   namespace capy {
19   19  
20   /** A fixed-capacity linear buffer satisfying DynamicBuffer. 20   /** A fixed-capacity linear buffer satisfying DynamicBuffer.
21   21  
22   This class provides a contiguous buffer with fixed capacity 22   This class provides a contiguous buffer with fixed capacity
23   determined at construction. Buffer sequences returned from 23   determined at construction. Buffer sequences returned from
24   @ref data and @ref prepare always contain exactly one element, 24   @ref data and @ref prepare always contain exactly one element,
25   making it suitable for APIs requiring contiguous memory. 25   making it suitable for APIs requiring contiguous memory.
26   26  
27   @par Example 27   @par Example
28   @code 28   @code
29   char storage[1024]; 29   char storage[1024];
30   flat_dynamic_buffer fb( storage, sizeof( storage ) ); 30   flat_dynamic_buffer fb( storage, sizeof( storage ) );
31   31  
32   // Write data 32   // Write data
33   auto mb = fb.prepare( 100 ); 33   auto mb = fb.prepare( 100 );
34   std::memcpy( mb.data(), "hello", 5 ); 34   std::memcpy( mb.data(), "hello", 5 );
35   fb.commit( 5 ); 35   fb.commit( 5 );
36   36  
37   // Read data 37   // Read data
38   auto data = fb.data(); 38   auto data = fb.data();
39   // process data... 39   // process data...
40   fb.consume( 5 ); 40   fb.consume( 5 );
41   @endcode 41   @endcode
42   42  
43   @par Thread Safety 43   @par Thread Safety
44   Distinct objects: Safe. 44   Distinct objects: Safe.
45   Shared objects: Unsafe. 45   Shared objects: Unsafe.
46   46  
47   @see circular_dynamic_buffer, string_dynamic_buffer 47   @see circular_dynamic_buffer, string_dynamic_buffer
48   */ 48   */
49   class flat_dynamic_buffer 49   class flat_dynamic_buffer
50   { 50   {
51   unsigned char* data_ = nullptr; 51   unsigned char* data_ = nullptr;
52   std::size_t cap_ = 0; 52   std::size_t cap_ = 0;
53   std::size_t in_pos_ = 0; 53   std::size_t in_pos_ = 0;
54   std::size_t in_size_ = 0; 54   std::size_t in_size_ = 0;
55   std::size_t out_size_ = 0; 55   std::size_t out_size_ = 0;
56   56  
57   public: 57   public:
58   /// Indicates this is a DynamicBuffer adapter over external storage. 58   /// Indicates this is a DynamicBuffer adapter over external storage.
59   using is_dynamic_buffer_adapter = void; 59   using is_dynamic_buffer_adapter = void;
60   60  
61   /// The ConstBufferSequence type for readable bytes. 61   /// The ConstBufferSequence type for readable bytes.
62   using const_buffers_type = const_buffer; 62   using const_buffers_type = const_buffer;
63   63  
64   /// The MutableBufferSequence type for writable bytes. 64   /// The MutableBufferSequence type for writable bytes.
65   using mutable_buffers_type = mutable_buffer; 65   using mutable_buffers_type = mutable_buffer;
66   66  
67   /// Construct an empty flat buffer with zero capacity. 67   /// Construct an empty flat buffer with zero capacity.
68   flat_dynamic_buffer() = default; 68   flat_dynamic_buffer() = default;
69   69  
70   /** Construct a flat buffer over existing storage. 70   /** Construct a flat buffer over existing storage.
71   71  
72   @param data Pointer to the storage. 72   @param data Pointer to the storage.
73   @param capacity Size of the storage in bytes. 73   @param capacity Size of the storage in bytes.
74   @param initial_size Number of bytes already present as 74   @param initial_size Number of bytes already present as
75   readable. Must not exceed @p capacity. 75   readable. Must not exceed @p capacity.
76   76  
77   @throws std::invalid_argument if initial_size > capacity. 77   @throws std::invalid_argument if initial_size > capacity.
78   */ 78   */
HITCBC 79   223 flat_dynamic_buffer( 79   223 flat_dynamic_buffer(
80   void* data, 80   void* data,
81   std::size_t capacity, 81   std::size_t capacity,
82   std::size_t initial_size = 0) 82   std::size_t initial_size = 0)
HITCBC 83   223 : data_(static_cast< 83   223 : data_(static_cast<
84   unsigned char*>(data)) 84   unsigned char*>(data))
HITCBC 85   223 , cap_(capacity) 85   223 , cap_(capacity)
HITCBC 86   223 , in_size_(initial_size) 86   223 , in_size_(initial_size)
87   { 87   {
HITCBC 88   223 if(in_size_ > cap_) 88   223 if(in_size_ > cap_)
HITCBC 89   1 detail::throw_invalid_argument(); 89   1 detail::throw_invalid_argument();
HITCBC 90   222 } 90   222 }
91   91  
92   /// Construct a copy. 92   /// Construct a copy.
93   flat_dynamic_buffer( 93   flat_dynamic_buffer(
94   flat_dynamic_buffer const&) = default; 94   flat_dynamic_buffer const&) = default;
95   95  
96   /// Assign by copying. 96   /// Assign by copying.
97   flat_dynamic_buffer& operator=( 97   flat_dynamic_buffer& operator=(
98   flat_dynamic_buffer const&) = default; 98   flat_dynamic_buffer const&) = default;
99   99  
100   /// Return the number of readable bytes. 100   /// Return the number of readable bytes.
101   std::size_t 101   std::size_t
HITCBC 102   856 size() const noexcept 102   856 size() const noexcept
103   { 103   {
HITCBC 104   856 return in_size_; 104   856 return in_size_;
105   } 105   }
106   106  
107   /// Return the maximum number of bytes the buffer can hold. 107   /// Return the maximum number of bytes the buffer can hold.
108   std::size_t 108   std::size_t
HITCBC 109   10 max_size() const noexcept 109   10 max_size() const noexcept
110   { 110   {
HITCBC 111   10 return cap_; 111   10 return cap_;
112   } 112   }
113   113  
114   /// Return the number of writable bytes without reallocation. 114   /// Return the number of writable bytes without reallocation.
115   std::size_t 115   std::size_t
HITCBC 116   238 capacity() const noexcept 116   238 capacity() const noexcept
117   { 117   {
HITCBC 118   238 return cap_ - (in_pos_ + in_size_); 118   238 return cap_ - (in_pos_ + in_size_);
119   } 119   }
120   120  
121   /// Return a buffer sequence representing the readable bytes. 121   /// Return a buffer sequence representing the readable bytes.
122   const_buffers_type 122   const_buffers_type
HITCBC 123   161 data() const noexcept 123   161 data() const noexcept
124   { 124   {
HITCBC 125   322 return const_buffers_type( 125   322 return const_buffers_type(
HITCBC 126   161 data_ + in_pos_, in_size_); 126   161 data_ + in_pos_, in_size_);
127   } 127   }
128   128  
129   /** Return a buffer sequence for writing. 129   /** Return a buffer sequence for writing.
130   130  
131   Invalidates buffer sequences previously obtained 131   Invalidates buffer sequences previously obtained
132   from @ref prepare. 132   from @ref prepare.
133   133  
134   @param n The desired number of writable bytes. 134   @param n The desired number of writable bytes.
135   135  
136   @return A mutable buffer sequence of size @p n. 136   @return A mutable buffer sequence of size @p n.
137   137  
138   @throws std::invalid_argument if `n > capacity()`. 138   @throws std::invalid_argument if `n > capacity()`.
139   */ 139   */
140   mutable_buffers_type 140   mutable_buffers_type
HITCBC 141   197 prepare(std::size_t n) 141   197 prepare(std::size_t n)
142   { 142   {
HITCBC 143   197 if( n > capacity() ) 143   197 if( n > capacity() )
HITCBC 144   3 detail::throw_invalid_argument(); 144   3 detail::throw_invalid_argument();
145   145  
HITCBC 146   194 out_size_ = n; 146   194 out_size_ = n;
HITCBC 147   388 return mutable_buffers_type( 147   388 return mutable_buffers_type(
HITCBC 148   194 data_ + in_pos_ + in_size_, n); 148   194 data_ + in_pos_ + in_size_, n);
149   } 149   }
150   150  
151   /** Move bytes from the output to the input sequence. 151   /** Move bytes from the output to the input sequence.
152   152  
153   Invalidates buffer sequences previously obtained 153   Invalidates buffer sequences previously obtained
154   from @ref prepare. Buffer sequences from @ref data 154   from @ref prepare. Buffer sequences from @ref data
155   remain valid. 155   remain valid.
156   156  
157   @param n The number of bytes to commit. If greater 157   @param n The number of bytes to commit. If greater
158   than the prepared size, all prepared bytes 158   than the prepared size, all prepared bytes
159   are committed. 159   are committed.
160   */ 160   */
161   void 161   void
HITCBC 162   160 commit( 162   160 commit(
163   std::size_t n) noexcept 163   std::size_t n) noexcept
164   { 164   {
HITCBC 165   160 if(n < out_size_) 165   160 if(n < out_size_)
HITCBC 166   15 in_size_ += n; 166   15 in_size_ += n;
167   else 167   else
HITCBC 168   145 in_size_ += out_size_; 168   145 in_size_ += out_size_;
HITCBC 169   160 out_size_ = 0; 169   160 out_size_ = 0;
HITCBC 170   160 } 170   160 }
171   171  
172   /** Remove bytes from the beginning of the input sequence. 172   /** Remove bytes from the beginning of the input sequence.
173   173  
174   Invalidates buffer sequences previously obtained 174   Invalidates buffer sequences previously obtained
175   from @ref data. Buffer sequences from @ref prepare 175   from @ref data. Buffer sequences from @ref prepare
176   remain valid. 176   remain valid.
177   177  
178   @param n The number of bytes to consume. If greater 178   @param n The number of bytes to consume. If greater
179   than @ref size(), all readable bytes are consumed. 179   than @ref size(), all readable bytes are consumed.
180   */ 180   */
181   void 181   void
HITCBC 182   180 consume( 182   180 consume(
183   std::size_t n) noexcept 183   std::size_t n) noexcept
184   { 184   {
HITCBC 185   180 if(n < in_size_) 185   180 if(n < in_size_)
186   { 186   {
HITCBC 187   15 in_pos_ += n; 187   15 in_pos_ += n;
HITCBC 188   15 in_size_ -= n; 188   15 in_size_ -= n;
189   } 189   }
190   else 190   else
191   { 191   {
HITCBC 192   165 in_pos_ = 0; 192   165 in_pos_ = 0;
HITCBC 193   165 in_size_ = 0; 193   165 in_size_ = 0;
194   } 194   }
HITCBC 195   180 } 195   180 }
196   }; 196   };
197   197  
198   } // capy 198   } // capy
199   } // boost 199   } // boost
200   200  
201   #endif 201   #endif