55.06% Lines (49/89)
63.64% Functions (7/11)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // Copyright (c) 2025 Mohammad Nejati | 3 | // Copyright (c) 2025 Mohammad Nejati | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |||||
| 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/cppalliance/http | 8 | // Official repository: https://github.com/cppalliance/http | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #include <boost/http/detail/workspace.hpp> | 11 | #include <boost/http/detail/workspace.hpp> | |||||
| 12 | #include <boost/http/detail/except.hpp> | 12 | #include <boost/http/detail/except.hpp> | |||||
| 13 | #include <boost/assert.hpp> | 13 | #include <boost/assert.hpp> | |||||
| 14 | #include <boost/core/exchange.hpp> | 14 | #include <boost/core/exchange.hpp> | |||||
| 15 | #include <utility> | 15 | #include <utility> | |||||
| 16 | 16 | |||||||
| 17 | namespace boost { | 17 | namespace boost { | |||||
| 18 | namespace http { | 18 | namespace http { | |||||
| 19 | namespace detail { | 19 | namespace detail { | |||||
| 20 | 20 | |||||||
| HITCBC | 21 | 159 | workspace:: | 21 | 159 | workspace:: | ||
| 22 | any:: | 22 | any:: | |||||
| 23 | ~any() = default; | 23 | ~any() = default; | |||||
| 24 | 24 | |||||||
| HITCBC | 25 | 2216 | workspace:: | 25 | 2225 | workspace:: | ||
| 26 | ~workspace() | 26 | ~workspace() | |||||
| 27 | { | 27 | { | |||||
| HITCBC | 28 | 2216 | clear(); | 28 | 2225 | clear(); | ||
| HITCBC | 29 | 2216 | delete[] begin_; | 29 | 2225 | delete[] begin_; | ||
| HITCBC | 30 | 2216 | } | 30 | 2225 | } | ||
| 31 | 31 | |||||||
| HITCBC | 32 | 2216 | workspace:: | 32 | 2225 | workspace:: | ||
| 33 | workspace( | 33 | workspace( | |||||
| HITCBC | 34 | 2216 | std::size_t n) | 34 | 2225 | std::size_t n) | ||
| HITCBC | 35 | 2216 | : begin_(new unsigned char[n]) | 35 | 2225 | : begin_(new unsigned char[n]) | ||
| HITCBC | 36 | 2216 | , front_(begin_) | 36 | 2225 | , front_(begin_) | ||
| HITCBC | 37 | 2216 | , head_(begin_ + n) | 37 | 2225 | , head_(begin_ + n) | ||
| HITCBC | 38 | 2216 | , back_(head_) | 38 | 2225 | , back_(head_) | ||
| HITCBC | 39 | 2216 | , end_(head_) | 39 | 2225 | , end_(head_) | ||
| 40 | { | 40 | { | |||||
| HITCBC | 41 | 2216 | } | 41 | 2225 | } | ||
| 42 | 42 | |||||||
| MISUBC | 43 | ✗ | workspace:: | 43 | ✗ | workspace:: | ||
| 44 | workspace( | 44 | workspace( | |||||
| MISUBC | 45 | ✗ | workspace&& other) noexcept | 45 | ✗ | workspace&& other) noexcept | ||
| MISUBC | 46 | ✗ | : begin_(boost::exchange(other.begin_, nullptr)) | 46 | ✗ | : begin_(boost::exchange(other.begin_, nullptr)) | ||
| MISUBC | 47 | ✗ | , front_(boost::exchange(other.front_, nullptr)) | 47 | ✗ | , front_(boost::exchange(other.front_, nullptr)) | ||
| MISUBC | 48 | ✗ | , head_(boost::exchange(other.head_, nullptr)) | 48 | ✗ | , head_(boost::exchange(other.head_, nullptr)) | ||
| MISUBC | 49 | ✗ | , back_(boost::exchange(other.back_, nullptr)) | 49 | ✗ | , back_(boost::exchange(other.back_, nullptr)) | ||
| MISUBC | 50 | ✗ | , end_(boost::exchange(other.end_, nullptr)) | 50 | ✗ | , end_(boost::exchange(other.end_, nullptr)) | ||
| 51 | { | 51 | { | |||||
| MISUBC | 52 | ✗ | } | 52 | ✗ | } | ||
| 53 | 53 | |||||||
| 54 | workspace& | 54 | workspace& | |||||
| MISUBC | 55 | ✗ | workspace:: | 55 | ✗ | workspace:: | ||
| 56 | operator=( | 56 | operator=( | |||||
| 57 | workspace&& other) noexcept | 57 | workspace&& other) noexcept | |||||
| 58 | { | 58 | { | |||||
| MISUBC | 59 | ✗ | if(this != &other) | 59 | ✗ | if(this != &other) | ||
| 60 | { | 60 | { | |||||
| MISUBC | 61 | ✗ | delete[] begin_; | 61 | ✗ | delete[] begin_; | ||
| 62 | 62 | |||||||
| MISUBC | 63 | ✗ | begin_ = boost::exchange(other.begin_, nullptr); | 63 | ✗ | begin_ = boost::exchange(other.begin_, nullptr); | ||
| MISUBC | 64 | ✗ | front_ = boost::exchange(other.front_, nullptr); | 64 | ✗ | front_ = boost::exchange(other.front_, nullptr); | ||
| MISUBC | 65 | ✗ | head_ = boost::exchange(other.head_, nullptr); | 65 | ✗ | head_ = boost::exchange(other.head_, nullptr); | ||
| MISUBC | 66 | ✗ | back_ = boost::exchange(other.back_, nullptr); | 66 | ✗ | back_ = boost::exchange(other.back_, nullptr); | ||
| MISUBC | 67 | ✗ | end_ = boost::exchange(other.end_, nullptr); | 67 | ✗ | end_ = boost::exchange(other.end_, nullptr); | ||
| 68 | } | 68 | } | |||||
| MISUBC | 69 | ✗ | return *this; | 69 | ✗ | return *this; | ||
| 70 | } | 70 | } | |||||
| 71 | 71 | |||||||
| 72 | void | 72 | void | |||||
| MISUBC | 73 | ✗ | workspace:: | 73 | ✗ | workspace:: | ||
| 74 | allocate( | 74 | allocate( | |||||
| 75 | std::size_t n) | 75 | std::size_t n) | |||||
| 76 | { | 76 | { | |||||
| 77 | // Cannot be empty | 77 | // Cannot be empty | |||||
| MISUBC | 78 | ✗ | if(n == 0) | 78 | ✗ | if(n == 0) | ||
| MISUBC | 79 | ✗ | detail::throw_invalid_argument(); | 79 | ✗ | detail::throw_invalid_argument(); | ||
| 80 | 80 | |||||||
| 81 | // Already allocated | 81 | // Already allocated | |||||
| MISUBC | 82 | ✗ | if(begin_ != nullptr) | 82 | ✗ | if(begin_ != nullptr) | ||
| MISUBC | 83 | ✗ | detail::throw_logic_error(); | 83 | ✗ | detail::throw_logic_error(); | ||
| 84 | 84 | |||||||
| MISUBC | 85 | ✗ | begin_ = new unsigned char[n]; | 85 | ✗ | begin_ = new unsigned char[n]; | ||
| MISUBC | 86 | ✗ | front_ = begin_; | 86 | ✗ | front_ = begin_; | ||
| MISUBC | 87 | ✗ | head_ = begin_ + n; | 87 | ✗ | head_ = begin_ + n; | ||
| MISUBC | 88 | ✗ | back_ = head_; | 88 | ✗ | back_ = head_; | ||
| MISUBC | 89 | ✗ | end_ = head_; | 89 | ✗ | end_ = head_; | ||
| MISUBC | 90 | ✗ | } | 90 | ✗ | } | ||
| 91 | 91 | |||||||
| 92 | void | 92 | void | |||||
| HITCBC | 93 | 23403 | workspace:: | 93 | 23430 | workspace:: | ||
| 94 | clear() noexcept | 94 | clear() noexcept | |||||
| 95 | { | 95 | { | |||||
| HITCBC | 96 | 23403 | if(! begin_) | 96 | 23430 | if(! begin_) | ||
| MISUBC | 97 | ✗ | return; | 97 | ✗ | return; | ||
| 98 | 98 | |||||||
| HITCBC | 99 | 23403 | auto const end = | 99 | 23430 | auto const end = | ||
| 100 | reinterpret_cast< | 100 | reinterpret_cast< | |||||
| 101 | any const*>(back_); | 101 | any const*>(back_); | |||||
| HITCBC | 102 | 23403 | auto p = | 102 | 23430 | auto p = | ||
| 103 | reinterpret_cast< | 103 | reinterpret_cast< | |||||
| 104 | any const*>(head_); | 104 | any const*>(head_); | |||||
| HITCBC | 105 | 23562 | while(p != end) | 105 | 23589 | while(p != end) | ||
| 106 | { | 106 | { | |||||
| HITCBC | 107 | 159 | auto next = p->next; | 107 | 159 | auto next = p->next; | ||
| HITCBC | 108 | 159 | p->~any(); | 108 | 159 | p->~any(); | ||
| HITCBC | 109 | 159 | p = next; | 109 | 159 | p = next; | ||
| 110 | } | 110 | } | |||||
| HITCBC | 111 | 23403 | front_ = begin_; | 111 | 23430 | front_ = begin_; | ||
| HITCBC | 112 | 23403 | head_ = end_; | 112 | 23430 | head_ = end_; | ||
| HITCBC | 113 | 23403 | back_ = end_; | 113 | 23430 | back_ = end_; | ||
| 114 | } | 114 | } | |||||
| 115 | 115 | |||||||
| 116 | unsigned char* | 116 | unsigned char* | |||||
| HITCBC | 117 | 19192 | workspace:: | 117 | 19210 | workspace:: | ||
| 118 | reserve_front( | 118 | reserve_front( | |||||
| 119 | std::size_t n) | 119 | std::size_t n) | |||||
| 120 | { | 120 | { | |||||
| 121 | // Requested size exceeds available space. | 121 | // Requested size exceeds available space. | |||||
| 122 | // Note you can never reserve the last byte. | 122 | // Note you can never reserve the last byte. | |||||
| HITCBC | 123 | 19192 | if(n >= size()) | 123 | 19210 | if(n >= size()) | ||
| MISUBC | 124 | ✗ | detail::throw_length_error(); | 124 | ✗ | detail::throw_length_error(); | ||
| 125 | 125 | |||||||
| HITCBC | 126 | 19192 | auto const p = front_; | 126 | 19210 | auto const p = front_; | ||
| HITCBC | 127 | 19192 | front_ += n ; | 127 | 19210 | front_ += n ; | ||
| HITCBC | 128 | 19192 | return p; | 128 | 19210 | return p; | ||
| 129 | } | 129 | } | |||||
| 130 | 130 | |||||||
| 131 | unsigned char* | 131 | unsigned char* | |||||
| MISUBC | 132 | ✗ | workspace:: | 132 | ✗ | workspace:: | ||
| 133 | try_reserve_front( | 133 | try_reserve_front( | |||||
| 134 | std::size_t n) noexcept | 134 | std::size_t n) noexcept | |||||
| 135 | { | 135 | { | |||||
| 136 | // Requested size exceeds available space. | 136 | // Requested size exceeds available space. | |||||
| 137 | // Note you can never reserve the last byte. | 137 | // Note you can never reserve the last byte. | |||||
| MISUBC | 138 | ✗ | if(n >= size()) | 138 | ✗ | if(n >= size()) | ||
| MISUBC | 139 | ✗ | return nullptr; | 139 | ✗ | return nullptr; | ||
| 140 | 140 | |||||||
| MISUBC | 141 | ✗ | auto const p = front_; | 141 | ✗ | auto const p = front_; | ||
| MISUBC | 142 | ✗ | front_ += n ; | 142 | ✗ | front_ += n ; | ||
| MISUBC | 143 | ✗ | return p; | 143 | ✗ | return p; | ||
| 144 | } | 144 | } | |||||
| 145 | 145 | |||||||
| 146 | unsigned char* | 146 | unsigned char* | |||||
| HITCBC | 147 | 9548 | workspace:: | 147 | 9557 | workspace:: | ||
| 148 | reserve_back( | 148 | reserve_back( | |||||
| 149 | std::size_t n) | 149 | std::size_t n) | |||||
| 150 | { | 150 | { | |||||
| 151 | // // can't reserve after acquire | 151 | // // can't reserve after acquire | |||||
| 152 | // if(head_ != end_) | 152 | // if(head_ != end_) | |||||
| 153 | // detail::throw_logic_error(); | 153 | // detail::throw_logic_error(); | |||||
| 154 | 154 | |||||||
| 155 | // can't reserve twice | 155 | // can't reserve twice | |||||
| HITCBC | 156 | 9548 | if(back_ != end_) | 156 | 9557 | if(back_ != end_) | ||
| MISUBC | 157 | ✗ | detail::throw_logic_error(); | 157 | ✗ | detail::throw_logic_error(); | ||
| 158 | 158 | |||||||
| 159 | // over capacity | 159 | // over capacity | |||||
| HITCBC | 160 | 9548 | std::size_t const lim = | 160 | 9557 | std::size_t const lim = | ||
| HITCBC | 161 | 9548 | head_ - front_; | 161 | 9557 | head_ - front_; | ||
| HITCBC | 162 | 9548 | if(n >= lim) | 162 | 9557 | if(n >= lim) | ||
| MISUBC | 163 | ✗ | detail::throw_length_error(); | 163 | ✗ | detail::throw_length_error(); | ||
| 164 | 164 | |||||||
| HITCBC | 165 | 9548 | head_ -= n; | 165 | 9557 | head_ -= n; | ||
| HITCBC | 166 | 9548 | back_ = head_; | 166 | 9557 | back_ = head_; | ||
| HITCBC | 167 | 9548 | return back_; | 167 | 9557 | return back_; | ||
| 168 | } | 168 | } | |||||
| 169 | 169 | |||||||
| 170 | // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html | 170 | // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html | |||||
| 171 | unsigned char* | 171 | unsigned char* | |||||
| HITCBC | 172 | 159 | workspace:: | 172 | 159 | workspace:: | ||
| 173 | bump_down( | 173 | bump_down( | |||||
| 174 | std::size_t size, | 174 | std::size_t size, | |||||
| 175 | std::size_t align) | 175 | std::size_t align) | |||||
| 176 | { | 176 | { | |||||
| HITCBC | 177 | 159 | BOOST_ASSERT(align > 0); | 177 | 159 | BOOST_ASSERT(align > 0); | ||
| HITCBC | 178 | 159 | BOOST_ASSERT( | 178 | 159 | BOOST_ASSERT( | ||
| 179 | (align & (align - 1)) == 0); | 179 | (align & (align - 1)) == 0); | |||||
| 180 | 180 | |||||||
| HITCBC | 181 | 159 | auto ip0 = reinterpret_cast< | 181 | 159 | auto ip0 = reinterpret_cast< | ||
| HITCBC | 182 | 159 | std::uintptr_t>(front_); | 182 | 159 | std::uintptr_t>(front_); | ||
| HITCBC | 183 | 159 | auto ip = reinterpret_cast< | 183 | 159 | auto ip = reinterpret_cast< | ||
| HITCBC | 184 | 159 | std::uintptr_t>(head_); | 184 | 159 | std::uintptr_t>(head_); | ||
| 185 | 185 | |||||||
| 186 | // If you get an exception here, it | 186 | // If you get an exception here, it | |||||
| 187 | // means that a buffer was too small | 187 | // means that a buffer was too small | |||||
| 188 | // for your workload. Increase the | 188 | // for your workload. Increase the | |||||
| 189 | // buffer size. | 189 | // buffer size. | |||||
| HITCBC | 190 | 159 | if(size > ip - ip0) | 190 | 159 | if(size > ip - ip0) | ||
| MISUBC | 191 | ✗ | detail::throw_length_error(); | 191 | ✗ | detail::throw_length_error(); | ||
| 192 | 192 | |||||||
| HITCBC | 193 | 159 | ip -= size; | 193 | 159 | ip -= size; | ||
| HITCBC | 194 | 159 | ip &= ~(align - 1); | 194 | 159 | ip &= ~(align - 1); | ||
| 195 | 195 | |||||||
| 196 | // If you get an exception here, it | 196 | // If you get an exception here, it | |||||
| 197 | // means that a buffer was too small | 197 | // means that a buffer was too small | |||||
| 198 | // for your workload. Increase the | 198 | // for your workload. Increase the | |||||
| 199 | // buffer size. | 199 | // buffer size. | |||||
| HITCBC | 200 | 159 | if(ip < ip0) | 200 | 159 | if(ip < ip0) | ||
| MISUBC | 201 | ✗ | detail::throw_length_error(); | 201 | ✗ | detail::throw_length_error(); | ||
| 202 | 202 | |||||||
| 203 | return reinterpret_cast< | 203 | return reinterpret_cast< | |||||
| HITCBC | 204 | 159 | unsigned char*>(ip); | 204 | 159 | unsigned char*>(ip); | ||
| 205 | } | 205 | } | |||||
| 206 | 206 | |||||||
| 207 | } // detail | 207 | } // detail | |||||
| 208 | } // http | 208 | } // http | |||||
| 209 | } // boost | 209 | } // boost | |||||