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