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