LCOV - code coverage report
Current view: top level - src/detail - workspace.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 55.1 % 89 49 40
Test Date: 2026-06-13 19:44:58 Functions: 58.3 % 12 7 5

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

Generated by: LCOV version 2.3