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

Generated by: LCOV version 2.3