detail/sbo_buffer.hpp

100.0% Lines (48/48) 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 2182495x 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 17889x 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 2164607x 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 2164607x 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 11793x 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 6242830x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::grow(unsigned long) :142 44x 92.9% 93.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) :168 44x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::append(char const*, unsigned long) :168 11794x 100.0% 100.0% boost::json::detail::sbo_buffer<32ul>::size() :179 89x 100.0% 100.0% boost::json::detail::sbo_buffer<34ul>::size() :179 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 2182553x is_small() const noexcept
43 {
44 2182553x 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 17934x max_size() noexcept
68 {
69 17934x return BOOST_JSON_MAX_STRING_SIZE;
70 }
71
72 public:
73 2164610x sbo_buffer()
74 2164610x : buffer_()
75 2164610x {}
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 2164610x ~sbo_buffer()
117 {
118 2164610x if( !is_small() )
119 3271x delete[] data_;
120 2164610x }
121
122 std::size_t
123 11846x capacity() const noexcept
124 {
125 19132x 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 6242872x clear()
137 {
138 6242872x size_ = 0;
139 6242872x }
140
141 void
142 11838x grow( std::size_t size )
143 {
144 11838x if( max_size() - size_ < size )
145 {
146 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
147 1x detail::throw_system_error( error::number_too_large, &loc );
148 }
149
150 11837x std::size_t const old_capacity = this->capacity();
151 11837x std::size_t new_capacity = size_ + size;
152 11837x if( new_capacity <= old_capacity )
153 5741x return;
154
155 // growth factor 2
156 6096x if( old_capacity <= max_size() - old_capacity ) // check for overflow
157 6096x new_capacity = (std::max)(old_capacity * 2, new_capacity);
158
159 6096x char* new_data = new char[new_capacity];
160 6096x std::memcpy(new_data, data_, size_);
161
162 6096x dispose();
163 6096x data_ = new_data;
164 6096x capacity_ = new_capacity;
165 }
166
167 char*
168 11838x append( char const* ptr, std::size_t size )
169 {
170 11838x grow(size);
171
172 11837x if(BOOST_JSON_LIKELY( size ))
173 9315x std::memcpy( data_ + size_, ptr, size );
174 11837x size_ += size;
175 11837x return data_;
176 }
177
178 std::size_t
179 3066431x size() noexcept
180 {
181 3066431x return size_;
182 }
183 };
184
185 } // namespace detail
186 } // namespace json
187 } // namespace boost
188
189 #endif // BOOST_JSON_DETAIL_SBO_BUFFER_HPP
190