impl/value.ipp

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