detail/string_impl.hpp

98.6% Lines (72/0/73) 100.0% List of functions (22/0/22)
string_impl.hpp
f(x) Functions (22)
Function Calls Lines Blocks
boost::json::detail::string_impl::max_size() :108 154009x 100.0% 100.0% boost::json::detail::string_impl::string_impl<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >(__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::json::storage_ptr const&, std::random_access_iterator_tag) :145 3x 100.0% 100.0% boost::json::detail::string_impl::string_impl<char const*>(char const*, char const*, boost::json::storage_ptr const&, std::random_access_iterator_tag) :145 5x 100.0% 100.0% boost::json::detail::string_impl::string_impl<boost::json::detail::pointer_token::iterator>(boost::json::detail::pointer_token::iterator, boost::json::detail::pointer_token::iterator, boost::json::storage_ptr const&, std::input_iterator_tag) :162 21x 100.0% 82.0% boost::json::detail::string_impl::string_impl<boost::json::input_iterator<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >(boost::json::input_iterator<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::json::input_iterator<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::json::storage_ptr const&, std::input_iterator_tag) :162 12x 100.0% 100.0% boost::json::detail::string_impl::string_impl<boost::json::input_iterator<char const*> >(boost::json::input_iterator<char const*>, boost::json::input_iterator<char const*>, boost::json::storage_ptr const&, std::input_iterator_tag) :162 5x 100.0% 100.0% boost::json::detail::string_impl::string_impl<boost::json::detail::pointer_token::iterator>(boost::json::detail::pointer_token::iterator, boost::json::detail::pointer_token::iterator, boost::json::storage_ptr const&, std::input_iterator_tag)::undo::~undo() :174 21x 85.7% 67.0% boost::json::detail::string_impl::size() const :196 99324x 100.0% 100.0% boost::json::detail::string_impl::capacity() const :205 92040x 100.0% 100.0% boost::json::detail::string_impl::size(unsigned long) :213 10018x 100.0% 100.0% boost::json::detail::string_impl::release_key(unsigned long&) :232 38150x 100.0% 75.0% boost::json::detail::string_impl::destroy(boost::json::storage_ptr const&) :245 57679x 100.0% 89.0% boost::json::detail::string_impl::term(unsigned long) :321 33639x 100.0% 100.0% boost::json::detail::string_impl::data() :339 117522x 100.0% 100.0% boost::json::detail::string_impl::data() const :348 44016x 100.0% 100.0% boost::json::detail::string_impl::end() :357 241x 100.0% 100.0% boost::json::detail::string_impl::end() const :363 10x 100.0% 100.0% boost::core::basic_string_view<char> boost::json::detail::to_string_view<boost::core::basic_string_view<char> >(boost::core::basic_string_view<char> const&) :371 8x 100.0% 100.0% boost::core::basic_string_view<char> boost::json::detail::to_string_view<char [14]>(char const (&) [14]) :371 1x 100.0% 100.0% boost::core::basic_string_view<char> boost::json::detail::to_string_view<char [3]>(char const (&) [3]) :371 109x 100.0% 100.0% boost::core::basic_string_view<char> boost::json::detail::to_string_view<char [6]>(char const (&) [6]) :371 15x 100.0% 100.0% boost::core::basic_string_view<char> boost::json::detail::to_string_view<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :371 2097x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/json
9 //
10
11 #ifndef BOOST_JSON_DETAIL_STRING_IMPL_HPP
12 #define BOOST_JSON_DETAIL_STRING_IMPL_HPP
13
14 #include <boost/core/detail/static_assert.hpp>
15 #include <boost/json/detail/config.hpp>
16 #include <boost/json/kind.hpp>
17 #include <boost/json/storage_ptr.hpp>
18 #include <boost/json/detail/value.hpp>
19 #include <algorithm>
20 #include <iterator>
21
22 namespace boost {
23 namespace json {
24
25 class value;
26 class string;
27
28 namespace detail {
29
30 bool
31 ptr_in_range(
32 const char* first,
33 const char* last,
34 const char* ptr) noexcept;
35
36 class string_impl
37 {
38 struct table
39 {
40 std::uint32_t size;
41 std::uint32_t capacity;
42 };
43
44 #if BOOST_JSON_ARCH == 64
45 static constexpr std::size_t sbo_chars_ = 14;
46 #elif BOOST_JSON_ARCH == 32
47 static constexpr std::size_t sbo_chars_ = 10;
48 #else
49 # error Unknown architecture
50 #endif
51
52 static
53 constexpr
54 kind
55 short_string_ =
56 static_cast<kind>(
57 ((unsigned char)
58 kind::string) | 0x80);
59
60 static
61 constexpr
62 kind
63 key_string_ =
64 static_cast<kind>(
65 ((unsigned char)
66 kind::string) | 0x40);
67
68 struct sbo
69 {
70 kind k; // must come first
71 char buf[sbo_chars_ + 1];
72 };
73
74 struct pointer
75 {
76 kind k; // must come first
77 table* t;
78 };
79
80 struct key
81 {
82 kind k; // must come first
83 std::uint32_t n;
84 char* s;
85 };
86
87 union
88 {
89 sbo s_;
90 pointer p_;
91 key k_;
92 };
93
94 #if BOOST_JSON_ARCH == 64
95 BOOST_CORE_STATIC_ASSERT( sizeof(sbo) <= 16 );
96 BOOST_CORE_STATIC_ASSERT( sizeof(pointer) <= 16 );
97 BOOST_CORE_STATIC_ASSERT( sizeof(key) <= 16 );
98 #elif BOOST_JSON_ARCH == 32
99 BOOST_CORE_STATIC_ASSERT( sizeof(sbo) <= 24 );
100 BOOST_CORE_STATIC_ASSERT( sizeof(pointer) <= 24 );
101 BOOST_CORE_STATIC_ASSERT( sizeof(key) <= 24 );
102 #endif
103
104 public:
105 static
106 constexpr
107 std::size_t
108 154009x max_size() noexcept
109 {
110 // max_size depends on the address model
111 using min = std::integral_constant<std::size_t,
112 std::size_t(-1) - sizeof(table)>;
113 return min::value < BOOST_JSON_MAX_STRING_SIZE ?
114 154009x min::value : BOOST_JSON_MAX_STRING_SIZE;
115 }
116
117 BOOST_JSON_DECL
118 string_impl() noexcept;
119
120 BOOST_JSON_DECL
121 string_impl(
122 std::size_t new_size,
123 storage_ptr const& sp);
124
125 BOOST_JSON_DECL
126 string_impl(
127 key_t,
128 string_view s,
129 storage_ptr const& sp);
130
131 BOOST_JSON_DECL
132 string_impl(
133 key_t,
134 string_view s1,
135 string_view s2,
136 storage_ptr const& sp);
137
138 BOOST_JSON_DECL
139 string_impl(
140 char** dest,
141 std::size_t len,
142 storage_ptr const& sp);
143
144 template<class InputIt>
145 8x string_impl(
146 InputIt first,
147 InputIt last,
148 storage_ptr const& sp,
149 std::random_access_iterator_tag)
150 8x : string_impl(last - first, sp)
151 {
152 7x char* out = data();
153 #if defined(_MSC_VER) && _MSC_VER <= 1900
154 while( first != last )
155 *out++ = *first++;
156 #else
157 7x std::copy(first, last, out);
158 #endif
159 7x }
160
161 template<class InputIt>
162 38x string_impl(
163 InputIt first,
164 InputIt last,
165 storage_ptr const& sp,
166 std::input_iterator_tag)
167 38x : string_impl(0, sp)
168 {
169 struct undo
170 {
171 string_impl* s;
172 storage_ptr const& sp;
173
174 21x ~undo()
175 {
176 21x if(s)
177 s->destroy(sp);
178 21x }
179 };
180
181 38x undo u{this, sp};
182 38x auto dest = data();
183 313x while(first != last)
184 {
185 278x if(size() < capacity())
186 267x size(size() + 1);
187 else
188 11x dest = append(1, sp);
189 275x *dest++ = *first++;
190 }
191 35x term(size());
192 35x u.s = nullptr;
193 38x }
194
195 std::size_t
196 99324x size() const noexcept
197 {
198 99324x return s_.k == kind::string ?
199 64663x p_.t->size :
200 sbo_chars_ -
201 99324x s_.buf[sbo_chars_];
202 }
203
204 std::size_t
205 92040x capacity() const noexcept
206 {
207 92040x return s_.k == kind::string ?
208 11846x p_.t->capacity :
209 92040x sbo_chars_;
210 }
211
212 void
213 10018x size(std::size_t n)
214 {
215 10018x if(s_.k == kind::string)
216 9735x p_.t->size = static_cast<
217 std::uint32_t>(n);
218 else
219 283x s_.buf[sbo_chars_] =
220 static_cast<char>(
221 283x sbo_chars_ - n);
222 10018x }
223
224 BOOST_JSON_DECL
225 static
226 std::uint32_t
227 growth(
228 std::size_t new_size,
229 std::size_t capacity);
230
231 char const*
232 38150x release_key(
233 std::size_t& n) noexcept
234 {
235 38150x BOOST_ASSERT(
236 k_.k == key_string_);
237 38150x n = k_.n;
238 38150x auto const s = k_.s;
239 // prevent deallocate
240 38150x k_.k = short_string_;
241 38150x return s;
242 }
243
244 void
245 57679x destroy(
246 storage_ptr const& sp) noexcept
247 {
248 57679x if(s_.k == kind::string)
249 {
250 26681x sp->deallocate(p_.t,
251 sizeof(table) +
252 26681x p_.t->capacity + 1,
253 alignof(table));
254 }
255 30998x else if(s_.k != key_string_)
256 {
257 // do nothing
258 }
259 else
260 {
261 146x BOOST_ASSERT(
262 s_.k == key_string_);
263 // VFALCO unfortunately the key string
264 // kind increases the cost of the destructor.
265 // This function should be skipped when using
266 // monotonic_resource.
267 146x sp->deallocate(k_.s, k_.n + 1);
268 }
269 57679x }
270
271 BOOST_JSON_DECL
272 char*
273 assign(
274 std::size_t new_size,
275 storage_ptr const& sp);
276
277 BOOST_JSON_DECL
278 char*
279 append(
280 std::size_t n,
281 storage_ptr const& sp);
282
283 BOOST_JSON_DECL
284 void
285 insert(
286 std::size_t pos,
287 const char* s,
288 std::size_t n,
289 storage_ptr const& sp);
290
291 BOOST_JSON_DECL
292 char*
293 insert_unchecked(
294 std::size_t pos,
295 std::size_t n,
296 storage_ptr const& sp);
297
298 BOOST_JSON_DECL
299 void
300 replace(
301 std::size_t pos,
302 std::size_t n1,
303 const char* s,
304 std::size_t n2,
305 storage_ptr const& sp);
306
307 BOOST_JSON_DECL
308 char*
309 replace_unchecked(
310 std::size_t pos,
311 std::size_t n1,
312 std::size_t n2,
313 storage_ptr const& sp);
314
315 BOOST_JSON_DECL
316 void
317 shrink_to_fit(
318 storage_ptr const& sp) noexcept;
319
320 void
321 33639x term(std::size_t n) noexcept
322 {
323 33639x if(s_.k == short_string_)
324 {
325 5145x s_.buf[sbo_chars_] =
326 static_cast<char>(
327 5145x sbo_chars_ - n);
328 5145x s_.buf[n] = 0;
329 }
330 else
331 {
332 28494x p_.t->size = static_cast<
333 std::uint32_t>(n);
334 28494x data()[n] = 0;
335 }
336 33639x }
337
338 char*
339 117522x data() noexcept
340 {
341 117522x if(s_.k == short_string_)
342 15422x return s_.buf;
343 return reinterpret_cast<
344 102100x char*>(p_.t + 1);
345 }
346
347 char const*
348 44016x data() const noexcept
349 {
350 44016x if(s_.k == short_string_)
351 4553x return s_.buf;
352 return reinterpret_cast<
353 39463x char const*>(p_.t + 1);
354 }
355
356 char*
357 241x end() noexcept
358 {
359 241x return data() + size();
360 }
361
362 char const*
363 10x end() const noexcept
364 {
365 10x return data() + size();
366 }
367 };
368
369 template<class T>
370 string_view
371 2486x to_string_view(T const& t) noexcept
372 {
373 2486x return string_view(t);
374 }
375
376 template<class T, class U>
377 using string_and_stringlike = std::integral_constant<bool,
378 std::is_same<T, string>::value &&
379 std::is_convertible<U const&, string_view>::value>;
380
381 template<class T, class U>
382 using string_comp_op_requirement
383 = typename std::enable_if<
384 string_and_stringlike<T, U>::value ||
385 string_and_stringlike<U, T>::value,
386 bool>::type;
387
388 } // detail
389 } // namespace json
390 } // namespace boost
391
392 #endif
393