GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/impl/stack.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 55 55 100.0%
Functions: 251 332 75.6%
Branches: 12 18 66.7%

Line Branch Exec 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/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
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
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 665342 stack::
68 push_unchecked(T const& t)
69 {
70 665342 constexpr std::size_t n = sizeof(T);
71 BOOST_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332671 times.
665342 BOOST_ASSERT( n <= cap_ - size_ );
73 665342 std::memcpy( base_ + size_, &t, n );
74 665342 size_ += n;
75 665342 }
76
77 template<class T>
78 void
79 1593556 stack::
80 peek(T& t)
81 {
82 1593556 constexpr std::size_t n = sizeof(T);
83 BOOST_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 796778 times.
1593556 BOOST_ASSERT( size_ >= n );
85 1593556 std::memcpy( &t, base_ + size_ - n, n );
86 1593556 }
87
88 //--------------------------------------
89
90 // trivial
91 template<class T>
92 void
93 95784 stack::
94 push(T const& t, std::true_type)
95 {
96
2/2
✓ Branch 0 taken 8953 times.
✓ Branch 1 taken 38939 times.
95784 if( sizeof(T) > cap_ - size_ )
97 17906 reserve_impl( sizeof(T) + size_ );
98 95780 push_unchecked(t);
99 95780 }
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
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
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
1/1
✓ Branch 1 taken 3 times.
3 reserve_impl(size_ + size + alignment - 1);
127 3 }
128 while(true);
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 BOOST_ASSERT(
130 (reinterpret_cast<unsigned char*>(ptr) + size - offset) ==
131 (base_ + size_) );
132
133
1/3
✓ Branch 2 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
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 658380 stack::
141 pop(T& t, std::true_type)
142 {
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 329190 times.
658380 BOOST_ASSERT( size_ >= sizeof(T) );
144 658380 peek(t);
145 658380 size_ -= sizeof(T);
146 658380 }
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
173