detail/string_impl.hpp

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