LCOV - code coverage report
Current view: top level - libs/http_proto/src/detail - workspace.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 61 83 73.5 %
Date: 2024-03-22 16:56:24 Functions: 7 8 87.5 %

          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             : workspace::
      19             : any::
      20             : ~any() = default;
      21             : 
      22        1058 : workspace::
      23        1058 : ~workspace()
      24             : {
      25        1058 :     if(begin_)
      26             :     {
      27        1058 :         clear();
      28        1058 :         delete[] begin_;
      29             :     }
      30        1058 : }
      31             : 
      32          14 : workspace::
      33             : workspace(
      34          14 :     std::size_t n)
      35          14 :     : begin_(new unsigned char[n])
      36          14 :     , front_(begin_)
      37          14 :     , head_(begin_ + n)
      38          14 :     , back_(head_)
      39          14 :     , end_(head_)
      40             : {
      41          14 : }
      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        4324 : workspace::
      81             : clear() noexcept
      82             : {
      83        4324 :     if(! begin_)
      84           0 :         return;
      85             : 
      86        4324 :     auto const end =
      87             :         reinterpret_cast<
      88             :             any const*>(back_);
      89        4324 :     auto p =
      90             :         reinterpret_cast<
      91             :             any const*>(head_);
      92        4664 :     while(p != end)
      93             :     {
      94         340 :         auto next = p->next;
      95         340 :         p->~any();
      96         340 :         p = next;
      97             :     }
      98        4324 :     front_ = begin_;
      99        4324 :     head_ = end_;
     100        4324 :     back_ = end_;
     101             : }
     102             : 
     103             : unsigned char*
     104        1329 : 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        1329 :     if(n >= size())
     112           0 :         detail::throw_length_error();
     113             : 
     114        1329 :     auto const p = front_;
     115        1329 :     front_ += n ;
     116        1329 :     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         340 : workspace::
     146             : bump_down(
     147             :     std::size_t size,
     148             :     std::size_t align)
     149             : {
     150         340 :     BOOST_ASSERT(align > 0);
     151         340 :     BOOST_ASSERT(
     152             :         (align & (align - 1)) == 0);
     153         340 :     BOOST_ASSERT(front_);
     154             : 
     155         340 :     auto ip0 = reinterpret_cast<
     156         340 :         std::uintptr_t>(front_);
     157         340 :     auto ip = reinterpret_cast<
     158         340 :         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         340 :     if(size > ip - ip0)
     165           0 :         detail::throw_bad_alloc();
     166             : 
     167         340 :     ip -= size;
     168         340 :     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         340 :     if(ip < ip0)
     175           0 :         detail::throw_bad_alloc();
     176             : 
     177             :     return reinterpret_cast<
     178         340 :         unsigned char*>(ip);
     179             : }
     180             : 
     181             : } // detail
     182             : } // http_proto
     183             : } // boost

Generated by: LCOV version 1.15