LCOV - code coverage report
Current view: top level - libs/http/src/detail - workspace.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 55.1 % 89 49
Test Date: 2026-02-02 17:02:49 Functions: 58.3 % 12 7

            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          101 : workspace::
      22              : any::
      23              : ~any() = default;
      24              : 
      25         1776 : workspace::
      26              : ~workspace()
      27              : {
      28         1776 :     clear();
      29         1776 :     delete[] begin_;
      30         1776 : }
      31              : 
      32         1776 : workspace::
      33              : workspace(
      34         1776 :     std::size_t n)
      35         1776 :     : begin_(new unsigned char[n])
      36         1776 :     , front_(begin_)
      37         1776 :     , head_(begin_ + n)
      38         1776 :     , back_(head_)
      39         1776 :     , end_(head_)
      40              : {
      41         1776 : }
      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        22212 : workspace::
      94              : clear() noexcept
      95              : {
      96        22212 :     if(! begin_)
      97            0 :         return;
      98              : 
      99        22212 :     auto const end =
     100              :         reinterpret_cast<
     101              :             any const*>(back_);
     102        22212 :     auto p =
     103              :         reinterpret_cast<
     104              :             any const*>(head_);
     105        22313 :     while(p != end)
     106              :     {
     107          101 :         auto next = p->next;
     108          101 :         p->~any();
     109          101 :         p = next;
     110              :     }
     111        22212 :     front_ = begin_;
     112        22212 :     head_ = end_;
     113        22212 :     back_ = end_;
     114              : }
     115              : 
     116              : unsigned char*
     117        18921 : 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        18921 :     if(n >= size())
     124            0 :         detail::throw_length_error();
     125              : 
     126        18921 :     auto const p = front_;
     127        18921 :     front_ += n ;
     128        18921 :     return p;
     129              : }
     130              : 
     131              : unsigned char*
     132            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         9451 : 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         9451 :     if(back_ != end_)
     157            0 :         detail::throw_logic_error();
     158              : 
     159              :     // over capacity
     160         9451 :     std::size_t const lim =
     161         9451 :         head_ - front_;
     162         9451 :     if(n >= lim)
     163            0 :         detail::throw_length_error();
     164              : 
     165         9451 :     head_ -= n;
     166         9451 :     back_ = head_;
     167         9451 :     return back_;
     168              : }
     169              : 
     170              : // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html
     171              : unsigned char*
     172          101 : workspace::
     173              : bump_down(
     174              :     std::size_t size,
     175              :     std::size_t align)
     176              : {
     177          101 :     BOOST_ASSERT(align > 0);
     178          101 :     BOOST_ASSERT(
     179              :         (align & (align - 1)) == 0);
     180              : 
     181          101 :     auto ip0 = reinterpret_cast<
     182          101 :         std::uintptr_t>(front_);
     183          101 :     auto ip = reinterpret_cast<
     184          101 :         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          101 :     if(size > ip - ip0)
     191            0 :         detail::throw_length_error();
     192              : 
     193          101 :     ip -= size;
     194          101 :     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          101 :     if(ip < ip0)
     201            0 :         detail::throw_length_error();
     202              : 
     203              :     return reinterpret_cast<
     204          101 :         unsigned char*>(ip);
     205              : }
     206              : 
     207              : } // detail
     208              : } // http
     209              : } // boost
        

Generated by: LCOV version 2.3