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