LCOV - code coverage report
Current view: top level - http_proto/detail/impl - workspace.ipp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 42 62 67.7 %
Date: 2023-02-02 18:17:21 Functions: 5 7 71.4 %

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

Generated by: LCOV version 1.15