LCOV - code coverage report
Current view: top level - http_proto/detail/impl - workspace.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 47 48 97.9 %
Date: 2023-02-11 03:18:39 Functions: 23 25 92.0 %

          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_HPP
      11             : #define BOOST_HTTP_PROTO_DETAIL_IMPL_WORKSPACE_HPP
      12             : 
      13             : namespace boost {
      14             : namespace http_proto {
      15             : namespace detail {
      16             : 
      17          37 : struct workspace::any
      18             : {
      19             :     any* next = nullptr;
      20             : 
      21             :     BOOST_HTTP_PROTO_DECL
      22             :     virtual ~any() = 0;
      23             : };
      24             : 
      25             : template<class U>
      26             : struct alignas(alignof(::max_align_t))
      27             :     workspace::any_impl : any
      28             : {
      29             :     U u;
      30             : 
      31             :     any_impl() = delete;
      32             :     any_impl(any_impl&&) = default;
      33             : 
      34             :     template<class U_>
      35          13 :     explicit any_impl(U_&& u_)
      36          13 :         : u(std::move(u_))
      37             :     {
      38          13 :     }
      39             : };
      40             : 
      41             : struct workspace::undo
      42             : {
      43             :     explicit
      44          37 :     undo(workspace& ws0) noexcept
      45          37 :         : ws_(ws0)
      46          37 :         , head_(ws0.head_)
      47             :     {
      48          37 :     }
      49             : 
      50          37 :     ~undo()
      51          37 :     {
      52          37 :         if(head_)
      53           0 :             ws_.head_ = head_;
      54          37 :     }
      55             : 
      56             :     void
      57          37 :     commit() noexcept
      58             :     {
      59          37 :         head_ = nullptr;
      60          37 :     }
      61             : 
      62             : private:
      63             :     workspace& ws_;
      64             :     unsigned char* head_;
      65             : };
      66             : 
      67             : template<class T>
      68             : constexpr
      69             : std::size_t
      70             : workspace::
      71             : space_needed()
      72             : {
      73             :     using U = typename std::decay<T>::type;
      74             : 
      75             :     static_assert(
      76             :         alignof(U) <= alignof(::max_align_t),
      77             :         "Overaligned types not supported");
      78             : 
      79             :     return sizeof(any_impl<U>);
      80             : }
      81             : 
      82             : template<class T>
      83             : auto
      84          13 : workspace::
      85             : push(T&& t) ->
      86             :     typename std::decay<T>::type&
      87             : {
      88             :     static_assert(
      89             :         alignof(T) <= alignof(::max_align_t),
      90             :         "Overaligned types not supported");
      91             : 
      92             :     using U = any_impl<typename
      93             :         std::decay<T>::type>;
      94             : 
      95          13 :     undo u(*this);
      96          13 :     auto p = ::new(bump_down(
      97             :         sizeof(U), alignof(U))) U(
      98          13 :             std::forward<T>(t));
      99          13 :     u.commit();
     100          13 :     p->next = reinterpret_cast<
     101          13 :         any*>(head_);
     102          13 :     head_ = reinterpret_cast<
     103             :         unsigned char*>(p);
     104          26 :     return p->u;
     105             : }
     106             : 
     107             : template<class T>
     108             : T*
     109          24 : workspace::
     110             : push_array(
     111             :     std::size_t n,
     112             :     T const& t)
     113             : {
     114             :     struct alignas(alignof(::max_align_t))
     115          24 :         U : any
     116             :     {
     117             :         std::size_t n_ = 0;
     118             : 
     119             :         U() = default;
     120          24 :         ~U()
     121             :         {
     122          70 :             for(std::size_t i = n_;
     123          70 :                     i-- > 0;)
     124          46 :                 data()[i].~T();
     125          48 :         }
     126             : 
     127          24 :         U(  std::size_t n,
     128             :             T const& t)
     129          24 :             : U()
     130             :         {
     131          70 :             while(n_ < n)
     132             :             {
     133          46 :                 new(&data()[n_]) T(t);
     134          46 :                 ++n_;
     135             :             }
     136          24 :         }
     137             : 
     138         116 :         T* data() noexcept
     139             :         {
     140             :             return reinterpret_cast<
     141         116 :                 T*>(this + 1);
     142             :         }
     143             :     };
     144             : 
     145          48 :     undo u(*this);
     146          24 :     auto p = ::new(bump_down(
     147          24 :         sizeof(U) + n * sizeof(T),
     148             :             alignof(::max_align_t))) U(n, t);
     149          24 :     u.commit();
     150          24 :     p->next = reinterpret_cast<
     151          24 :         any*>(head_);
     152          24 :     head_ = reinterpret_cast<
     153             :         unsigned char*>(p);
     154          48 :     return p->data();
     155             : }
     156             : 
     157             : } // detail
     158             : } // http_proto
     159             : } // boost
     160             : 
     161             : #endif

Generated by: LCOV version 1.15