GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/sbo_buffer.hpp
Date: 2026-01-06 06:25:57
Exec Total Coverage
Lines: 44 44 100.0%
Functions: 10 10 100.0%
Branches: 16 19 84.2%

Line Branch Exec Source
1 //
2 // Copyright (c) 2023 Dmitry Arkhipov (grisumbras@yandex.ru)
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
11 #ifndef BOOST_JSON_DETAIL_SBO_BUFFER_HPP
12 #define BOOST_JSON_DETAIL_SBO_BUFFER_HPP
13
14 #include <boost/core/detail/static_assert.hpp>
15 #include <boost/json/detail/config.hpp>
16 #include <boost/json/detail/except.hpp>
17 #include <string>
18 #include <array>
19
20 namespace boost {
21 namespace json {
22 namespace detail {
23
24 template< std::size_t N >
25 class sbo_buffer
26 {
27 struct size_ptr_pair
28 {
29 std::size_t size;
30 char* ptr;
31 };
32 BOOST_CORE_STATIC_ASSERT( N >= sizeof(size_ptr_pair) );
33
34 union {
35 std::array<char, N> buffer_;
36 std::size_t capacity_;
37 };
38 char* data_ = buffer_.data();
39 std::size_t size_ = 0;
40
41 bool
42 2183159 is_small() const noexcept
43 {
44 2183159 return data_ == buffer_.data();
45 }
46
47 void
48 9271 dispose()
49 {
50
2/2
✓ Branch 1 taken 4771 times.
✓ Branch 2 taken 4500 times.
9271 if( is_small() )
51 4771 return;
52
53
1/2
✓ Branch 0 taken 4500 times.
✗ Branch 1 not taken.
4500 delete[] data_;
54 #if defined(__GNUC__)
55 # pragma GCC diagnostic push
56 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
57 #endif
58 4500 buffer_ = {};
59 #if defined(__GNUC__)
60 # pragma GCC diagnostic pop
61 #endif
62 9000 data_ = buffer_.data();
63 }
64
65 static constexpr
66 std::size_t
67 18543 max_size() noexcept
68 {
69 18543 return BOOST_JSON_MAX_STRING_SIZE;
70 }
71
72 public:
73 2164617 sbo_buffer()
74 2164617 : buffer_()
75 2164617 {}
76
77 sbo_buffer( sbo_buffer&& other ) noexcept
78 : size_(other.size_)
79 {
80 if( other.is_small() )
81 {
82 buffer_ = other.buffer_;
83 data_ = buffer_.data();
84 }
85 else
86 {
87 data_ = other.data_;
88 other.data_ = other.buffer_.data();
89 }
90 BOOST_ASSERT( other.is_small() );
91 }
92
93 sbo_buffer&
94 operator=( sbo_buffer&& other ) noexcept
95 {
96 if( &other == this )
97 return this;
98
99 if( other.is_small() )
100 {
101 buffer_ = other.buffer_;
102 data_ = buffer_.data();
103 }
104 else
105 {
106 data_ = other.data_;
107 other.data_ = other.buffer_.data();
108 }
109
110 size_ = other.size_;
111 other.size_ = 0;
112
113 return *this;
114 }
115
116 2164617 ~sbo_buffer()
117 {
118
2/2
✓ Branch 1 taken 4771 times.
✓ Branch 2 taken 2159846 times.
2164617 if( !is_small() )
119
1/2
✓ Branch 0 taken 4771 times.
✗ Branch 1 not taken.
4771 delete[] data_;
120 2164617 }
121
122 std::size_t
123 9271 capacity() const noexcept
124 {
125
2/2
✓ Branch 1 taken 4771 times.
✓ Branch 2 taken 4500 times.
14042 return is_small() ? buffer_.size() : capacity_;
126 }
127
128 void
129 reset() noexcept
130 {
131 dispose();
132 clear();
133 }
134
135 void
136 6242889 clear()
137 {
138 6242889 size_ = 0;
139 6242889 }
140
141 void
142 11794 grow( std::size_t size )
143 {
144
2/2
✓ Branch 0 taken 2522 times.
✓ Branch 1 taken 9272 times.
11794 if( !size )
145 2522 return;
146
147
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9271 times.
9272 if( max_size() - size_ < size )
148 {
149 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
150 1 detail::throw_system_error( error::number_too_large, &loc );
151 }
152
153 9271 std::size_t const old_capacity = this->capacity();
154 9271 std::size_t new_capacity = size_ + size;
155
156 // growth factor 2
157
1/2
✓ Branch 1 taken 9271 times.
✗ Branch 2 not taken.
9271 if( old_capacity <= max_size() - old_capacity ) // check for overflow
158 9271 new_capacity = (std::max)(old_capacity * 2, new_capacity);
159
160
1/1
✓ Branch 1 taken 9271 times.
9271 char* new_data = new char[new_capacity];
161 9271 std::memcpy(new_data, data_, size_);
162
163 9271 dispose();
164 9271 data_ = new_data;
165 9271 capacity_ = new_capacity;
166 }
167
168 char*
169 11794 append( char const* ptr, std::size_t size )
170 {
171 11794 grow(size);
172
173
2/2
✓ Branch 0 taken 9271 times.
✓ Branch 1 taken 2522 times.
11793 if(BOOST_JSON_LIKELY( size ))
174 9271 std::memcpy( data_ + size_, ptr, size );
175 11793 size_ += size;
176 11793 return data_;
177 }
178
179 std::size_t
180 3066342 size() noexcept
181 {
182 3066342 return size_;
183 }
184 };
185
186 } // namespace detail
187 } // namespace json
188 } // namespace boost
189
190 #endif // BOOST_JSON_DETAIL_SBO_BUFFER_HPP
191