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