LCOV - code coverage report
Current view: top level - json/detail/impl - stack.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 55 55
Test Date: 2026-02-25 20:43:10 Functions: 75.6 % 312 236 76

           TLA  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/boostorg/json
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_JSON_DETAIL_IMPL_STACK_HPP
      11                 : #define BOOST_JSON_DETAIL_IMPL_STACK_HPP
      12                 : 
      13                 : #include <boost/core/detail/static_assert.hpp>
      14                 : #include <memory>
      15                 : 
      16                 : namespace boost {
      17                 : namespace json {
      18                 : namespace detail {
      19                 : 
      20                 : template<>
      21                 : struct stack::non_trivial<void>
      22                 : {
      23                 :     using relocate_t = non_trivial* (*) (non_trivial*, void*);
      24                 : 
      25                 :     relocate_t rel;
      26                 :     non_trivial* next;
      27                 :     std::size_t offset;
      28                 : 
      29                 :     BOOST_JSON_DECL
      30                 :     non_trivial<>*
      31                 :     destroy() noexcept;
      32                 : 
      33                 :     BOOST_JSON_DECL
      34                 :     non_trivial*
      35                 :     relocate(void* dst) noexcept;
      36                 : 
      37                 : protected:
      38                 :     ~non_trivial() = default;
      39                 : };
      40                 : 
      41                 : template< class T >
      42                 : struct stack::non_trivial
      43                 :     : stack::non_trivial<void>
      44                 : {
      45                 :     T obj;
      46                 : 
      47                 :     explicit
      48 HIT           4 :     non_trivial(T t, non_trivial<>* next, std::size_t offset)
      49               4 :         : non_trivial<void>{relocate, next, offset}, obj( std::move(t) )
      50               4 :     {}
      51                 : 
      52                 :     static
      53                 :     non_trivial<>*
      54               4 :     relocate(non_trivial<>* src, void* dest) noexcept
      55                 :     {
      56               4 :         non_trivial* self = static_cast<non_trivial*>(src);
      57               4 :         non_trivial<>* result = nullptr;
      58               4 :         if( dest )
      59               3 :             result = ::new(dest) non_trivial( std::move(*self) );
      60               4 :         self->~non_trivial();
      61               4 :         return result;
      62                 :     }
      63                 : };
      64                 : 
      65                 : template<class T>
      66                 : void
      67          332068 : stack::
      68                 : push_unchecked(T const& t)
      69                 : {
      70          332068 :     constexpr std::size_t n = sizeof(T);
      71                 :     BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
      72          332068 :     BOOST_ASSERT( n <= cap_ - size_ );
      73          332068 :     std::memcpy( base_ + size_, &t, n );
      74          332068 :     size_ += n;
      75          332068 : }
      76                 : 
      77                 : template<class T>
      78                 : void
      79          795418 : stack::
      80                 : peek(T& t)
      81                 : {
      82          795418 :     constexpr std::size_t n = sizeof(T);
      83                 :     BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
      84          795418 :     BOOST_ASSERT( size_ >= n );
      85          795418 :     std::memcpy( &t, base_ + size_ - n, n );
      86          795418 : }
      87                 : 
      88                 : //--------------------------------------
      89                 : 
      90                 : // trivial
      91                 : template<class T>
      92                 : void
      93           47892 : stack::
      94                 : push(T const& t, std::true_type)
      95                 : {
      96           47892 :     if( sizeof(T) > cap_ - size_ )
      97            8953 :         reserve_impl( sizeof(T) + size_ );
      98           47890 :     push_unchecked(t);
      99           47890 : }
     100                 : 
     101                 : // non-trivial
     102                 : template<class T>
     103                 : void
     104               4 : stack::
     105                 : push(T&& t, std::false_type)
     106                 : {
     107                 :     BOOST_CORE_STATIC_ASSERT( ! is_trivially_copy_assignable<T>::value );
     108                 : 
     109                 :     using Holder = non_trivial< remove_cvref<T> >;
     110               4 :     constexpr std::size_t size = sizeof(Holder);
     111               4 :     constexpr std::size_t alignment = alignof(Holder);
     112                 : 
     113                 :     void* ptr;
     114                 :     std::size_t offset;
     115                 :     do
     116                 :     {
     117               7 :         std::size_t space = cap_ - size_;
     118               7 :         unsigned char* buf = base_ + size_;
     119               7 :         ptr = buf;
     120               7 :         if( std::align(alignment, size, ptr, space) )
     121                 :         {
     122               4 :             offset = (reinterpret_cast<unsigned char*>(ptr) - buf) + size;
     123               4 :             break;
     124                 :         }
     125                 : 
     126               3 :         reserve_impl(size_ + size + alignment - 1);
     127               3 :     }
     128                 :     while(true);
     129               4 :     BOOST_ASSERT(
     130                 :         (reinterpret_cast<unsigned char*>(ptr) + size - offset) ==
     131                 :         (base_ + size_) );
     132                 : 
     133               4 :     head_ = ::new(ptr) Holder( static_cast<T&&>(t), head_, offset );
     134               4 :     size_ += offset;
     135               4 : }
     136                 : 
     137                 : // trivial
     138                 : template<class T>
     139                 : void
     140          328587 : stack::
     141                 : pop(T& t, std::true_type)
     142                 : {
     143          328587 :     BOOST_ASSERT( size_ >= sizeof(T) );
     144          328587 :     peek(t);
     145          328587 :     size_ -= sizeof(T);
     146          328587 : }
     147                 : 
     148                 : // non-trivial
     149                 : template<class T>
     150                 : void
     151               3 : stack::
     152                 : pop(T& t, std::false_type)
     153                 : {
     154               3 :     auto next = head_->next;
     155               3 :     auto offset = head_->offset;
     156                 : 
     157                 :     using U = remove_cvref<T>;
     158                 :     using Holder = non_trivial<U>;
     159               3 :     auto const head = static_cast<Holder*>(head_);
     160                 : 
     161               3 :     t = std::move( head->obj );
     162               3 :     head->~Holder();
     163                 : 
     164               3 :     head_ = next;
     165               3 :     size_ -= offset;
     166               3 : }
     167                 : 
     168                 : } // detail
     169                 : } // json
     170                 : } // boost
     171                 : 
     172                 : #endif
        

Generated by: LCOV version 2.3