LCOV - code coverage report
Current view: top level - http_proto/detail/impl - workspace.ipp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 49 65 75.4 %
Date: 2023-02-10 23:49:12 Functions: 6 7 85.7 %

          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             : #ifndef BOOST_HTTP_PROTO_DETAIL_IMPL_WORKSPACE_IPP
      11             : #define BOOST_HTTP_PROTO_DETAIL_IMPL_WORKSPACE_IPP
      12             : 
      13             : #include <boost/http_proto/detail/workspace.hpp>
      14             : #include <boost/http_proto/detail/except.hpp>
      15             : #include <boost/assert.hpp>
      16             : 
      17             : namespace boost {
      18             : namespace http_proto {
      19             : namespace detail {
      20             : 
      21             : /*  Layout
      22             : 
      23             :     The buffer is laid out thusly:
      24             : 
      25             :   base_         begin_        head_           end_
      26             : 
      27             :     |<- reserved ->|<- unused ->|<- acquired ->|
      28             : */
      29             : workspace::
      30             : any::
      31             : ~any() = default;
      32             : 
      33         756 : workspace::
      34         756 : ~workspace()
      35             : {
      36         756 :     if(base_)
      37             :     {
      38         756 :         clear();
      39         756 :         delete[] base_;
      40             :     }
      41         756 : }
      42             : 
      43          11 : workspace::
      44             : workspace(
      45          11 :     std::size_t n)
      46          11 :     : base_(new unsigned char[n])
      47          11 :     , begin_(base_)
      48          11 :     , head_(base_ + n)
      49          11 :     , end_(head_)
      50             : {
      51          11 : }
      52             : 
      53           0 : workspace::
      54             : workspace(
      55           0 :     workspace&& other) noexcept
      56           0 :     : base_(other.base_)
      57           0 :     , begin_(other.begin_)
      58           0 :     , head_(other.end_)
      59           0 :     , end_(other.end_)
      60             : {
      61           0 :     other.base_ = nullptr;
      62           0 :     other.begin_ = nullptr;
      63           0 :     other.head_ = nullptr;
      64           0 :     other.end_ = nullptr;
      65           0 : }
      66             : 
      67             : void
      68         745 : workspace::
      69             : allocate(
      70             :     std::size_t n)
      71             : {
      72             :     // n == 0
      73         745 :     if(n == 0)
      74           0 :         detail::throw_invalid_argument();
      75             : 
      76             :     // this->size() > 0
      77         745 :     if(base_ != nullptr)
      78           0 :         detail::throw_logic_error();
      79             : 
      80         745 :     base_ = new unsigned char[n];
      81         745 :     begin_ = base_;
      82         745 :     head_ = base_ + n;
      83         745 :     end_ = head_;
      84         745 : }
      85             : 
      86             : void
      87        1543 : workspace::
      88             : clear() noexcept
      89             : {
      90        1543 :     BOOST_ASSERT(begin_);
      91             : 
      92        1543 :     auto const end =
      93             :         reinterpret_cast<
      94             :             any const*>(end_);
      95        1543 :     auto p =
      96             :         reinterpret_cast<
      97             :             any const*>(head_);
      98        1580 :     while(p != end)
      99             :     {
     100          37 :         auto next = p->next;
     101          37 :         p->~any();
     102          37 :         p = next;
     103             :     }
     104        1543 :     head_ = end_;
     105        1543 :     begin_ = base_;
     106        1543 : }
     107             : 
     108             : void
     109           6 : workspace::
     110             : reserve(std::size_t n)
     111             : {
     112             :     // Requested size exceeds available space.
     113             :     // Note you can never reserve the last byte.
     114           6 :     if(n >= size())
     115           0 :         detail::throw_length_error();
     116             : 
     117           6 :     base_ += n ;
     118           6 : }
     119             : 
     120             : // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html
     121             : void*
     122          37 : workspace::
     123             : bump_down(
     124             :     std::size_t size,
     125             :     std::size_t align)
     126             : {
     127          37 :     BOOST_ASSERT(align > 0);
     128          37 :     BOOST_ASSERT(
     129             :         (align & (align - 1)) == 0);
     130          37 :     BOOST_ASSERT(begin_);
     131             : 
     132          37 :     auto ip0 = reinterpret_cast<
     133          37 :         std::uintptr_t>(begin_);
     134          37 :     auto ip = reinterpret_cast<
     135          37 :         std::uintptr_t>(head_);
     136             : 
     137             :     // If you get an exception here, it
     138             :     // means that a buffer was too small
     139             :     // for your workload. Increase the
     140             :     // buffer size.
     141          37 :     if(size > ip - ip0)
     142           0 :         detail::throw_bad_alloc();
     143             : 
     144          37 :     ip -= size;
     145          37 :     ip &= ~(align - 1);
     146             : 
     147             :     // If you get an exception here, it
     148             :     // means that a buffer was too small
     149             :     // for your workload. Increase the
     150             :     // buffer size.
     151          37 :     if(ip < ip0)
     152           0 :         detail::throw_bad_alloc();
     153             : 
     154          37 :     return reinterpret_cast<void*>(ip);
     155             : }
     156             : 
     157             : } // detail
     158             : } // http_proto
     159             : } // boost
     160             : 
     161             : #endif

Generated by: LCOV version 1.15