| Line | Branch | Exec | Source | 
|---|---|---|---|
| 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 | 92 | 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 | 
        2/2✓ Branch 0 taken 2 times. 
          ✓ Branch 1 taken 5 times. 
         | 
      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 | 
        2/2✓ Branch 0 taken 2 times. 
          ✓ Branch 1 taken 5 times. 
         | 
      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 | ||
| 243 |