impl/value.ipp

98.7% Lines (462/468) 100.0% List of functions (70/70)
value.ipp
f(x) Functions (70)
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 2179054x 100.0% 100.0% boost::json::value::value(boost::json::value const&, boost::json::storage_ptr) :107 9741x 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 186x 100.0% 100.0% boost::json::value::try_as_object() :386 9x 100.0% 100.0% boost::json::value::try_as_object() const :397 208x 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 80.0% 70.0% boost::json::value::try_at(boost::core::basic_string_view<char>) const :538 3x 80.0% 70.0% boost::json::value::try_at(unsigned long) :547 8x 80.0% 70.0% boost::json::value::try_at(unsigned long) const :556 2x 80.0% 70.0% boost::json::value::as_object(boost::source_location const&) const & :565 197x 100.0% 100.0% boost::json::value::as_array(boost::source_location const&) const & :571 176x 100.0% 100.0% boost::json::value::as_string(boost::source_location const&) const & :577 113x 100.0% 100.0% boost::json::value::as_int64(boost::source_location const&) :583 44x 100.0% 100.0% boost::json::value::as_int64(boost::source_location const&) const :589 26x 100.0% 100.0% boost::json::value::as_uint64(boost::source_location const&) :595 8x 100.0% 100.0% boost::json::value::as_uint64(boost::source_location const&) const :601 8x 100.0% 100.0% boost::json::value::as_double(boost::source_location const&) :607 2000649x 100.0% 100.0% boost::json::value::as_double(boost::source_location const&) const :613 572x 100.0% 100.0% boost::json::value::as_bool(boost::source_location const&) :619 10x 100.0% 100.0% boost::json::value::as_bool(boost::source_location const&) const :625 22x 100.0% 100.0% boost::json::value::emplace_string() :637 99x 100.0% 100.0% boost::json::value::emplace_array() :645 250x 100.0% 100.0% boost::json::value::emplace_object() :653 56x 100.0% 100.0% boost::json::value::swap(boost::json::value&) :661 259x 100.0% 81.0% boost::json::value::swap(boost::json::value&)::U::U() :670 258x 100.0% 100.0% boost::json::value::swap(boost::json::value&)::U::~U() :671 258x 100.0% 100.0% boost::json::operator>>(std::istream&, boost::json::value&) :694 10x 100.0% 92.0% boost::json::operator>>(std::istream&, boost::json::parse_options const&) :795 3x 100.0% 100.0% boost::json::value::destroy() :811 423x 100.0% 100.0% boost::json::value::equal(boost::json::value const&) const :849 4276x 100.0% 100.0% boost::json::key_value_pair::key_value_pair(boost::json::pilfered<boost::json::value>, boost::json::pilfered<boost::json::value>) :924 38261x 100.0% 100.0% boost::json::key_value_pair::key_value_pair(boost::json::key_value_pair const&, boost::json::storage_ptr) :935 7054x 100.0% 100.0% boost::json::detail::hash_value_impl(boost::json::value const&) :958 248x 100.0% 100.0% std::hash<boost::json::value>::operator()(boost::json::value const&) const :980 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 2179054x value::
81 ~value() noexcept
82 {
83 2179054x switch(kind())
84 {
85 2113086x 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 2113086x sca_.~scalar();
91 2113086x break;
92
93 27491x case json::kind::string:
94 27491x str_.~string();
95 27491x break;
96
97 3151x case json::kind::array:
98 3151x arr_.~array();
99 3151x break;
100
101 35326x case json::kind::object:
102 35326x obj_.~object();
103 35326x break;
104 }
105 2179054x }
106
107 9741x value::
108 value(
109 value const& other,
110 9741x storage_ptr sp)
111 {
112 9741x 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 7084x case json::kind::int64:
126 21252x ::new(&sca_) scalar(
127 7084x other.sca_.i,
128 7084x std::move(sp));
129 7084x 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 205x case json::kind::string:
144 17x ::new(&str_) string(
145 205x other.str_,
146 239x std::move(sp));
147 188x break;
148
149 155x case json::kind::array:
150 26x ::new(&arr_) array(
151 155x other.arr_,
152 207x std::move(sp));
153 129x break;
154
155 95x case json::kind::object:
156 10x ::new(&obj_) object(
157 95x other.obj_,
158 115x std::move(sp));
159 85x break;
160 }
161 9688x }
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 186x value::try_as_array() const noexcept
376 {
377 186x if( is_array() )
378 158x return arr_;
379
380 28x system::error_code ec;
381 28x BOOST_JSON_FAIL(ec, error::not_array);
382 28x 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 208x value::try_as_object() const noexcept
398 {
399 208x if( is_object() )
400 180x return obj_;
401
402 28x system::error_code ec;
403 28x BOOST_JSON_FAIL(ec, error::not_object);
404 28x 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 1x auto r = try_as_object();
532 1x if( !r )
533 return r.error();
534 1x return r->try_at(key);
535 }
536
537 boost::system::result<value const&>
538 3x value::try_at(string_view key) const noexcept
539 {
540 3x auto r = try_as_object();
541 3x if( !r )
542 return r.error();
543 3x return r->try_at(key);
544 }
545
546 boost::system::result<value&>
547 8x value::try_at(std::size_t pos) noexcept
548 {
549 8x auto r = try_as_array();
550 8x if( !r )
551 return r.error();
552 8x return r->try_at(pos);
553 }
554
555 boost::system::result<value const&>
556 2x value::try_at(std::size_t pos) const noexcept
557 {
558 2x auto r = try_as_array();
559 2x if( !r )
560 return r.error();
561 2x return r->try_at(pos);
562 }
563
564 object const&
565 197x value::as_object(source_location const& loc) const&
566 {
567 197x return try_as_object().value(loc);
568 }
569
570 array const&
571 176x value::as_array(source_location const& loc) const&
572 {
573 176x return try_as_array().value(loc);
574 }
575
576 string const&
577 113x value::as_string(source_location const& loc) const&
578 {
579 113x return try_as_string().value(loc);
580 }
581
582 std::int64_t&
583 44x value::as_int64(source_location const& loc)
584 {
585 44x return try_as_int64().value(loc);
586 }
587
588 std::int64_t
589 26x value::as_int64(source_location const& loc) const
590 {
591 26x return try_as_int64().value(loc);
592 }
593
594 std::uint64_t&
595 8x value::as_uint64(source_location const& loc)
596 {
597 8x return try_as_uint64().value(loc);
598 }
599
600 std::uint64_t
601 8x value::as_uint64(source_location const& loc) const
602 {
603 8x return try_as_uint64().value(loc);
604 }
605
606 double&
607 2000649x value::as_double(source_location const& loc)
608 {
609 2000649x return try_as_double().value(loc);
610 }
611
612 double
613 572x value::as_double(source_location const& loc) const
614 {
615 572x return try_as_double().value(loc);
616 }
617
618 bool&
619 10x value::as_bool(source_location const& loc)
620 {
621 10x return try_as_bool().value(loc);
622 }
623
624 bool
625 22x value::as_bool(source_location const& loc) const
626 {
627 22x return try_as_bool().value(loc);
628 }
629
630 //----------------------------------------------------------
631 //
632 // Modifiers
633 //
634 //----------------------------------------------------------
635
636 string&
637 99x value::
638 emplace_string() noexcept
639 {
640 99x storage_ptr sp = destroy();
641 99x return *::new(&str_) string(sp);
642 99x }
643
644 array&
645 250x value::
646 emplace_array() noexcept
647 {
648 250x storage_ptr sp = destroy();
649 250x return *::new(&arr_) array(sp);
650 250x }
651
652 object&
653 56x value::
654 emplace_object() noexcept
655 {
656 56x storage_ptr sp = destroy();
657 56x return *::new(&obj_) object(sp);
658 56x }
659
660 void
661 259x value::
662 swap(value& other)
663 {
664 259x if(*storage() == *other.storage())
665 {
666 // fast path
667 union U
668 {
669 value tmp;
670 258x U(){}
671 258x ~U(){}
672 };
673 258x U u;
674 258x relocate(&u.tmp, *this);
675 258x relocate(this, other);
676 258x relocate(&other, u.tmp);
677 258x return;
678 258x }
679
680 // copy
681 value temp1(
682 1x std::move(*this),
683 2x other.storage());
684 value temp2(
685 1x std::move(other),
686 2x this->storage());
687 1x other.~value();
688 1x ::new(&other) value(pilfer(temp1));
689 1x this->~value();
690 1x ::new(this) value(pilfer(temp2));
691 1x }
692
693 std::istream&
694 10x operator>>(
695 std::istream& is,
696 value& jv)
697 {
698 using Traits = std::istream::traits_type;
699
700 // sentry prepares the stream for reading and finalizes it in destructor
701 10x std::istream::sentry sentry(is);
702 10x if( !sentry )
703 1x return is;
704
705 9x parse_options opts = get_parse_options( is );
706 9x if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
707 3x opts.max_depth = depth;
708
709 unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
710 9x stream_parser p( {}, opts, parser_buf );
711 9x p.reset( jv.storage() );
712
713 char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
714 9x std::streambuf& buf = *is.rdbuf();
715 9x std::ios::iostate err = std::ios::goodbit;
716 #ifndef BOOST_NO_EXCEPTIONS
717 try
718 #endif
719 {
720 while( true )
721 {
722 15x system::error_code ec;
723
724 // we peek the buffer; this either makes sure that there's no
725 // more input, or makes sure there's something in the internal
726 // buffer (so in_avail will return a positive number)
727 15x std::istream::int_type c = is.rdbuf()->sgetc();
728 // if we indeed reached EOF, we check if we parsed a full JSON
729 // document; if not, we error out
730 13x if( Traits::eq_int_type(c, Traits::eof()) )
731 {
732 3x err |= std::ios::eofbit;
733 3x p.finish(ec);
734 3x if( ec.failed() )
735 4x break;
736 }
737
738 // regardless of reaching EOF, we might have parsed a full JSON
739 // document; if so, we successfully finish
740 12x if( p.done() )
741 {
742 3x jv = p.release();
743 3x return is;
744 }
745
746 // at this point we definitely have more input, specifically in
747 // buf's internal buffer; we also definitely haven't parsed a whole
748 // document
749 9x std::streamsize available = buf.in_avail();
750 // if this assert fails, the streambuf is buggy
751 9x BOOST_ASSERT( available > 0 );
752
753 18x available = ( std::min )(
754 9x static_cast<std::size_t>(available), sizeof(read_buf) );
755 // we read from the internal buffer of buf into our buffer
756 9x available = buf.sgetn( read_buf, available );
757
758 9x std::size_t consumed = p.write_some(
759 read_buf, static_cast<std::size_t>(available), ec );
760 // if the parser hasn't consumed the entire input we've took from
761 // buf, we put the remaining data back; this should succeed,
762 // because we only read data from buf's internal buffer
763 21x while( consumed++ < static_cast<std::size_t>(available) )
764 {
765 12x std::istream::int_type const status = buf.sungetc();
766 12x BOOST_ASSERT( status != Traits::eof() );
767 (void)status;
768 }
769
770 9x if( ec.failed() )
771 3x break;
772 6x }
773 }
774 #ifndef BOOST_NO_EXCEPTIONS
775 2x catch(...)
776 {
777 try
778 {
779 2x is.setstate(std::ios::badbit);
780 }
781 // we ignore the exception, because we need to throw the original
782 // exception instead
783 1x catch( std::ios::failure const& ) { }
784
785 2x if( is.exceptions() & std::ios::badbit )
786 1x throw;
787 2x }
788 #endif
789
790 5x is.setstate(err | std::ios::failbit);
791 5x return is;
792 9x }
793
794 std::istream&
795 3x operator>>(
796 std::istream& is,
797 parse_options const& opts)
798 {
799 3x is.iword(parse_flags_xalloc) = to_bitmask(opts);
800 3x is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
801 3x return is;
802 }
803
804 //----------------------------------------------------------
805 //
806 // private
807 //
808 //----------------------------------------------------------
809
810 storage_ptr
811 423x value::
812 destroy() noexcept
813 {
814 423x switch(kind())
815 {
816 404x case json::kind::null:
817 case json::kind::bool_:
818 case json::kind::int64:
819 case json::kind::uint64:
820 case json::kind::double_:
821 404x break;
822
823 14x case json::kind::string:
824 {
825 14x auto sp = str_.storage();
826 14x str_.~string();
827 14x return sp;
828 14x }
829
830 2x case json::kind::array:
831 {
832 2x auto sp = arr_.storage();
833 2x arr_.~array();
834 2x return sp;
835 2x }
836
837 3x case json::kind::object:
838 {
839 3x auto sp = obj_.storage();
840 3x obj_.~object();
841 3x return sp;
842 3x }
843
844 }
845 404x return std::move(sp_);
846 }
847
848 bool
849 4276x value::
850 equal(value const& other) const noexcept
851 {
852 4276x switch(kind())
853 {
854 21x default: // unreachable()?
855 case json::kind::null:
856 21x return other.kind() == json::kind::null;
857
858 17x case json::kind::bool_:
859 return
860 27x other.kind() == json::kind::bool_ &&
861 27x get_bool() == other.get_bool();
862
863 3967x case json::kind::int64:
864 3967x switch(other.kind())
865 {
866 3940x case json::kind::int64:
867 3940x return get_int64() == other.get_int64();
868 26x case json::kind::uint64:
869 26x if(get_int64() < 0)
870 1x return false;
871 25x return static_cast<std::uint64_t>(
872 25x get_int64()) == other.get_uint64();
873 1x default:
874 1x return false;
875 }
876
877 7x case json::kind::uint64:
878 7x switch(other.kind())
879 {
880 2x case json::kind::uint64:
881 2x return get_uint64() == other.get_uint64();
882 3x case json::kind::int64:
883 3x if(other.get_int64() < 0)
884 2x return false;
885 1x return static_cast<std::uint64_t>(
886 1x other.get_int64()) == get_uint64();
887 2x default:
888 2x return false;
889 }
890
891 55x case json::kind::double_:
892 return
893 108x other.kind() == json::kind::double_ &&
894 108x get_double() == other.get_double();
895
896 70x case json::kind::string:
897 return
898 137x other.kind() == json::kind::string &&
899 137x get_string() == other.get_string();
900
901 82x case json::kind::array:
902 return
903 162x other.kind() == json::kind::array &&
904 162x get_array() == other.get_array();
905
906 57x case json::kind::object:
907 return
908 111x other.kind() == json::kind::object &&
909 111x get_object() == other.get_object();
910 }
911 }
912
913 //----------------------------------------------------------
914 //
915 // key_value_pair
916 //
917 //----------------------------------------------------------
918
919 // empty keys point here
920 BOOST_JSON_REQUIRE_CONST_INIT
921 char const
922 key_value_pair::empty_[1] = { 0 };
923
924 38261x key_value_pair::
925 key_value_pair(
926 pilfered<json::value> key,
927 38261x pilfered<json::value> value) noexcept
928 38261x : value_(value)
929 {
930 std::size_t len;
931 38261x key_ = access::release_key(key.get(), len);
932 38261x len_ = static_cast<std::uint32_t>(len);
933 38261x }
934
935 7054x key_value_pair::
936 key_value_pair(
937 key_value_pair const& other,
938 7054x storage_ptr sp)
939 7058x : value_(other.value_, std::move(sp))
940 {
941 auto p = reinterpret_cast<
942 7050x char*>(value_.storage()->
943 7050x allocate(other.len_ + 1,
944 alignof(char)));
945 6792x std::memcpy(
946 6792x p, other.key_, other.len_);
947 6792x len_ = other.len_;
948 6792x p[len_] = 0;
949 6792x key_ = p;
950 7050x }
951
952 //----------------------------------------------------------
953
954 namespace detail
955 {
956
957 std::size_t
958 248x hash_value_impl( value const& jv ) noexcept
959 {
960 248x std::size_t seed = 0;
961
962 248x kind const k = jv.kind();
963 248x boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
964
965 248x visit( value_hasher{seed}, jv );
966 248x return seed;
967 }
968
969 } // namespace detail
970 } // namespace json
971 } // namespace boost
972
973 //----------------------------------------------------------
974 //
975 // std::hash specialization
976 //
977 //----------------------------------------------------------
978
979 std::size_t
980 62x std::hash<::boost::json::value>::operator()(
981 ::boost::json::value const& jv) const noexcept
982 {
983 62x return ::boost::hash< ::boost::json::value >()( jv );
984 }
985
986 //----------------------------------------------------------
987
988 #endif
989