detail/sbo_buffer.hpp

100.0% Lines (50/50) 100.0% List of functions (21/21)
sbo_buffer.hpp
f(x) Functions (21)
Function Calls Lines Blocks
boost::json::detail::sbo_buffer<32ul>::is_small() const :42 58x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::is_small() const :42 2179970x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::dispose() :48 2x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::dispose() :48 6095x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::max_size() :67 45x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::max_size() :67 15367x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::sbo_buffer() :73 3x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::sbo_buffer() :73 2164604x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::~sbo_buffer() :116 3x 75.0% 60.0% boost::json::detail::sbo_buffer<34ul>::~sbo_buffer() :116 2164604x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::capacity() const :123 53x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::capacity() const :123 9271x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::reset() :129 1x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::clear() :136 42x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::clear() :136 6242824x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::grow(unsigned long) :142 44x 93.8% 89.0% boost::json::detail::sbo_buffer<34ul>::grow(unsigned long) :142 11794x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::append(char const*, unsigned long) :172 44x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::append(char const*, unsigned long) :172 11794x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::size() :183 89x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::size() :183 3066342x 100.0% 100.0%
Line TLA Hits Source Code
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 2180028x is_small() const noexcept
43 {
44 2180028x return data_ == buffer_.data();
45 }
46
47 void
48 6097x dispose()
49 {
50 6097x if( is_small() )
51 3272x return;
52
53 2825x delete[] data_;
54 #if defined(__GNUC__)
55 # pragma GCC diagnostic push
56 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
57 #endif
58 2825x buffer_ = {};
59 #if defined(__GNUC__)
60 # pragma GCC diagnostic pop
61 #endif
62 5650x data_ = buffer_.data();
63 }
64
65 static constexpr
66 std::size_t
67 15412x max_size() noexcept
68 {
69 15412x return BOOST_JSON_MAX_STRING_SIZE;
70 }
71
72 public:
73 2164607x sbo_buffer()
74 2164607x : buffer_()
75 2164607x {}
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 2164607x ~sbo_buffer()
117 {
118 2164607x if( !is_small() )
119 3271x delete[] data_;
120 2164607x }
121
122 std::size_t
123 9324x capacity() const noexcept
124 {
125 15734x return is_small() ? buffer_.size() : capacity_;
126 }
127
128 void
129 1x reset() noexcept
130 {
131 1x dispose();
132 1x clear();
133 1x }
134
135 void
136 6242866x clear()
137 {
138 6242866x size_ = 0;
139 6242866x }
140
141 void
142 11838x grow( std::size_t size )
143 {
144 11838x if( !size )
145 5741x return;
146
147 9316x if( max_size() - size_ < size )
148 {
149 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
150 1x detail::throw_system_error( error::number_too_large, &loc );
151 }
152
153 9315x std::size_t const old_capacity = this->capacity();
154 9315x if( size <= old_capacity - size_ )
155 3219x return;
156
157 6096x std::size_t new_capacity = size_ + size;
158
159 // growth factor 2
160 6096x if( old_capacity <= max_size() - old_capacity ) // check for overflow
161 6096x new_capacity = (std::max)(old_capacity * 2, new_capacity);
162
163 6096x char* new_data = new char[new_capacity];
164 6096x std::memcpy(new_data, data_, size_);
165
166 6096x dispose();
167 6096x data_ = new_data;
168 6096x capacity_ = new_capacity;
169 }
170
171 char*
172 11838x append( char const* ptr, std::size_t size )
173 {
174 11838x grow(size);
175
176 11837x if(BOOST_JSON_LIKELY( size ))
177 9315x std::memcpy( data_ + size_, ptr, size );
178 11837x size_ += size;
179 11837x return data_;
180 }
181
182 std::size_t
183 3066431x size() noexcept
184 {
185 3066431x return size_;
186 }
187 };
188
189 } // namespace detail
190 } // namespace json
191 } // namespace boost
192
193 #endif // BOOST_JSON_DETAIL_SBO_BUFFER_HPP
194