impl/value.ipp

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