LCOV - code coverage report
Current view: top level - http_proto/detail - workspace.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 37 37 100.0 %
Date: 2023-02-10 23:49:12 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_WORKSPACE_HPP
      11             : #define BOOST_HTTP_PROTO_DETAIL_WORKSPACE_HPP
      12             : 
      13             : #include <boost/http_proto/detail/except.hpp>
      14             : #include <boost/assert.hpp>
      15             : #include <cstdlib>
      16             : #include <new>
      17             : #include <utility>
      18             : #include <stddef.h> // ::max_align_t
      19             : 
      20             : namespace boost {
      21             : namespace http_proto {
      22             : namespace detail {
      23             : 
      24             : /** A contiguous buffer of storage used by algorithms.
      25             : 
      26             :     Objects of this type retain ownership of a
      27             :     contiguous buffer of storage allocated upon
      28             :     construction. This storage is divided into
      29             :     three regions:
      30             : 
      31             :     @li The reserved area, which starts at the
      32             :         beginning of the buffer and can grow
      33             :         upwards towards the end of the buffer.
      34             : 
      35             :     @li The acquired area, which starts at the
      36             :         end of the buffer and can grow downwards
      37             :         towards the beginning of the buffer.
      38             : 
      39             :     @li The unused area, which starts from the
      40             :         end of the reserved area and stretches
      41             :         until the beginning of the acquired area.
      42             : */
      43             : class workspace
      44             : {
      45          37 :     struct any
      46             :     {
      47             :         any* next = nullptr;
      48             : 
      49             :         BOOST_HTTP_PROTO_DECL
      50             :         virtual ~any() = 0;
      51             :     };
      52             : 
      53             :     unsigned char* base_ = nullptr;
      54             :     unsigned char* begin_ = nullptr;
      55             :     unsigned char* head_ = nullptr;
      56             :     unsigned char* end_ = nullptr;
      57             : 
      58             : public:
      59             :     /** Destructor.
      60             :     */
      61             :     ~workspace();
      62             : 
      63             :     /** Constructor.
      64             : 
      65             :         @param n The number of bytes of storage
      66             :             to allocate for the internal buffer.
      67             :     */
      68             :     explicit
      69             :     workspace(
      70             :         std::size_t n);
      71             : 
      72             :     /** Constructor.
      73             :     */
      74         745 :     workspace() = default;
      75             : 
      76             :     /** Constructor.
      77             :     */
      78             :     workspace(workspace&&) noexcept;
      79             : 
      80             :     /** Allocate internal storage.
      81             : 
      82             :         @throws std::logic_error this->size() > 0
      83             : 
      84             :         @throws std::invalid_argument n == 0
      85             :     */
      86             :     void
      87             :     allocate(
      88             :         std::size_t n);
      89             : 
      90             :     /** Return a pointer to the unused area.
      91             :     */
      92             :     void*
      93        7958 :     data() noexcept
      94             :     {
      95        7958 :         return begin_;
      96             :     }
      97             : 
      98             :     /** Return the size of the unused area.
      99             :     */
     100             :     std::size_t
     101          20 :     size() const noexcept
     102             :     {
     103          20 :         return head_ - begin_;
     104             :     }
     105             : 
     106             :     /** Clear the contents while preserving capacity.
     107             :     */
     108             :     BOOST_HTTP_PROTO_DECL
     109             :     void
     110             :     clear() noexcept;
     111             : 
     112             :     /** Convert unused storage to reserved storage.
     113             : 
     114             :         @throws std::invalid_argument n >= this->size()
     115             :     */
     116             :     BOOST_HTTP_PROTO_DECL
     117             :     void
     118             :     reserve(std::size_t n);
     119             : 
     120             :     template<class T>
     121             :     auto
     122             :     push(T&& t) ->
     123             :         typename std::decay<T>::type&;
     124             : 
     125             :     template<class T>
     126             :     T*
     127             :     push_array(
     128             :         std::size_t n,
     129             :         T const& t);
     130             : 
     131             : private:
     132             :     BOOST_HTTP_PROTO_DECL
     133             :     void*
     134             :     bump_down(
     135             :         std::size_t size,
     136             :         std::size_t align);
     137             : };
     138             : 
     139             : template<class T>
     140             : auto
     141          13 : workspace::
     142             : push(T&& t) ->
     143             :     typename std::decay<T>::type&
     144             : {
     145             :     struct alignas(alignof(::max_align_t))
     146             :         U : any
     147             :     {
     148             :         typename std::decay<T>::type v_;
     149             : 
     150             :         U() = delete;
     151             :         U(U&&) = default;
     152             : 
     153          13 :         explicit U(T&& t)
     154          13 :             : v_(std::move(t))
     155             :         {
     156          13 :         }
     157             :     };
     158             : 
     159          13 :     auto p = ::new(bump_down(
     160             :         sizeof(U), alignof(U))) U(
     161          13 :             std::forward<T>(t));
     162          13 :     p->next = reinterpret_cast<
     163          13 :         any*>(head_);
     164          13 :     head_ = reinterpret_cast<
     165             :         unsigned char*>(p);
     166          13 :     return p->v_;
     167             : }
     168             : 
     169             : template<class T>
     170             : T*
     171          24 : workspace::
     172             : push_array(
     173             :     std::size_t n,
     174             :     T const& t)
     175             : {
     176             :     struct alignas(alignof(::max_align_t))
     177          24 :         U : any
     178             :     {
     179             :         std::size_t n_ = 0;
     180             : 
     181             :         U() = default;
     182          24 :         ~U()
     183             :         {
     184          70 :             for(std::size_t i = n_;
     185          70 :                     i-- > 0;)
     186          46 :                 data()[i].~T();
     187          48 :         }
     188             : 
     189          24 :         U(  std::size_t n,
     190             :             T const& t)
     191          24 :             : U()
     192             :         {
     193          70 :             while(n_ < n)
     194             :             {
     195          46 :                 new(&data()[n_]) T(t);
     196          46 :                 ++n_;
     197             :             }
     198          24 :         }
     199             : 
     200         116 :         T* data() noexcept
     201             :         {
     202             :             return reinterpret_cast<
     203         116 :                 T*>(this + 1);
     204             :         }
     205             :     };
     206             : 
     207          24 :     auto p = ::new(bump_down(
     208          24 :         sizeof(U) + n * sizeof(T),
     209             :             alignof(::max_align_t))) U(n, t);
     210          24 :     p->next = reinterpret_cast<
     211          24 :         any*>(head_);
     212          24 :     head_ = reinterpret_cast<
     213             :         unsigned char*>(p);
     214          24 :     return p->data();
     215             : }
     216             : 
     217             : } // detail
     218             : } // http_proto
     219             : } // boost
     220             : 
     221             : #endif

Generated by: LCOV version 1.15