LCOV - code coverage report
Current view: top level - json/detail/impl - stack.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 55 55
Test Date: 2025-12-23 17:20:51 Functions: 75.6 % 332 251

            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/align/align.hpp>
      14              : #include <boost/static_assert.hpp>
      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            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       332671 : stack::
      68              : push_unchecked(T const& t)
      69              : {
      70       332671 :     constexpr std::size_t n = sizeof(T);
      71              :     BOOST_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
      72       332671 :     BOOST_ASSERT( n <= cap_ - size_ );
      73       332671 :     std::memcpy( base_ + size_, &t, n );
      74       332671 :     size_ += n;
      75       332671 : }
      76              : 
      77              : template<class T>
      78              : void
      79       796778 : stack::
      80              : peek(T& t)
      81              : {
      82       796778 :     constexpr std::size_t n = sizeof(T);
      83              :     BOOST_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
      84       796778 :     BOOST_ASSERT( size_ >= n );
      85       796778 :     std::memcpy( &t, base_ + size_ - n, n );
      86       796778 : }
      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_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( alignment::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       329190 : stack::
     141              : pop(T& t, std::true_type)
     142              : {
     143       329190 :     BOOST_ASSERT( size_ >= sizeof(T) );
     144       329190 :     peek(t);
     145       329190 :     size_ -= sizeof(T);
     146       329190 : }
     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.1