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: 73.5 % 83 61
Test Date: 2024-07-08 21:32:34 Functions: 80.0 % 10 8

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

Generated by: LCOV version 2.1