LCOV - code coverage report
Current view: top level - json/impl - monotonic_resource.ipp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 97.3 % 73 71 2
Test Date: 2026-08-21 06:47:08 Functions: 81.8 % 11 9 2

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/boostorg/json
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
      12                 : #define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
      13                 : 
      14                 : #include <boost/json/monotonic_resource.hpp>
      15                 : #include <boost/json/detail/except.hpp>
      16                 : #include <boost/core/max_align.hpp>
      17                 : #include <boost/throw_exception.hpp>
      18                 : 
      19                 : #include <memory>
      20                 : #include <new>
      21                 : 
      22                 : namespace boost {
      23                 : namespace json {
      24                 : 
      25                 : struct alignas(core::max_align_t)
      26                 :     monotonic_resource::block : block_base
      27                 : {
      28                 : };
      29                 : 
      30                 : constexpr
      31                 : std::size_t
      32 HIT         238 : monotonic_resource::
      33                 : max_size()
      34                 : {
      35             238 :     return std::size_t(-1) - sizeof(block);
      36                 : }
      37                 : 
      38                 : // lowest power of 2 greater than or equal to n
      39                 : std::size_t
      40              57 : monotonic_resource::
      41                 : round_pow2(
      42                 :     std::size_t n) noexcept
      43                 : {
      44              57 :     if(n & (n - 1))
      45              15 :         return next_pow2(n);
      46              42 :     return n;
      47                 : }
      48                 : 
      49                 : // lowest power of 2 greater than n
      50                 : std::size_t
      51              68 : monotonic_resource::
      52                 : next_pow2(
      53                 :     std::size_t n) noexcept
      54                 : {
      55              68 :     std::size_t result = min_size_;
      56             260 :     while(result <= n)
      57                 :     {
      58             193 :         if(result >= max_size() - result)
      59                 :         {
      60                 :             // overflow
      61               1 :             result = max_size();
      62               1 :             break;
      63                 :         }
      64             192 :         result *= 2;
      65                 :     }
      66              68 :     return result;
      67                 : }
      68                 : 
      69                 : //----------------------------------------------------------
      70                 : 
      71              57 : monotonic_resource::
      72              57 : ~monotonic_resource()
      73                 : {
      74              57 :     release();
      75              57 : }
      76                 : 
      77              47 : monotonic_resource::
      78                 : monotonic_resource(
      79                 :     std::size_t initial_size,
      80              47 :     storage_ptr upstream) noexcept
      81              47 :     : buffer_{
      82                 :         nullptr, 0, 0, nullptr}
      83              94 :     , next_size_(round_pow2(initial_size))
      84              47 :     , upstream_(std::move(upstream))
      85                 : {
      86              47 : }
      87                 : 
      88              10 : monotonic_resource::
      89                 : monotonic_resource(
      90                 :     unsigned char* buffer,
      91                 :     std::size_t size,
      92              10 :     storage_ptr upstream) noexcept
      93              10 :     : buffer_{
      94                 :         buffer, size, size, nullptr}
      95              20 :     , next_size_(next_pow2(size))
      96              10 :     , upstream_(std::move(upstream))
      97                 : {
      98              10 : }
      99                 : 
     100                 : void
     101              58 : monotonic_resource::
     102                 : release() noexcept
     103                 : {
     104              58 :     auto p = head_;
     105             101 :     while(p != &buffer_)
     106                 :     {
     107              43 :         auto next = p->next;
     108              43 :         upstream_->deallocate(p, sizeof(block) + p->size);
     109              43 :         p = next;
     110                 :     }
     111              58 :     buffer_.p = reinterpret_cast<
     112              58 :         unsigned char*>(buffer_.p) - (
     113              58 :             buffer_.size - buffer_.avail);
     114              58 :     buffer_.avail = buffer_.size;
     115              58 :     head_ = &buffer_;
     116              58 : }
     117                 : 
     118                 : void*
     119          129508 : monotonic_resource::
     120                 : do_allocate(
     121                 :     std::size_t n,
     122                 :     std::size_t align)
     123                 : {
     124          129508 :     auto p = std::align(align, n, head_->p, head_->avail);
     125          129508 :     if(p)
     126                 :     {
     127          129464 :         head_->p = reinterpret_cast<
     128          129464 :             unsigned char*>(p) + n;
     129          129464 :         head_->avail -= n;
     130          129464 :         return p;
     131                 :     }
     132                 : 
     133                 :     // a new block is only aligned to alignof(block), so an
     134                 :     // over-aligned request may need up to align - alignof(block)
     135                 :     // bytes of padding in addition to n
     136              44 :     std::size_t const pad = align > alignof(block)
     137              44 :         ? align - alignof(block) : 0;
     138              44 :     if(n > max_size() - pad)
     139               2 :         throw_exception( std::bad_alloc(), BOOST_CURRENT_LOCATION );
     140              43 :     if(next_size_ < n + pad)
     141              10 :         next_size_ = round_pow2(n + pad);
     142              43 :     auto b = ::new(upstream_->allocate(
     143              43 :         sizeof(block) + next_size_)) block;
     144              43 :     b->p = b + 1;
     145              43 :     b->avail = next_size_;
     146              43 :     b->size = next_size_;
     147              43 :     b->next = head_;
     148              43 :     head_ = b;
     149              43 :     next_size_ = next_pow2(next_size_);
     150                 : 
     151              43 :     p = std::align(align, n, head_->p, head_->avail);
     152              43 :     BOOST_ASSERT(p);
     153              43 :     head_->p = reinterpret_cast<
     154              43 :         unsigned char*>(p) + n;
     155              43 :     head_->avail -= n;
     156              43 :     return p;
     157                 : }
     158                 : 
     159                 : void
     160              29 : monotonic_resource::
     161                 : do_deallocate(
     162                 :     void*,
     163                 :     std::size_t,
     164                 :     std::size_t)
     165                 : {
     166                 :     // do nothing
     167              29 : }
     168                 : 
     169                 : bool
     170 MIS           0 : monotonic_resource::
     171                 : do_is_equal(
     172                 :     memory_resource const& mr) const noexcept
     173                 : {
     174               0 :     return this == &mr;
     175                 : }
     176                 : 
     177                 : } // namespace json
     178                 : } // namespace boost
     179                 : 
     180                 : #endif
        

Generated by: LCOV version 2.3