impl/value.ipp

99.6% Lines (455/457) 100.0% List of functions (74/74)
value.ipp
f(x) Functions (74)
Function Calls Lines Blocks
void boost::json::(anonymous namespace)::value_hasher::operator()<bool const&>(bool const&) const :36 28x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<boost::json::array const&>(boost::json::array const&) const :36 10x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<boost::json::object const&>(boost::json::object const&) const :36 20x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<boost::json::string const&>(boost::json::string const&) const :36 44x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<decltype(nullptr) const&>(decltype(nullptr) const&) const :36 32x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<double const&>(double const&) const :36 8x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<long const&>(long const&) const :36 90x 100.0% 100.0% void boost::json::(anonymous namespace)::value_hasher::operator()<unsigned long const&>(unsigned long const&) const :36 16x 100.0% 100.0% boost::json::(anonymous namespace)::to_bitmask(boost::json::parse_options const&) :50 3x 100.0% 73.0% boost::json::(anonymous namespace)::get_parse_options(std::istream&) :63 9x 100.0% 100.0% boost::json::value::~value() :80 2178639x 100.0% 100.0% boost::json::value::value(boost::json::value const&, boost::json::storage_ptr) :107 9490x 100.0% 100.0% boost::json::value::value(boost::json::value&&) :163 3784x 100.0% 100.0% boost::json::value::value(boost::json::value&&, boost::json::storage_ptr) :170 11452x 100.0% 100.0% boost::json::value::value(std::initializer_list<boost::json::value_ref>, boost::json::storage_ptr) :228 336x 84.6% 64.0% boost::json::value::operator=(boost::json::value const&) :263 38x 100.0% 86.0% boost::json::value::operator=(boost::json::value&&) :272 82x 100.0% 100.0% boost::json::value::operator=(std::initializer_list<boost::json::value_ref>) :281 13x 100.0% 64.0% boost::json::value::operator=(boost::core::basic_string_view<char>) :291 2x 100.0% 64.0% boost::json::value::operator=(char const*) :299 28x 100.0% 64.0% boost::json::value::operator=(boost::json::string const&) :307 12x 100.0% 64.0% boost::json::value::operator=(boost::json::string&&) :315 7x 100.0% 67.0% boost::json::value::operator=(boost::json::array const&) :324 4x 100.0% 64.0% boost::json::value::operator=(boost::json::array&&) :332 21x 100.0% 67.0% boost::json::value::operator=(boost::json::object const&) :341 4x 100.0% 64.0% boost::json::value::operator=(boost::json::object&&) :349 54x 100.0% 67.0% boost::json::value::try_as_array() :364 16x 100.0% 100.0% boost::json::value::try_as_array() const :375 305x 100.0% 100.0% boost::json::value::try_as_object() :386 9x 100.0% 100.0% boost::json::value::try_as_object() const :397 282x 100.0% 100.0% boost::json::value::try_as_string() :408 9x 100.0% 100.0% boost::json::value::try_as_string() const :419 121x 100.0% 100.0% boost::json::value::try_as_int64() :430 52x 100.0% 100.0% boost::json::value::try_as_int64() const :441 33x 100.0% 100.0% boost::json::value::try_as_uint64() :452 16x 100.0% 100.0% boost::json::value::try_as_uint64() const :463 16x 100.0% 100.0% boost::json::value::try_as_double() :474 2000657x 100.0% 100.0% boost::json::value::try_as_double() const :485 580x 100.0% 100.0% boost::json::value::try_as_bool() :496 19x 100.0% 100.0% boost::json::value::try_as_bool() const :507 30x 100.0% 100.0% boost::json::value::try_as_null() const :518 2x 100.0% 100.0% boost::json::value::try_at(boost::core::basic_string_view<char>) :529 1x 100.0% 100.0% boost::json::value::try_at(boost::core::basic_string_view<char>)::{lambda(boost::json::object&)#1}::operator()(boost::json::object&) const :531 1x 100.0% 100.0% boost::json::value::try_at(boost::core::basic_string_view<char>) const :535 3x 100.0% 100.0% boost::json::value::try_at(boost::core::basic_string_view<char>) const::{lambda(boost::json::object const&)#1}::operator()(boost::json::object const&) const :538 3x 100.0% 100.0% boost::json::value::try_at(unsigned long) :542 8x 100.0% 100.0% boost::json::value::try_at(unsigned long)::{lambda(boost::json::array&)#1}::operator()(boost::json::array&) const :544 8x 100.0% 100.0% boost::json::value::try_at(unsigned long) const :548 2x 100.0% 100.0% boost::json::value::try_at(unsigned long) const::{lambda(boost::json::array const&)#1}::operator()(boost::json::array const&) const :550 2x 100.0% 100.0% boost::json::value::as_object(boost::source_location const&) const & :554 197x 100.0% 100.0% boost::json::value::as_array(boost::source_location const&) const & :560 176x 100.0% 100.0% boost::json::value::as_string(boost::source_location const&) const & :566 113x 100.0% 100.0% boost::json::value::as_int64(boost::source_location const&) :572 44x 100.0% 100.0% boost::json::value::as_int64(boost::source_location const&) const :578 26x 100.0% 100.0% boost::json::value::as_uint64(boost::source_location const&) :584 8x 100.0% 100.0% boost::json::value::as_uint64(boost::source_location const&) const :590 8x 100.0% 100.0% boost::json::value::as_double(boost::source_location const&) :596 2000649x 100.0% 100.0% boost::json::value::as_double(boost::source_location const&) const :602 572x 100.0% 100.0% boost::json::value::as_bool(boost::source_location const&) :608 10x 100.0% 100.0% boost::json::value::as_bool(boost::source_location const&) const :614 22x 100.0% 100.0% boost::json::value::emplace_string() :626 99x 100.0% 100.0% boost::json::value::emplace_array() :634 250x 100.0% 100.0% boost::json::value::emplace_object() :642 56x 100.0% 100.0% boost::json::value::swap(boost::json::value&) :650 259x 100.0% 81.0% boost::json::value::swap(boost::json::value&)::U::U() :659 258x 100.0% 100.0% boost::json::value::swap(boost::json::value&)::U::~U() :660 258x 100.0% 100.0% boost::json::operator>>(std::istream&, boost::json::value&) :683 10x 100.0% 92.0% boost::json::operator>>(std::istream&, boost::json::parse_options const&) :784 3x 100.0% 100.0% boost::json::value::destroy() :800 423x 100.0% 100.0% boost::json::value::equal(boost::json::value const&) const :838 4172x 100.0% 100.0% boost::json::key_value_pair::key_value_pair(boost::json::pilfered<boost::json::value>, boost::json::pilfered<boost::json::value>) :913 38150x 100.0% 100.0% boost::json::key_value_pair::key_value_pair(boost::json::key_value_pair const&, boost::json::storage_ptr) :924 6858x 100.0% 100.0% boost::json::detail::hash_value_impl(boost::json::value const&) :947 248x 100.0% 100.0% std::hash<boost::json::value>::operator()(boost::json::value const&) const :969 62x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
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 #ifndef BOOST_JSON_IMPL_VALUE_IPP
11 #define BOOST_JSON_IMPL_VALUE_IPP
12
13 #include <boost/container_hash/hash.hpp>
14 #include <boost/json/value.hpp>
15 #include <boost/json/parser.hpp>
16 #include <cstring>
17 #include <istream>
18 #include <limits>
19 #include <new>
20 #include <utility>
21
22 namespace boost {
23 namespace json {
24
25 namespace
26 {
27
28 int parse_depth_xalloc = std::ios::xalloc();
29 int parse_flags_xalloc = std::ios::xalloc();
30
31 struct value_hasher
32 {
33 std::size_t& seed;
34
35 template< class T >
36 248x void operator()( T&& t ) const noexcept
37 {
38 248x boost::hash_combine( seed, t );
39 248x }
40 };
41
42 enum class stream_parse_flags
43 {
44 allow_comments = 1 << 0,
45 allow_trailing_commas = 1 << 1,
46 allow_invalid_utf8 = 1 << 2,
47 };
48
49 long
50 3x to_bitmask( parse_options const& opts )
51 {
52 using E = stream_parse_flags;
53 return
54 3x (opts.allow_comments ?
55 3x static_cast<long>(E::allow_comments) : 0) |
56 3x (opts.allow_trailing_commas ?
57 static_cast<long>(E::allow_trailing_commas) : 0) |
58 3x (opts.allow_invalid_utf8 ?
59 3x static_cast<long>(E::allow_invalid_utf8) : 0);
60 }
61
62 parse_options
63 9x get_parse_options( std::istream& is )
64 {
65 9x long const flags = is.iword(parse_flags_xalloc);
66
67 using E = stream_parse_flags;
68 9x parse_options opts;
69 9x opts.allow_comments =
70 9x flags & static_cast<long>(E::allow_comments) ? true : false;
71 9x opts.allow_trailing_commas =
72 9x flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
73 9x opts.allow_invalid_utf8 =
74 9x flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
75 9x return opts;
76 }
77
78 } // namespace
79
80 2178639x value::
81 ~value() noexcept
82 {
83 2178639x switch(kind())
84 {
85 2112969x case json::kind::null:
86 case json::kind::bool_:
87 case json::kind::int64:
88 case json::kind::uint64:
89 case json::kind::double_:
90 2112969x sca_.~scalar();
91 2112969x break;
92
93 27377x case json::kind::string:
94 27377x str_.~string();
95 27377x break;
96
97 3088x case json::kind::array:
98 3088x arr_.~array();
99 3088x break;
100
101 35205x case json::kind::object:
102 35205x obj_.~object();
103 35205x break;
104 }
105 2178639x }
106
107 9490x value::
108 value(
109 value const& other,
110 9490x storage_ptr sp)
111 {
112 9490x switch(other.kind())
113 {
114 2034x case json::kind::null:
115 6102x ::new(&sca_) scalar(
116 2034x std::move(sp));
117 2034x break;
118
119 121x case json::kind::bool_:
120 363x ::new(&sca_) scalar(
121 121x other.sca_.b,
122 121x std::move(sp));
123 121x break;
124
125 7006x case json::kind::int64:
126 21018x ::new(&sca_) scalar(
127 7006x other.sca_.i,
128 7006x std::move(sp));
129 7006x break;
130
131 35x case json::kind::uint64:
132 105x ::new(&sca_) scalar(
133 35x other.sca_.u,
134 35x std::move(sp));
135 35x break;
136
137 12x case json::kind::double_:
138 36x ::new(&sca_) scalar(
139 12x other.sca_.d,
140 12x std::move(sp));
141 12x break;
142
143 130x case json::kind::string:
144 17x ::new(&str_) string(
145 130x other.str_,
146 164x std::move(sp));
147 113x break;
148
149 122x case json::kind::array:
150 26x ::new(&arr_) array(
151 122x other.arr_,
152 174x std::move(sp));
153 96x break;
154
155 30x case json::kind::object:
156 10x ::new(&obj_) object(
157 30x other.obj_,
158 50x std::move(sp));
159 20x break;
160 }
161 9437x }
162
163 3784x value::
164 3784x value(value&& other) noexcept
165 {
166 3784x relocate(this, other);
167 3784x ::new(&other.sca_) scalar(sp_);
168 3784x }
169
170 11452x value::
171 value(
172 value&& other,
173 11452x storage_ptr sp)
174 {
175 11452x switch(other.kind())
176 {
177 77x case json::kind::null:
178 229x ::new(&sca_) scalar(
179 77x std::move(sp));
180 77x break;
181
182 190x case json::kind::bool_:
183 570x ::new(&sca_) scalar(
184 190x other.sca_.b, std::move(sp));
185 190x break;
186
187 10452x case json::kind::int64:
188 31356x ::new(&sca_) scalar(
189 10452x other.sca_.i, std::move(sp));
190 10452x break;
191
192 75x case json::kind::uint64:
193 225x ::new(&sca_) scalar(
194 75x other.sca_.u, std::move(sp));
195 75x break;
196
197 34x case json::kind::double_:
198 102x ::new(&sca_) scalar(
199 34x other.sca_.d, std::move(sp));
200 34x break;
201
202 336x case json::kind::string:
203 4x ::new(&str_) string(
204 336x std::move(other.str_),
205 680x std::move(sp));
206 332x break;
207
208 224x case json::kind::array:
209 5x ::new(&arr_) array(
210 224x std::move(other.arr_),
211 458x std::move(sp));
212 219x break;
213
214 64x case json::kind::object:
215 13x ::new(&obj_) object(
216 64x std::move(other.obj_),
217 154x std::move(sp));
218 51x break;
219 }
220 11430x }
221
222 //----------------------------------------------------------
223 //
224 // Conversion
225 //
226 //----------------------------------------------------------
227
228 336x value::
229 value(
230 std::initializer_list<value_ref> init,
231 336x storage_ptr sp)
232 {
233 336x if(value_ref::maybe_object(init))
234 {
235 ::new(&obj_) object(
236 value_ref::make_object(
237 103x init, std::move(sp)));
238 }
239 else
240 {
241 233x if( init.size() == 1 )
242 {
243 13x ::new(&sca_) scalar();
244 13x value temp = init.begin()->make_value( std::move(sp) );
245 13x swap(temp);
246 13x }
247 else
248 {
249 ::new(&arr_) array(
250 value_ref::make_array(
251 220x init, std::move(sp)));
252 }
253 }
254 336x }
255
256 //----------------------------------------------------------
257 //
258 // Assignment
259 //
260 //----------------------------------------------------------
261
262 value&
263 38x value::
264 operator=(value const& other)
265 {
266 76x value(other,
267 32x storage()).swap(*this);
268 32x return *this;
269 }
270
271 value&
272 82x value::
273 operator=(value&& other)
274 {
275 164x value(std::move(other),
276 63x storage()).swap(*this);
277 63x return *this;
278 }
279
280 value&
281 13x value::
282 operator=(
283 std::initializer_list<value_ref> init)
284 {
285 26x value(init,
286 13x storage()).swap(*this);
287 13x return *this;
288 }
289
290 value&
291 2x value::
292 operator=(string_view s)
293 {
294 2x value(s, storage()).swap(*this);
295 2x return *this;
296 }
297
298 value&
299 28x value::
300 operator=(char const* s)
301 {
302 28x value(s, storage()).swap(*this);
303 28x return *this;
304 }
305
306 value&
307 12x value::
308 operator=(string const& str)
309 {
310 12x value(str, storage()).swap(*this);
311 12x return *this;
312 }
313
314 value&
315 7x value::
316 operator=(string&& str)
317 {
318 14x value(std::move(str),
319 7x storage()).swap(*this);
320 7x return *this;
321 }
322
323 value&
324 4x value::
325 operator=(array const& arr)
326 {
327 4x value(arr, storage()).swap(*this);
328 4x return *this;
329 }
330
331 value&
332 21x value::
333 operator=(array&& arr)
334 {
335 42x value(std::move(arr),
336 21x storage()).swap(*this);
337 21x return *this;
338 }
339
340 value&
341 4x value::
342 operator=(object const& obj)
343 {
344 4x value(obj, storage()).swap(*this);
345 4x return *this;
346 }
347
348 value&
349 54x value::
350 operator=(object&& obj)
351 {
352 108x value(std::move(obj),
353 54x storage()).swap(*this);
354 54x return *this;
355 }
356
357 //----------------------------------------------------------
358 //
359 // Accessors
360 //
361 //----------------------------------------------------------
362
363 system::result<array&>
364 16x value::try_as_array() noexcept
365 {
366 16x if( is_array() )
367 9x return arr_;
368
369 7x system::error_code ec;
370 7x BOOST_JSON_FAIL(ec, error::not_array);
371 7x return ec;
372 }
373
374 system::result<array const&>
375 305x value::try_as_array() const noexcept
376 {
377 305x if( is_array() )
378 265x return arr_;
379
380 40x system::error_code ec;
381 40x BOOST_JSON_FAIL(ec, error::not_array);
382 40x return ec;
383 }
384
385 system::result<object&>
386 9x value::try_as_object() noexcept
387 {
388 9x if( is_object() )
389 2x return obj_;
390
391 7x system::error_code ec;
392 7x BOOST_JSON_FAIL(ec, error::not_object);
393 7x return ec;
394 }
395
396 system::result<object const&>
397 282x value::try_as_object() const noexcept
398 {
399 282x if( is_object() )
400 242x return obj_;
401
402 40x system::error_code ec;
403 40x BOOST_JSON_FAIL(ec, error::not_object);
404 40x return ec;
405 }
406
407 system::result<string&>
408 9x value::try_as_string() noexcept
409 {
410 9x if( is_string() )
411 2x return str_;
412
413 7x system::error_code ec;
414 7x BOOST_JSON_FAIL(ec, error::not_string);
415 7x return ec;
416 }
417
418 system::result<string const&>
419 121x value::try_as_string() const noexcept
420 {
421 121x if( is_string() )
422 92x return str_;
423
424 29x system::error_code ec;
425 29x BOOST_JSON_FAIL(ec, error::not_string);
426 29x return ec;
427 }
428
429 system::result<std::int64_t&>
430 52x value::try_as_int64() noexcept
431 {
432 52x if( is_int64() )
433 38x return sca_.i;
434
435 14x system::error_code ec;
436 14x BOOST_JSON_FAIL(ec, error::not_int64);
437 14x return ec;
438 }
439
440 system::result<std::int64_t>
441 33x value::try_as_int64() const noexcept
442 {
443 33x if( is_int64() )
444 19x return sca_.i;
445
446 14x system::error_code ec;
447 14x BOOST_JSON_FAIL(ec, error::not_int64);
448 14x return ec;
449 }
450
451 system::result<std::uint64_t&>
452 16x value::try_as_uint64() noexcept
453 {
454 16x if( is_uint64() )
455 2x return sca_.u;
456
457 14x system::error_code ec;
458 14x BOOST_JSON_FAIL(ec, error::not_uint64);
459 14x return ec;
460 }
461
462 system::result<std::uint64_t>
463 16x value::try_as_uint64() const noexcept
464 {
465 16x if( is_uint64() )
466 2x return sca_.u;
467
468 14x system::error_code ec;
469 14x BOOST_JSON_FAIL(ec, error::not_uint64);
470 14x return ec;
471 }
472
473 system::result<double&>
474 2000657x value::try_as_double() noexcept
475 {
476 2000657x if( is_double() )
477 2000643x return sca_.d;
478
479 14x system::error_code ec;
480 14x BOOST_JSON_FAIL(ec, error::not_double);
481 14x return ec;
482 }
483
484 system::result<double>
485 580x value::try_as_double() const noexcept
486 {
487 580x if( is_double() )
488 566x return sca_.d;
489
490 14x system::error_code ec;
491 14x BOOST_JSON_FAIL(ec, error::not_double);
492 14x return ec;
493 }
494
495 system::result<bool&>
496 19x value::try_as_bool() noexcept
497 {
498 19x if( is_bool() )
499 4x return sca_.b;
500
501 15x system::error_code ec;
502 15x BOOST_JSON_FAIL(ec, error::not_bool);
503 15x return ec;
504 }
505
506 system::result<bool>
507 30x value::try_as_bool() const noexcept
508 {
509 30x if( is_bool() )
510 16x return sca_.b;
511
512 14x system::error_code ec;
513 14x BOOST_JSON_FAIL(ec, error::not_bool);
514 14x return ec;
515 }
516
517 system::result<std::nullptr_t>
518 2x value::try_as_null() const noexcept
519 {
520 2x if( is_null() )
521 1x return nullptr;
522
523 1x system::error_code ec;
524 1x BOOST_JSON_FAIL(ec, error::not_null);
525 1x return ec;
526 }
527
528 boost::system::result<value&>
529 1x value::try_at(string_view key) noexcept
530 {
531 2x return try_as_object() & [key](object& jo) { return jo.try_at(key); };
532 }
533
534 boost::system::result<value const&>
535 3x value::try_at(string_view key) const noexcept
536 {
537 6x return try_as_object()
538 6x & [key](object const& jo) { return jo.try_at(key); };
539 }
540
541 boost::system::result<value&>
542 8x value::try_at(std::size_t pos) noexcept
543 {
544 16x return try_as_array() & [pos](array& ja) { return ja.try_at(pos); };
545 }
546
547 boost::system::result<value const&>
548 2x value::try_at(std::size_t pos) const noexcept
549 {
550 4x return try_as_array() & [pos](array const& ja) { return ja.try_at(pos); };
551 }
552
553 object const&
554 197x value::as_object(source_location const& loc) const&
555 {
556 197x return try_as_object().value(loc);
557 }
558
559 array const&
560 176x value::as_array(source_location const& loc) const&
561 {
562 176x return try_as_array().value(loc);
563 }
564
565 string const&
566 113x value::as_string(source_location const& loc) const&
567 {
568 113x return try_as_string().value(loc);
569 }
570
571 std::int64_t&
572 44x value::as_int64(source_location const& loc)
573 {
574 44x return try_as_int64().value(loc);
575 }
576
577 std::int64_t
578 26x value::as_int64(source_location const& loc) const
579 {
580 26x return try_as_int64().value(loc);
581 }
582
583 std::uint64_t&
584 8x value::as_uint64(source_location const& loc)
585 {
586 8x return try_as_uint64().value(loc);
587 }
588
589 std::uint64_t
590 8x value::as_uint64(source_location const& loc) const
591 {
592 8x return try_as_uint64().value(loc);
593 }
594
595 double&
596 2000649x value::as_double(source_location const& loc)
597 {
598 2000649x return try_as_double().value(loc);
599 }
600
601 double
602 572x value::as_double(source_location const& loc) const
603 {
604 572x return try_as_double().value(loc);
605 }
606
607 bool&
608 10x value::as_bool(source_location const& loc)
609 {
610 10x return try_as_bool().value(loc);
611 }
612
613 bool
614 22x value::as_bool(source_location const& loc) const
615 {
616 22x return try_as_bool().value(loc);
617 }
618
619 //----------------------------------------------------------
620 //
621 // Modifiers
622 //
623 //----------------------------------------------------------
624
625 string&
626 99x value::
627 emplace_string() noexcept
628 {
629 99x storage_ptr sp = destroy();
630 99x return *::new(&str_) string(sp);
631 99x }
632
633 array&
634 250x value::
635 emplace_array() noexcept
636 {
637 250x storage_ptr sp = destroy();
638 250x return *::new(&arr_) array(sp);
639 250x }
640
641 object&
642 56x value::
643 emplace_object() noexcept
644 {
645 56x storage_ptr sp = destroy();
646 56x return *::new(&obj_) object(sp);
647 56x }
648
649 void
650 259x value::
651 swap(value& other)
652 {
653 259x if(*storage() == *other.storage())
654 {
655 // fast path
656 union U
657 {
658 value tmp;
659 258x U(){}
660 258x ~U(){}
661 };
662 258x U u;
663 258x relocate(&u.tmp, *this);
664 258x relocate(this, other);
665 258x relocate(&other, u.tmp);
666 258x return;
667 258x }
668
669 // copy
670 value temp1(
671 1x std::move(*this),
672 2x other.storage());
673 value temp2(
674 1x std::move(other),
675 2x this->storage());
676 1x other.~value();
677 1x ::new(&other) value(pilfer(temp1));
678 1x this->~value();
679 1x ::new(this) value(pilfer(temp2));
680 1x }
681
682 std::istream&
683 10x operator>>(
684 std::istream& is,
685 value& jv)
686 {
687 using Traits = std::istream::traits_type;
688
689 // sentry prepares the stream for reading and finalizes it in destructor
690 10x std::istream::sentry sentry(is);
691 10x if( !sentry )
692 1x return is;
693
694 9x parse_options opts = get_parse_options( is );
695 9x if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
696 3x opts.max_depth = depth;
697
698 unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
699 9x stream_parser p( {}, opts, parser_buf );
700 9x p.reset( jv.storage() );
701
702 char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
703 9x std::streambuf& buf = *is.rdbuf();
704 9x std::ios::iostate err = std::ios::goodbit;
705 #ifndef BOOST_NO_EXCEPTIONS
706 try
707 #endif
708 {
709 while( true )
710 {
711 15x system::error_code ec;
712
713 // we peek the buffer; this either makes sure that there's no
714 // more input, or makes sure there's something in the internal
715 // buffer (so in_avail will return a positive number)
716 15x std::istream::int_type c = is.rdbuf()->sgetc();
717 // if we indeed reached EOF, we check if we parsed a full JSON
718 // document; if not, we error out
719 13x if( Traits::eq_int_type(c, Traits::eof()) )
720 {
721 3x err |= std::ios::eofbit;
722 3x p.finish(ec);
723 3x if( ec.failed() )
724 4x break;
725 }
726
727 // regardless of reaching EOF, we might have parsed a full JSON
728 // document; if so, we successfully finish
729 12x if( p.done() )
730 {
731 3x jv = p.release();
732 3x return is;
733 }
734
735 // at this point we definitely have more input, specifically in
736 // buf's internal buffer; we also definitely haven't parsed a whole
737 // document
738 9x std::streamsize available = buf.in_avail();
739 // if this assert fails, the streambuf is buggy
740 9x BOOST_ASSERT( available > 0 );
741
742 18x available = ( std::min )(
743 9x static_cast<std::size_t>(available), sizeof(read_buf) );
744 // we read from the internal buffer of buf into our buffer
745 9x available = buf.sgetn( read_buf, available );
746
747 9x std::size_t consumed = p.write_some(
748 read_buf, static_cast<std::size_t>(available), ec );
749 // if the parser hasn't consumed the entire input we've took from
750 // buf, we put the remaining data back; this should succeed,
751 // because we only read data from buf's internal buffer
752 21x while( consumed++ < static_cast<std::size_t>(available) )
753 {
754 12x std::istream::int_type const status = buf.sungetc();
755 12x BOOST_ASSERT( status != Traits::eof() );
756 (void)status;
757 }
758
759 9x if( ec.failed() )
760 3x break;
761 6x }
762 }
763 #ifndef BOOST_NO_EXCEPTIONS
764 2x catch(...)
765 {
766 try
767 {
768 2x is.setstate(std::ios::badbit);
769 }
770 // we ignore the exception, because we need to throw the original
771 // exception instead
772 1x catch( std::ios::failure const& ) { }
773
774 2x if( is.exceptions() & std::ios::badbit )
775 1x throw;
776 2x }
777 #endif
778
779 5x is.setstate(err | std::ios::failbit);
780 5x return is;
781 9x }
782
783 std::istream&
784 3x operator>>(
785 std::istream& is,
786 parse_options const& opts)
787 {
788 3x is.iword(parse_flags_xalloc) = to_bitmask(opts);
789 3x is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
790 3x return is;
791 }
792
793 //----------------------------------------------------------
794 //
795 // private
796 //
797 //----------------------------------------------------------
798
799 storage_ptr
800 423x value::
801 destroy() noexcept
802 {
803 423x switch(kind())
804 {
805 404x case json::kind::null:
806 case json::kind::bool_:
807 case json::kind::int64:
808 case json::kind::uint64:
809 case json::kind::double_:
810 404x break;
811
812 14x case json::kind::string:
813 {
814 14x auto sp = str_.storage();
815 14x str_.~string();
816 14x return sp;
817 14x }
818
819 2x case json::kind::array:
820 {
821 2x auto sp = arr_.storage();
822 2x arr_.~array();
823 2x return sp;
824 2x }
825
826 3x case json::kind::object:
827 {
828 3x auto sp = obj_.storage();
829 3x obj_.~object();
830 3x return sp;
831 3x }
832
833 }
834 404x return std::move(sp_);
835 }
836
837 bool
838 4172x value::
839 equal(value const& other) const noexcept
840 {
841 4172x switch(kind())
842 {
843 21x default: // unreachable()?
844 case json::kind::null:
845 21x return other.kind() == json::kind::null;
846
847 17x case json::kind::bool_:
848 return
849 27x other.kind() == json::kind::bool_ &&
850 27x get_bool() == other.get_bool();
851
852 3943x case json::kind::int64:
853 3943x switch(other.kind())
854 {
855 3916x case json::kind::int64:
856 3916x return get_int64() == other.get_int64();
857 26x case json::kind::uint64:
858 26x if(get_int64() < 0)
859 1x return false;
860 25x return static_cast<std::uint64_t>(
861 25x get_int64()) == other.get_uint64();
862 1x default:
863 1x return false;
864 }
865
866 7x case json::kind::uint64:
867 7x switch(other.kind())
868 {
869 2x case json::kind::uint64:
870 2x return get_uint64() == other.get_uint64();
871 3x case json::kind::int64:
872 3x if(other.get_int64() < 0)
873 2x return false;
874 1x return static_cast<std::uint64_t>(
875 1x other.get_int64()) == get_uint64();
876 2x default:
877 2x return false;
878 }
879
880 55x case json::kind::double_:
881 return
882 108x other.kind() == json::kind::double_ &&
883 108x get_double() == other.get_double();
884
885 47x case json::kind::string:
886 return
887 91x other.kind() == json::kind::string &&
888 91x get_string() == other.get_string();
889
890 62x case json::kind::array:
891 return
892 122x other.kind() == json::kind::array &&
893 122x get_array() == other.get_array();
894
895 20x case json::kind::object:
896 return
897 37x other.kind() == json::kind::object &&
898 37x get_object() == other.get_object();
899 }
900 }
901
902 //----------------------------------------------------------
903 //
904 // key_value_pair
905 //
906 //----------------------------------------------------------
907
908 // empty keys point here
909 BOOST_JSON_REQUIRE_CONST_INIT
910 char const
911 key_value_pair::empty_[1] = { 0 };
912
913 38150x key_value_pair::
914 key_value_pair(
915 pilfered<json::value> key,
916 38150x pilfered<json::value> value) noexcept
917 38150x : value_(value)
918 {
919 std::size_t len;
920 38150x key_ = access::release_key(key.get(), len);
921 38150x len_ = static_cast<std::uint32_t>(len);
922 38150x }
923
924 6858x key_value_pair::
925 key_value_pair(
926 key_value_pair const& other,
927 6858x storage_ptr sp)
928 6862x : value_(other.value_, std::move(sp))
929 {
930 auto p = reinterpret_cast<
931 6854x char*>(value_.storage()->
932 6854x allocate(other.len_ + 1,
933 alignof(char)));
934 6596x std::memcpy(
935 6596x p, other.key_, other.len_);
936 6596x len_ = other.len_;
937 6596x p[len_] = 0;
938 6596x key_ = p;
939 6854x }
940
941 //----------------------------------------------------------
942
943 namespace detail
944 {
945
946 std::size_t
947 248x hash_value_impl( value const& jv ) noexcept
948 {
949 248x std::size_t seed = 0;
950
951 248x kind const k = jv.kind();
952 248x boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
953
954 248x visit( value_hasher{seed}, jv );
955 248x return seed;
956 }
957
958 } // namespace detail
959 } // namespace json
960 } // namespace boost
961
962 //----------------------------------------------------------
963 //
964 // std::hash specialization
965 //
966 //----------------------------------------------------------
967
968 std::size_t
969 62x std::hash<::boost::json::value>::operator()(
970 ::boost::json::value const& jv) const noexcept
971 {
972 62x return ::boost::hash< ::boost::json::value >()( jv );
973 }
974
975 //----------------------------------------------------------
976
977 #endif
978