1 // 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/boostorg/beast 8 // 9 10 #ifndef BOOST_BEAST_FLAT_STATIC_BUFFER_HPP 11 #define BOOST_BEAST_FLAT_STATIC_BUFFER_HPP 12 13 #include <boost/beast/core/detail/config.hpp> 14 #include <boost/asio/buffer.hpp> 15 #include <algorithm> 16 #include <cstddef> 17 #include <cstring> 18 19 namespace boost { 20 namespace beast { 21 22 /** A dynamic buffer using a fixed size internal buffer. 23 24 A dynamic buffer encapsulates memory storage that may be 25 automatically resized as required, where the memory is 26 divided into two regions: readable bytes followed by 27 writable bytes. These memory regions are internal to 28 the dynamic buffer, but direct access to the elements 29 is provided to permit them to be efficiently used with 30 I/O operations. 31 32 Objects of this type meet the requirements of <em>DynamicBuffer</em> 33 and have the following additional properties: 34 35 @li A mutable buffer sequence representing the readable 36 bytes is returned by @ref data when `this` is non-const. 37 38 @li Buffer sequences representing the readable and writable 39 bytes, returned by @ref data and @ref prepare, will have 40 length one. 41 42 @li Ownership of the underlying storage belongs to the 43 derived class. 44 45 @note Variables are usually declared using the template class 46 @ref flat_static_buffer; however, to reduce the number of template 47 instantiations, objects should be passed `flat_static_buffer_base&`. 48 49 @see flat_static_buffer 50 */ 51 class flat_static_buffer_base 52 { 53 char* begin_; 54 char* in_; 55 char* out_; 56 char* last_; 57 char* end_; 58 59 flat_static_buffer_base( 60 flat_static_buffer_base const& other) = delete; 61 flat_static_buffer_base& operator=( 62 flat_static_buffer_base const&) = delete; 63 64 public: 65 /** Constructor 66 67 This creates a dynamic buffer using the provided storage area. 68 69 @param p A pointer to valid storage of at least `n` bytes. 70 71 @param n The number of valid bytes pointed to by `p`. 72 */ flat_static_buffer_base(void * p,std::size_t n)73 flat_static_buffer_base( 74 void* p, std::size_t n) noexcept 75 { 76 reset(p, n); 77 } 78 79 /** Clear the readable and writable bytes to zero. 80 81 This function causes the readable and writable bytes 82 to become empty. The capacity is not changed. 83 84 Buffer sequences previously obtained using @ref data or 85 @ref prepare become invalid. 86 87 @esafe 88 89 No-throw guarantee. 90 */ 91 BOOST_BEAST_DECL 92 void 93 clear() noexcept; 94 95 //-------------------------------------------------------------------------- 96 97 /// The ConstBufferSequence used to represent the readable bytes. 98 using const_buffers_type = net::const_buffer; 99 100 /// The MutableBufferSequence used to represent the writable bytes. 101 using mutable_buffers_type = net::mutable_buffer; 102 103 /// Returns the number of readable bytes. 104 std::size_t size() const105 size() const noexcept 106 { 107 return out_ - in_; 108 } 109 110 /// Return the maximum number of bytes, both readable and writable, that can ever be held. 111 std::size_t max_size() const112 max_size() const noexcept 113 { 114 return dist(begin_, end_); 115 } 116 117 /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation. 118 std::size_t capacity() const119 capacity() const noexcept 120 { 121 return max_size(); 122 } 123 124 /// Returns a constant buffer sequence representing the readable bytes 125 const_buffers_type data() const126 data() const noexcept 127 { 128 return {in_, dist(in_, out_)}; 129 } 130 131 /// Returns a constant buffer sequence representing the readable bytes 132 const_buffers_type cdata() const133 cdata() const noexcept 134 { 135 return data(); 136 } 137 138 /// Returns a mutable buffer sequence representing the readable bytes 139 mutable_buffers_type data()140 data() noexcept 141 { 142 return {in_, dist(in_, out_)}; 143 } 144 145 /** Returns a mutable buffer sequence representing writable bytes. 146 147 Returns a mutable buffer sequence representing the writable 148 bytes containing exactly `n` bytes of storage. 149 150 All buffers sequences previously obtained using 151 @ref data or @ref prepare are invalidated. 152 153 @param n The desired number of bytes in the returned buffer 154 sequence. 155 156 @throws std::length_error if `size() + n` exceeds `max_size()`. 157 158 @esafe 159 160 Strong guarantee. 161 */ 162 BOOST_BEAST_DECL 163 mutable_buffers_type 164 prepare(std::size_t n); 165 166 /** Append writable bytes to the readable bytes. 167 168 Appends n bytes from the start of the writable bytes to the 169 end of the readable bytes. The remainder of the writable bytes 170 are discarded. If n is greater than the number of writable 171 bytes, all writable bytes are appended to the readable bytes. 172 173 All buffers sequences previously obtained using 174 @ref data or @ref prepare are invalidated. 175 176 @param n The number of bytes to append. If this number 177 is greater than the number of writable bytes, all 178 writable bytes are appended. 179 180 @esafe 181 182 No-throw guarantee. 183 */ 184 void commit(std::size_t n)185 commit(std::size_t n) noexcept 186 { 187 out_ += (std::min<std::size_t>)(n, last_ - out_); 188 } 189 190 /** Remove bytes from beginning of the readable bytes. 191 192 Removes n bytes from the beginning of the readable bytes. 193 194 All buffers sequences previously obtained using 195 @ref data or @ref prepare are invalidated. 196 197 @param n The number of bytes to remove. If this number 198 is greater than the number of readable bytes, all 199 readable bytes are removed. 200 201 @esafe 202 203 No-throw guarantee. 204 */ 205 BOOST_BEAST_DECL 206 void 207 consume(std::size_t n) noexcept; 208 209 protected: 210 /** Constructor 211 212 The buffer will be in an undefined state. It is necessary 213 for the derived class to call @ref reset with a pointer 214 and size in order to initialize the object. 215 */ 216 flat_static_buffer_base() = default; 217 218 /** Reset the pointed-to buffer. 219 220 This function resets the internal state to the buffer provided. 221 All input and output sequences are invalidated. This function 222 allows the derived class to construct its members before 223 initializing the static buffer. 224 225 @param p A pointer to valid storage of at least `n` bytes. 226 227 @param n The number of valid bytes pointed to by `p`. 228 229 @esafe 230 231 No-throw guarantee. 232 */ 233 BOOST_BEAST_DECL 234 void 235 reset(void* p, std::size_t n) noexcept; 236 237 private: 238 static 239 std::size_t dist(char const * first,char const * last)240 dist(char const* first, char const* last) noexcept 241 { 242 return static_cast<std::size_t>(last - first); 243 } 244 }; 245 246 //------------------------------------------------------------------------------ 247 248 /** A <em>DynamicBuffer</em> with a fixed size internal buffer. 249 250 Buffer sequences returned by @ref data and @ref prepare 251 will always be of length one. 252 This implements a dynamic buffer using no memory allocations. 253 254 @tparam N The number of bytes in the internal buffer. 255 256 @note To reduce the number of template instantiations when passing 257 objects of this type in a deduced context, the signature of the 258 receiving function should use @ref flat_static_buffer_base instead. 259 260 @see flat_static_buffer_base 261 */ 262 template<std::size_t N> 263 class flat_static_buffer : public flat_static_buffer_base 264 { 265 char buf_[N]; 266 267 public: 268 /// Constructor 269 flat_static_buffer(flat_static_buffer const&); 270 271 /// Constructor flat_static_buffer()272 flat_static_buffer() 273 : flat_static_buffer_base(buf_, N) 274 { 275 } 276 277 /// Assignment 278 flat_static_buffer& operator=(flat_static_buffer const&); 279 280 /// Returns the @ref flat_static_buffer_base portion of this object 281 flat_static_buffer_base& base()282 base() 283 { 284 return *this; 285 } 286 287 /// Returns the @ref flat_static_buffer_base portion of this object 288 flat_static_buffer_base const& base() const289 base() const 290 { 291 return *this; 292 } 293 294 /// Return the maximum sum of the input and output sequence sizes. 295 std::size_t constexpr max_size() const296 max_size() const 297 { 298 return N; 299 } 300 301 /// Return the maximum sum of input and output sizes that can be held without an allocation. 302 std::size_t constexpr capacity() const303 capacity() const 304 { 305 return N; 306 } 307 }; 308 309 } // beast 310 } // boost 311 312 #include <boost/beast/core/impl/flat_static_buffer.hpp> 313 #ifdef BOOST_BEAST_HEADER_ONLY 314 #include <boost/beast/core/impl/flat_static_buffer.ipp> 315 #endif 316 317 #endif