LCOV - code coverage report
Current view: top level - libs/http_proto/src/detail/workspace.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 60.7 % 89 54
Test Date: 2025-09-21 18:08:14 Functions: 66.7 % 12 8

            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_proto
       9              : //
      10              : 
      11              : #include <boost/http_proto/detail/workspace.hpp>
      12              : #include <boost/http_proto/detail/except.hpp>
      13              : #include <boost/assert.hpp>
      14              : #include <boost/core/exchange.hpp>
      15              : #include <utility>
      16              : 
      17              : namespace boost {
      18              : namespace http_proto {
      19              : namespace detail {
      20              : 
      21         1011 : workspace::
      22              : any::
      23              : ~any() = default;
      24              : 
      25         1078 : workspace::
      26              : ~workspace()
      27              : {
      28         1078 :     clear();
      29         1078 :     delete[] begin_;
      30         1078 : }
      31              : 
      32         1078 : workspace::
      33              : workspace(
      34         1078 :     std::size_t n)
      35         1078 :     : begin_(new unsigned char[n])
      36         1078 :     , front_(begin_)
      37         1078 :     , head_(begin_ + n)
      38         1078 :     , back_(head_)
      39         1078 :     , end_(head_)
      40              : {
      41         1078 : }
      42              : 
      43            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        21990 : workspace::
      94              : clear() noexcept
      95              : {
      96        21990 :     if(! begin_)
      97            0 :         return;
      98              : 
      99        21990 :     auto const end =
     100              :         reinterpret_cast<
     101              :             any const*>(back_);
     102        21990 :     auto p =
     103              :         reinterpret_cast<
     104              :             any const*>(head_);
     105        23001 :     while(p != end)
     106              :     {
     107         1011 :         auto next = p->next;
     108         1011 :         p->~any();
     109         1011 :         p = next;
     110              :     }
     111        21990 :     front_ = begin_;
     112        21990 :     head_ = end_;
     113        21990 :     back_ = end_;
     114              : }
     115              : 
     116              : unsigned char*
     117        28770 : 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        28770 :     if(n >= size())
     124            0 :         detail::throw_length_error();
     125              : 
     126        28770 :     auto const p = front_;
     127        28770 :     front_ += n ;
     128        28770 :     return p;
     129              : }
     130              : 
     131              : unsigned char*
     132          368 : 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          368 :     if(n >= size())
     139            0 :         return nullptr;
     140              : 
     141          368 :     auto const p = front_;
     142          368 :     front_ += n ;
     143          368 :     return p;
     144              : }
     145              : 
     146              : unsigned char*
     147        10006 : 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        10006 :     if(back_ != end_)
     157            0 :         detail::throw_logic_error();
     158              : 
     159              :     // over capacity
     160        10006 :     std::size_t const lim =
     161        10006 :         head_ - front_;
     162        10006 :     if(n >= lim)
     163            0 :         detail::throw_length_error();
     164              : 
     165        10006 :     head_ -= n;
     166        10006 :     back_ = head_;
     167        10006 :     return back_;
     168              : }
     169              : 
     170              : // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html
     171              : unsigned char*
     172         1011 : workspace::
     173              : bump_down(
     174              :     std::size_t size,
     175              :     std::size_t align)
     176              : {
     177         1011 :     BOOST_ASSERT(align > 0);
     178         1011 :     BOOST_ASSERT(
     179              :         (align & (align - 1)) == 0);
     180              : 
     181         1011 :     auto ip0 = reinterpret_cast<
     182         1011 :         std::uintptr_t>(front_);
     183         1011 :     auto ip = reinterpret_cast<
     184         1011 :         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         1011 :     if(size > ip - ip0)
     191            0 :         detail::throw_length_error();
     192              : 
     193         1011 :     ip -= size;
     194         1011 :     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         1011 :     if(ip < ip0)
     201            0 :         detail::throw_length_error();
     202              : 
     203              :     return reinterpret_cast<
     204         1011 :         unsigned char*>(ip);
     205              : }
     206              : 
     207              : } // detail
     208              : } // http_proto
     209              : } // boost
        

Generated by: LCOV version 2.1