impl/value.ipp

98.8% Lines (477/483) 100.0% List of functions (70/70)
f(x) Functions (70)
Function Calls Lines Branches 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 2178636x 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 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 98x 100.0% 100.0% boost::json::value::emplace_array() :644 249x 100.0% 100.0% boost::json::value::emplace_object() :651 55x 100.0% 100.0% boost::json::value::swap(boost::json::value&) :658 259x 100.0% 81.0% boost::json::value::swap(boost::json::value&)::U::U() :667 258x 100.0% 100.0% boost::json::value::swap(boost::json::value&)::U::~U() :668 258x 100.0% 100.0% boost::json::operator>>(std::istream&, boost::json::value&) :691 10x 100.0% 92.0% boost::json::operator>>(std::istream&, boost::json::parse_options const&) :792 3x 100.0% 100.0% boost::json::value::destroy() :808 420x 100.0% 100.0% boost::json::value::equal(boost::json::value const&) const :846 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>) :921 38150x 100.0% 100.0% boost::json::key_value_pair::key_value_pair(boost::json::key_value_pair const&, boost::json::storage_ptr) :932 6858x 100.0% 100.0% boost::json::detail::hash_value_impl(boost::json::value const&) :955 248x 100.0% 100.0% std::hash<boost::json::value>::operator()(boost::json::value const&) const :977 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 2178636x value::
81 ~value() noexcept
82 {
83 2178636x 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 27376x case json::kind::string:
94 27376x str_.~string();
95 27376x break;
96
97 3087x case json::kind::array:
98 3087x arr_.~array();
99 3087x break;
100
101 35204x case json::kind::object:
102 35204x obj_.~object();
103 35204x break;
104 }
105 2178636x }
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 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 98x value::
638 emplace_string() noexcept
639 {
640 98x return *::new(&str_) string(destroy());
641 }
642
643 array&
644 249x value::
645 emplace_array() noexcept
646 {
647 249x return *::new(&arr_) array(destroy());
648 }
649
650 object&
651 55x value::
652 emplace_object() noexcept
653 {
654 55x return *::new(&obj_) object(destroy());
655 }
656
657 void
658 259x value::
659 swap(value& other)
660 {
661 259x if(*storage() == *other.storage())
662 {
663 // fast path
664 union U
665 {
666 value tmp;
667 258x U(){}
668 258x ~U(){}
669 };
670 258x U u;
671 258x relocate(&u.tmp, *this);
672 258x relocate(this, other);
673 258x relocate(&other, u.tmp);
674 258x return;
675 258x }
676
677 // copy
678 value temp1(
679 1x std::move(*this),
680 2x other.storage());
681 value temp2(
682 1x std::move(other),
683 2x this->storage());
684 1x other.~value();
685 1x ::new(&other) value(pilfer(temp1));
686 1x this->~value();
687 1x ::new(this) value(pilfer(temp2));
688 1x }
689
690 std::istream&
691 10x operator>>(
692 std::istream& is,
693 value& jv)
694 {
695 using Traits = std::istream::traits_type;
696
697 // sentry prepares the stream for reading and finalizes it in destructor
698 10x std::istream::sentry sentry(is);
699 10x if( !sentry )
700 1x return is;
701
702 9x parse_options opts = get_parse_options( is );
703 9x if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
704 3x opts.max_depth = depth;
705
706 unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
707 9x stream_parser p( {}, opts, parser_buf );
708 9x p.reset( jv.storage() );
709
710 char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
711 9x std::streambuf& buf = *is.rdbuf();
712 9x std::ios::iostate err = std::ios::goodbit;
713 #ifndef BOOST_NO_EXCEPTIONS
714 try
715 #endif
716 {
717 while( true )
718 {
719 15x system::error_code ec;
720
721 // we peek the buffer; this either makes sure that there's no
722 // more input, or makes sure there's something in the internal
723 // buffer (so in_avail will return a positive number)
724 15x std::istream::int_type c = is.rdbuf()->sgetc();
725 // if we indeed reached EOF, we check if we parsed a full JSON
726 // document; if not, we error out
727 13x if( Traits::eq_int_type(c, Traits::eof()) )
728 {
729 3x err |= std::ios::eofbit;
730 3x p.finish(ec);
731 3x if( ec.failed() )
732 4x break;
733 }
734
735 // regardless of reaching EOF, we might have parsed a full JSON
736 // document; if so, we successfully finish
737 12x if( p.done() )
738 {
739 3x jv = p.release();
740 3x return is;
741 }
742
743 // at this point we definitely have more input, specifically in
744 // buf's internal buffer; we also definitely haven't parsed a whole
745 // document
746 9x std::streamsize available = buf.in_avail();
747 // if this assert fails, the streambuf is buggy
748 9x BOOST_ASSERT( available > 0 );
749
750 18x available = ( std::min )(
751 9x static_cast<std::size_t>(available), sizeof(read_buf) );
752 // we read from the internal buffer of buf into our buffer
753 9x available = buf.sgetn( read_buf, available );
754
755 9x std::size_t consumed = p.write_some(
756 read_buf, static_cast<std::size_t>(available), ec );
757 // if the parser hasn't consumed the entire input we've took from
758 // buf, we put the remaining data back; this should succeed,
759 // because we only read data from buf's internal buffer
760 21x while( consumed++ < static_cast<std::size_t>(available) )
761 {
762 12x std::istream::int_type const status = buf.sungetc();
763 12x BOOST_ASSERT( status != Traits::eof() );
764 (void)status;
765 }
766
767 9x if( ec.failed() )
768 3x break;
769 6x }
770 }
771 #ifndef BOOST_NO_EXCEPTIONS
772 2x catch(...)
773 {
774 try
775 {
776 2x is.setstate(std::ios::badbit);
777 }
778 // we ignore the exception, because we need to throw the original
779 // exception instead
780 1x catch( std::ios::failure const& ) { }
781
782 2x if( is.exceptions() & std::ios::badbit )
783 1x throw;
784 2x }
785 #endif
786
787 5x is.setstate(err | std::ios::failbit);
788 5x return is;
789 9x }
790
791 std::istream&
792 3x operator>>(
793 std::istream& is,
794 parse_options const& opts)
795 {
796 3x is.iword(parse_flags_xalloc) = to_bitmask(opts);
797 3x is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
798 3x return is;
799 }
800
801 //----------------------------------------------------------
802 //
803 // private
804 //
805 //----------------------------------------------------------
806
807 storage_ptr
808 420x value::
809 destroy() noexcept
810 {
811 420x switch(kind())
812 {
813 401x case json::kind::null:
814 case json::kind::bool_:
815 case json::kind::int64:
816 case json::kind::uint64:
817 case json::kind::double_:
818 401x break;
819
820 14x case json::kind::string:
821 {
822 14x auto sp = str_.storage();
823 14x str_.~string();
824 14x return sp;
825 14x }
826
827 2x case json::kind::array:
828 {
829 2x auto sp = arr_.storage();
830 2x arr_.~array();
831 2x return sp;
832 2x }
833
834 3x case json::kind::object:
835 {
836 3x auto sp = obj_.storage();
837 3x obj_.~object();
838 3x return sp;
839 3x }
840
841 }
842 401x return std::move(sp_);
843 }
844
845 bool
846 4172x value::
847 equal(value const& other) const noexcept
848 {
849 4172x switch(kind())
850 {
851 21x default: // unreachable()?
852 case json::kind::null:
853 21x return other.kind() == json::kind::null;
854
855 17x case json::kind::bool_:
856 return
857 27x other.kind() == json::kind::bool_ &&
858 27x get_bool() == other.get_bool();
859
860 3943x case json::kind::int64:
861 3943x switch(other.kind())
862 {
863 3916x case json::kind::int64:
864 3916x return get_int64() == other.get_int64();
865 26x case json::kind::uint64:
866 26x if(get_int64() < 0)
867 1x return false;
868 25x return static_cast<std::uint64_t>(
869 25x get_int64()) == other.get_uint64();
870 1x default:
871 1x return false;
872 }
873
874 7x case json::kind::uint64:
875 7x switch(other.kind())
876 {
877 2x case json::kind::uint64:
878 2x return get_uint64() == other.get_uint64();
879 3x case json::kind::int64:
880 3x if(other.get_int64() < 0)
881 2x return false;
882 1x return static_cast<std::uint64_t>(
883 1x other.get_int64()) == get_uint64();
884 2x default:
885 2x return false;
886 }
887
888 55x case json::kind::double_:
889 return
890 108x other.kind() == json::kind::double_ &&
891 108x get_double() == other.get_double();
892
893 47x case json::kind::string:
894 return
895 91x other.kind() == json::kind::string &&
896 91x get_string() == other.get_string();
897
898 62x case json::kind::array:
899 return
900 122x other.kind() == json::kind::array &&
901 122x get_array() == other.get_array();
902
903 20x case json::kind::object:
904 return
905 37x other.kind() == json::kind::object &&
906 37x get_object() == other.get_object();
907 }
908 }
909
910 //----------------------------------------------------------
911 //
912 // key_value_pair
913 //
914 //----------------------------------------------------------
915
916 // empty keys point here
917 BOOST_JSON_REQUIRE_CONST_INIT
918 char const
919 key_value_pair::empty_[1] = { 0 };
920
921 38150x key_value_pair::
922 key_value_pair(
923 pilfered<json::value> key,
924 38150x pilfered<json::value> value) noexcept
925 38150x : value_(value)
926 {
927 std::size_t len;
928 38150x key_ = access::release_key(key.get(), len);
929 38150x len_ = static_cast<std::uint32_t>(len);
930 38150x }
931
932 6858x key_value_pair::
933 key_value_pair(
934 key_value_pair const& other,
935 6858x storage_ptr sp)
936 6862x : value_(other.value_, std::move(sp))
937 {
938 auto p = reinterpret_cast<
939 6854x char*>(value_.storage()->
940 6854x allocate(other.len_ + 1,
941 alignof(char)));
942 6596x std::memcpy(
943 6596x p, other.key_, other.len_);
944 6596x len_ = other.len_;
945 6596x p[len_] = 0;
946 6596x key_ = p;
947 6854x }
948
949 //----------------------------------------------------------
950
951 namespace detail
952 {
953
954 std::size_t
955 248x hash_value_impl( value const& jv ) noexcept
956 {
957 248x std::size_t seed = 0;
958
959 248x kind const k = jv.kind();
960 248x boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
961
962 248x visit( value_hasher{seed}, jv );
963 248x return seed;
964 }
965
966 } // namespace detail
967 } // namespace json
968 } // namespace boost
969
970 //----------------------------------------------------------
971 //
972 // std::hash specialization
973 //
974 //----------------------------------------------------------
975
976 std::size_t
977 62x std::hash<::boost::json::value>::operator()(
978 ::boost::json::value const& jv) const noexcept
979 {
980 62x return ::boost::hash< ::boost::json::value >()( jv );
981 }
982
983 //----------------------------------------------------------
984
985 #endif
986