Coverage Report

Created: 2026-03-09 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boost/boost/json/detail/impl/stack.hpp
Line
Count
Source
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
    non_trivial(T t, non_trivial<>* next, std::size_t offset)
49
        : non_trivial<void>{relocate, next, offset}, obj( std::move(t) )
50
    {}
51
52
    static
53
    non_trivial<>*
54
    relocate(non_trivial<>* src, void* dest) noexcept
55
    {
56
        non_trivial* self = static_cast<non_trivial*>(src);
57
        non_trivial<>* result = nullptr;
58
        if( dest )
59
            result = ::new(dest) non_trivial( std::move(*self) );
60
        self->~non_trivial();
61
        return result;
62
    }
63
};
64
65
template<class T>
66
void
67
stack::
68
push_unchecked(T const& t)
69
43.1k
{
70
43.1k
    constexpr std::size_t n = sizeof(T);
71
43.1k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
43.1k
    BOOST_ASSERT( n <= cap_ - size_ );
73
43.1k
    std::memcpy( base_ + size_, &t, n );
74
43.1k
    size_ += n;
75
43.1k
}
void boost::json::detail::stack::push_unchecked<boost::json::detail::writer::state>(boost::json::detail::writer::state const&)
Line
Count
Source
69
9.78k
{
70
9.78k
    constexpr std::size_t n = sizeof(T);
71
9.78k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
9.78k
    std::memcpy( base_ + size_, &t, n );
74
9.78k
    size_ += n;
75
9.78k
}
void boost::json::detail::stack::push_unchecked<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state const&)
Line
Count
Source
69
13.6k
{
70
13.6k
    constexpr std::size_t n = sizeof(T);
71
13.6k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
13.6k
    std::memcpy( base_ + size_, &t, n );
74
13.6k
    size_ += n;
75
13.6k
}
void boost::json::detail::stack::push_unchecked<unsigned long>(unsigned long const&)
Line
Count
Source
69
4.47k
{
70
4.47k
    constexpr std::size_t n = sizeof(T);
71
4.47k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
4.47k
    std::memcpy( base_ + size_, &t, n );
74
4.47k
    size_ += n;
75
4.47k
}
void boost::json::detail::stack::push_unchecked<boost::json::array const*>(boost::json::array const* const&)
Line
Count
Source
69
5.76k
{
70
5.76k
    constexpr std::size_t n = sizeof(T);
71
5.76k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
5.76k
    std::memcpy( base_ + size_, &t, n );
74
5.76k
    size_ += n;
75
5.76k
}
void boost::json::detail::stack::push_unchecked<boost::json::value const*>(boost::json::value const* const&)
Line
Count
Source
69
5.76k
{
70
5.76k
    constexpr std::size_t n = sizeof(T);
71
5.76k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
5.76k
    std::memcpy( base_ + size_, &t, n );
74
5.76k
    size_ += n;
75
5.76k
}
void boost::json::detail::stack::push_unchecked<boost::json::object const*>(boost::json::object const* const&)
Line
Count
Source
69
1.89k
{
70
1.89k
    constexpr std::size_t n = sizeof(T);
71
1.89k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
1.89k
    std::memcpy( base_ + size_, &t, n );
74
1.89k
    size_ += n;
75
1.89k
}
void boost::json::detail::stack::push_unchecked<boost::json::key_value_pair const*>(boost::json::key_value_pair const* const&)
Line
Count
Source
69
1.89k
{
70
1.89k
    constexpr std::size_t n = sizeof(T);
71
1.89k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
    BOOST_ASSERT( n <= cap_ - size_ );
73
1.89k
    std::memcpy( base_ + size_, &t, n );
74
1.89k
    size_ += n;
75
1.89k
}
76
77
template<class T>
78
void
79
stack::
80
peek(T& t)
81
84.7k
{
82
84.7k
    constexpr std::size_t n = sizeof(T);
83
84.7k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
84.7k
    BOOST_ASSERT( size_ >= n );
85
84.7k
    std::memcpy( &t, base_ + size_ - n, n );
86
84.7k
}
void boost::json::detail::stack::peek<unsigned long>(unsigned long&)
Line
Count
Source
81
4.47k
{
82
4.47k
    constexpr std::size_t n = sizeof(T);
83
4.47k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
4.47k
    std::memcpy( &t, base_ + size_ - n, n );
86
4.47k
}
void boost::json::detail::stack::peek<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state&)
Line
Count
Source
81
45.7k
{
82
45.7k
    constexpr std::size_t n = sizeof(T);
83
45.7k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
45.7k
    std::memcpy( &t, base_ + size_ - n, n );
86
45.7k
}
void boost::json::detail::stack::peek<boost::json::detail::writer::state>(boost::json::detail::writer::state&)
Line
Count
Source
81
19.1k
{
82
19.1k
    constexpr std::size_t n = sizeof(T);
83
19.1k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
19.1k
    std::memcpy( &t, base_ + size_ - n, n );
86
19.1k
}
void boost::json::detail::stack::peek<boost::json::value const*>(boost::json::value const*&)
Line
Count
Source
81
5.76k
{
82
5.76k
    constexpr std::size_t n = sizeof(T);
83
5.76k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
5.76k
    std::memcpy( &t, base_ + size_ - n, n );
86
5.76k
}
void boost::json::detail::stack::peek<boost::json::array const*>(boost::json::array const*&)
Line
Count
Source
81
5.76k
{
82
5.76k
    constexpr std::size_t n = sizeof(T);
83
5.76k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
5.76k
    std::memcpy( &t, base_ + size_ - n, n );
86
5.76k
}
void boost::json::detail::stack::peek<boost::json::key_value_pair const*>(boost::json::key_value_pair const*&)
Line
Count
Source
81
1.89k
{
82
1.89k
    constexpr std::size_t n = sizeof(T);
83
1.89k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
1.89k
    std::memcpy( &t, base_ + size_ - n, n );
86
1.89k
}
void boost::json::detail::stack::peek<boost::json::object const*>(boost::json::object const*&)
Line
Count
Source
81
1.89k
{
82
1.89k
    constexpr std::size_t n = sizeof(T);
83
1.89k
    BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
    BOOST_ASSERT( size_ >= n );
85
1.89k
    std::memcpy( &t, base_ + size_ - n, n );
86
1.89k
}
87
88
//--------------------------------------
89
90
// trivial
91
template<class T>
92
void
93
stack::
94
push(T const& t, std::true_type)
95
25.1k
{
96
25.1k
    if( sizeof(T) > cap_ - size_ )
97
1.69k
        reserve_impl( sizeof(T) + size_ );
98
25.1k
    push_unchecked(t);
99
25.1k
}
void boost::json::detail::stack::push<boost::json::detail::writer::state>(boost::json::detail::writer::state const&, std::__1::integral_constant<bool, true>)
Line
Count
Source
95
9.78k
{
96
9.78k
    if( sizeof(T) > cap_ - size_ )
97
566
        reserve_impl( sizeof(T) + size_ );
98
9.78k
    push_unchecked(t);
99
9.78k
}
Unexecuted instantiation: void boost::json::detail::stack::push<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state const&, std::__1::integral_constant<bool, true>)
void boost::json::detail::stack::push<boost::json::array const*>(boost::json::array const* const&, std::__1::integral_constant<bool, true>)
Line
Count
Source
95
5.76k
{
96
5.76k
    if( sizeof(T) > cap_ - size_ )
97
418
        reserve_impl( sizeof(T) + size_ );
98
5.76k
    push_unchecked(t);
99
5.76k
}
void boost::json::detail::stack::push<boost::json::value const*>(boost::json::value const* const&, std::__1::integral_constant<bool, true>)
Line
Count
Source
95
5.76k
{
96
5.76k
    if( sizeof(T) > cap_ - size_ )
97
418
        reserve_impl( sizeof(T) + size_ );
98
5.76k
    push_unchecked(t);
99
5.76k
}
void boost::json::detail::stack::push<boost::json::object const*>(boost::json::object const* const&, std::__1::integral_constant<bool, true>)
Line
Count
Source
95
1.89k
{
96
1.89k
    if( sizeof(T) > cap_ - size_ )
97
147
        reserve_impl( sizeof(T) + size_ );
98
1.89k
    push_unchecked(t);
99
1.89k
}
void boost::json::detail::stack::push<boost::json::key_value_pair const*>(boost::json::key_value_pair const* const&, std::__1::integral_constant<bool, true>)
Line
Count
Source
95
1.89k
{
96
1.89k
    if( sizeof(T) > cap_ - size_ )
97
147
        reserve_impl( sizeof(T) + size_ );
98
1.89k
    push_unchecked(t);
99
1.89k
}
100
101
// non-trivial
102
template<class T>
103
void
104
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
    constexpr std::size_t size = sizeof(Holder);
111
    constexpr std::size_t alignment = alignof(Holder);
112
113
    void* ptr;
114
    std::size_t offset;
115
    do
116
    {
117
        std::size_t space = cap_ - size_;
118
        unsigned char* buf = base_ + size_;
119
        ptr = buf;
120
        if( std::align(alignment, size, ptr, space) )
121
        {
122
            offset = (reinterpret_cast<unsigned char*>(ptr) - buf) + size;
123
            break;
124
        }
125
126
        reserve_impl(size_ + size + alignment - 1);
127
    }
128
    while(true);
129
    BOOST_ASSERT(
130
        (reinterpret_cast<unsigned char*>(ptr) + size - offset) ==
131
        (base_ + size_) );
132
133
    head_ = ::new(ptr) Holder( static_cast<T&&>(t), head_, offset );
134
    size_ += offset;
135
}
136
137
// trivial
138
template<class T>
139
void
140
stack::
141
pop(T& t, std::true_type)
142
43.1k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
43.1k
    peek(t);
145
43.1k
    size_ -= sizeof(T);
146
43.1k
}
void boost::json::detail::stack::pop<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
13.5k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
13.5k
    peek(t);
145
13.5k
    size_ -= sizeof(T);
146
13.5k
}
void boost::json::detail::stack::pop<unsigned long>(unsigned long&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
4.47k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
4.47k
    peek(t);
145
4.47k
    size_ -= sizeof(T);
146
4.47k
}
void boost::json::detail::stack::pop<boost::json::detail::writer::state>(boost::json::detail::writer::state&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
9.78k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
9.78k
    peek(t);
145
9.78k
    size_ -= sizeof(T);
146
9.78k
}
void boost::json::detail::stack::pop<boost::json::value const*>(boost::json::value const*&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
5.76k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
5.76k
    peek(t);
145
5.76k
    size_ -= sizeof(T);
146
5.76k
}
void boost::json::detail::stack::pop<boost::json::array const*>(boost::json::array const*&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
5.76k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
5.76k
    peek(t);
145
5.76k
    size_ -= sizeof(T);
146
5.76k
}
void boost::json::detail::stack::pop<boost::json::key_value_pair const*>(boost::json::key_value_pair const*&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
1.89k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
1.89k
    peek(t);
145
1.89k
    size_ -= sizeof(T);
146
1.89k
}
void boost::json::detail::stack::pop<boost::json::object const*>(boost::json::object const*&, std::__1::integral_constant<bool, true>)
Line
Count
Source
142
1.89k
{
143
    BOOST_ASSERT( size_ >= sizeof(T) );
144
1.89k
    peek(t);
145
1.89k
    size_ -= sizeof(T);
146
1.89k
}
147
148
// non-trivial
149
template<class T>
150
void
151
stack::
152
pop(T& t, std::false_type)
153
{
154
    auto next = head_->next;
155
    auto offset = head_->offset;
156
157
    using U = remove_cvref<T>;
158
    using Holder = non_trivial<U>;
159
    auto const head = static_cast<Holder*>(head_);
160
161
    t = std::move( head->obj );
162
    head->~Holder();
163
164
    head_ = next;
165
    size_ -= offset;
166
}
167
168
} // detail
169
} // json
170
} // boost
171
172
#endif