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/http_proto 8 : // 9 : 10 : #ifndef BOOST_HTTP_PROTO_BUFFERED_BASE_HPP 11 : #define BOOST_HTTP_PROTO_BUFFERED_BASE_HPP 12 : 13 : #include <boost/http_proto/detail/config.hpp> 14 : #include <cstddef> 15 : 16 : namespace boost { 17 : namespace http_proto { 18 : 19 : /** Base class for buffered algorithms 20 : 21 : Algorithms implementing @ref filter, 22 : @ref source, or @ref sink inherit from 23 : this common interface. 24 : */ 25 : struct BOOST_HTTP_PROTO_DECL 26 46 : buffered_base 27 : { 28 : /** Allocator for buffered algorithms. 29 : */ 30 : class allocator; 31 : 32 : /** Destructor. 33 : */ 34 : virtual 35 : ~buffered_base(); 36 : 37 : /** Initialize the algorithm. 38 : 39 : The derived class must be initialized 40 : before invoking any other members, 41 : except destruction. 42 : The default implementation does nothing. 43 : The purpose of this function is to 44 : allow the derived class to optionally 45 : allocate temporary storage using the 46 : specified allocator, which could offer 47 : advantages. 48 : <br> 49 : Subclasses are still required to operate 50 : correctly even when insufficient storage 51 : is available from the allocator. In this 52 : case they should simply allocate normally. 53 : 54 : @par Preconditions 55 : Initialization has not already occurred. 56 : 57 : @param a The allocator to use. 58 : */ 59 : void 60 23 : init(allocator& a) 61 : { 62 23 : on_init(a); 63 20 : } 64 : 65 : /** Initialize the algorithm. 66 : 67 : The derived class must be initialized 68 : before invoking any other members, 69 : except destruction. 70 : The default implementation does nothing. 71 : The purpose of this function is to 72 : allow the derived class to optionally 73 : allocate temporary storage using the 74 : specified allocator, which could offer 75 : advantages. 76 : <br> 77 : Subclasses are still required to operate 78 : correctly even when insufficient storage 79 : is available from the allocator. In this 80 : case they should simply allocate normally. 81 : 82 : @par Preconditions 83 : Initialization has not already occurred. 84 : 85 : @throws std::invalid_argument `max_size > a.max_size()` 86 : 87 : @param a The allocator to use. 88 : 89 : @param max_size The largest allowed 90 : total amount of bytes for the 91 : allocator. 92 : */ 93 : void 94 : init( 95 : allocator& a, 96 : std::size_t max_size); 97 : 98 : protected: 99 : /** Initialize the algorithm. 100 : 101 : The default implementation does nothing. 102 : The purpose of this function is to 103 : allow the derived class to optionally 104 : allocate temporary storage using the 105 : specified allocator, which could offer 106 : advantages. 107 : <br> 108 : Subclasses are still required to operate 109 : correctly even when insufficient storage 110 : is available from the allocator. In this 111 : case they should simply allocate normally. 112 : 113 : @par Preconditions 114 : Initialization has not already occurred. 115 : 116 : @param a The allocator to use. 117 : */ 118 : virtual 119 : void 120 : on_init(allocator& a); 121 : }; 122 : 123 : //------------------------------------------------ 124 : 125 : /** Provides memory to buffered algorithms. 126 : */ 127 : class buffered_base::allocator 128 : { 129 : public: 130 : /** Constructor 131 : 132 : Default constructed objects return 133 : zero from @ref max_size. 134 : */ 135 : allocator() = default; 136 : 137 : /** Constructor 138 : 139 : This function constructs an allocator 140 : which uses the specified contiguous 141 : buffer. Calls to allocate will return 142 : parcels of the buffer from either the 143 : beginning or the end depending on the 144 : value of `downwards`. 145 : 146 : @par Preconditions 147 : @code 148 : p != nullptr || n == 0 149 : @endcode 150 : 151 : @par Exception Safety 152 : Throws nothing. 153 : 154 : @param p A pointer to contiguous storage. 155 : This may be `nullptr` if `n == 0`. 156 : 157 : @param n The number of valid bytes of 158 : storage pointed to by p. This may 159 : be zero. 160 : 161 : @param downwards When true, calls to 162 : allocate will return storage from 163 : the end of the memory pointed to 164 : by `p` rather than the beginning. 165 : */ 166 18 : allocator( 167 : void* p, 168 : std::size_t n, 169 : bool downwards) noexcept 170 18 : : base_(static_cast< 171 : unsigned char*>(p)) 172 : , size_(n) 173 18 : , down_(downwards) 174 : { 175 18 : } 176 : 177 : /** The maximum amount that can be successfully returned from reserve 178 : */ 179 : std::size_t 180 38 : max_size() const noexcept 181 : { 182 38 : return size_; 183 : } 184 : 185 : /** Return the total number of bytes allocated 186 : */ 187 : std::size_t 188 24 : size_used() const noexcept 189 : { 190 24 : return size_used_; 191 : } 192 : 193 : /** Return a pointer to at least n bytes of contiguous storage 194 : 195 : Allocated storage will be automatically 196 : deallocated when the @ref filter, 197 : @ref sink, or @ref source is destroyed. 198 : 199 : @throws std::invalid_argument `n > max_size()` 200 : 201 : @return A pointer to uninitialized storage. 202 : 203 : @param n The number of bytes. 204 : */ 205 : BOOST_HTTP_PROTO_DECL 206 : void* 207 : allocate(std::size_t n); 208 : 209 : private: 210 : void 211 7 : remove( 212 : std::size_t n) noexcept 213 : { 214 7 : if(down_) 215 2 : base_ += n; 216 7 : size_ -= n; 217 7 : } 218 : 219 : void 220 7 : restore( 221 : std::size_t n) noexcept 222 : { 223 7 : if(down_) 224 2 : base_ -= n; 225 7 : size_ += n; 226 7 : } 227 : 228 : friend struct buffered_base; 229 : 230 : unsigned char* base_ = nullptr; 231 : std::size_t size_ = 0; 232 : std::size_t size_used_ = 0; 233 : bool down_ = false; 234 : }; 235 : 236 : } // http_proto 237 : } // boost 238 : 239 : #endif