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