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