GCC Code Coverage Report


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