Coverage Report

Created: 2023-06-07 06:25

/src/boost/boost/json/value.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4
//
5
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
//
8
// Official repository: https://github.com/boostorg/json
9
//
10
11
#ifndef BOOST_JSON_VALUE_HPP
12
#define BOOST_JSON_VALUE_HPP
13
14
#include <boost/json/detail/config.hpp>
15
#include <boost/json/array.hpp>
16
#include <boost/json/kind.hpp>
17
#include <boost/json/object.hpp>
18
#include <boost/json/pilfer.hpp>
19
#include <boost/json/set_pointer_options.hpp>
20
#include <boost/json/storage_ptr.hpp>
21
#include <boost/json/string.hpp>
22
#include <boost/json/string_view.hpp>
23
#include <boost/json/value_ref.hpp>
24
#include <boost/json/detail/except.hpp>
25
#include <boost/json/detail/value.hpp>
26
#include <cstdlib>
27
#include <cstring>
28
#include <initializer_list>
29
#include <iosfwd>
30
#include <limits>
31
#include <new>
32
#include <type_traits>
33
#include <utility>
34
35
namespace boost {
36
namespace json {
37
38
//----------------------------------------------------------
39
40
/** The type used to represent any JSON value
41
42
    This is a
43
    <a href="https://en.cppreference.com/w/cpp/concepts/regular"><em>Regular</em></a>
44
    type which works like
45
    a variant of the basic JSON data types: array,
46
    object, string, number, boolean, and null.
47
48
    @par Thread Safety
49
50
    Distinct instances may be accessed concurrently.
51
    Non-const member functions of a shared instance
52
    may not be called concurrently with any other
53
    member functions of that instance.
54
*/
55
class value
56
{
57
#ifndef BOOST_JSON_DOCS
58
    using scalar = detail::scalar;
59
60
    union
61
    {
62
        storage_ptr sp_; // must come first
63
        array       arr_;
64
        object      obj_;
65
        string      str_;
66
        scalar      sca_;
67
    };
68
#endif
69
70
    struct init_iter;
71
72
#ifndef BOOST_JSON_DOCS
73
    // VFALCO doc toolchain incorrectly treats this as public
74
    friend struct detail::access;
75
#endif
76
77
    explicit
78
    value(
79
        detail::unchecked_array&& ua)
80
        : arr_(std::move(ua))
81
1.92k
    {
82
1.92k
    }
83
84
    explicit
85
    value(
86
        detail::unchecked_object&& uo)
87
        : obj_(std::move(uo))
88
14.3k
    {
89
14.3k
    }
90
91
    value(
92
        detail::key_t const&,
93
        string_view s,
94
        storage_ptr sp)
95
        : str_(detail::key_t{}, s, std::move(sp))
96
1.02M
    {
97
1.02M
    }
98
99
    value(
100
        detail::key_t const&,
101
        string_view s1,
102
        string_view s2,
103
        storage_ptr sp)
104
        : str_(detail::key_t{}, s1, s2, std::move(sp))
105
1.59k
    {
106
1.59k
    }
107
108
    inline bool is_scalar() const noexcept
109
    {
110
        return sca_.k < json::kind::string;
111
    }
112
113
public:
114
    /** The type of _Allocator_ returned by @ref get_allocator
115
116
        This type is a @ref polymorphic_allocator.
117
    */
118
#ifdef BOOST_JSON_DOCS
119
    // VFALCO doc toolchain renders this incorrectly
120
    using allocator_type = __see_below__;
121
#else
122
    using allocator_type = polymorphic_allocator<value>;
123
#endif
124
125
    /** Destructor.
126
127
        The value and all of its contents are destroyed.
128
        Any dynamically allocated memory that was allocated
129
        internally is freed.
130
131
        @par Complexity
132
        Constant, or linear in size for array or object.
133
134
        @par Exception Safety
135
        No-throw guarantee.
136
    */
137
    BOOST_JSON_DECL
138
    ~value() noexcept;
139
140
    /** Default constructor.
141
142
        The constructed value is null,
143
        using the [default memory resource].
144
145
        @par Complexity
146
        Constant.
147
148
        @par Exception Safety
149
        No-throw guarantee.
150
151
        [default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
152
    */
153
    value() noexcept
154
        : sca_()
155
0
    {
156
0
    }
157
158
    /** Constructor.
159
160
        The constructed value is null,
161
        using the specified @ref memory_resource.
162
163
        @par Complexity
164
        Constant.
165
166
        @par Exception Safety
167
        No-throw guarantee.
168
169
        @param sp A pointer to the @ref memory_resource
170
        to use. The container will acquire shared
171
        ownership of the memory resource.
172
    */
173
    explicit
174
    value(storage_ptr sp) noexcept
175
        : sca_(std::move(sp))
176
0
    {
177
0
    }
178
179
    /** Pilfer constructor.
180
181
        The value is constructed by acquiring ownership
182
        of the contents of `other` using pilfer semantics.
183
        This is more efficient than move construction, when
184
        it is known that the moved-from object will be
185
        immediately destroyed afterwards.
186
187
        @par Complexity
188
        Constant.
189
190
        @par Exception Safety
191
        No-throw guarantee.
192
193
        @param other The value to pilfer. After pilfer
194
        construction, `other` is not in a usable state
195
        and may only be destroyed.
196
197
        @see @ref pilfer,
198
            <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
199
                Valueless Variants Considered Harmful</a>
200
    */
201
    value(pilfered<value> other) noexcept
202
925k
    {
203
925k
        relocate(this, other.get());
204
925k
        ::new(&other.get().sca_) scalar();
205
925k
    }
206
207
    /** Copy constructor.
208
209
        The value is constructed with a copy of the
210
        contents of `other`, using the same
211
        memory resource as `other`.
212
213
        @par Complexity
214
        Linear in the size of `other`.
215
216
        @par Exception Safety
217
        Strong guarantee.
218
        Calls to `memory_resource::allocate` may throw.
219
220
        @param other The value to copy.
221
    */
222
    value(value const& other)
223
        : value(other, other.storage())
224
    {
225
    }
226
227
    /** Copy constructor
228
229
        The value is constructed with a copy of the
230
        contents of `other`, using the
231
        specified memory resource.
232
233
        @par Complexity
234
        Linear in the size of `other`.
235
236
        @par Exception Safety
237
        Strong guarantee.
238
        Calls to `memory_resource::allocate` may throw.
239
240
        @param other The value to copy.
241
242
        @param sp A pointer to the @ref memory_resource
243
        to use. The container will acquire shared
244
        ownership of the memory resource.
245
    */
246
    BOOST_JSON_DECL
247
    value(
248
        value const& other,
249
        storage_ptr sp);
250
251
    /** Move constructor
252
253
        The value is constructed by acquiring ownership of
254
        the contents of `other` and shared ownership of
255
        `other`'s memory resource.
256
257
        @note
258
259
        After construction, the moved-from value becomes a
260
        null value with its current storage pointer.
261
262
        @par Complexity
263
        Constant.
264
265
        @par Exception Safety
266
        No-throw guarantee.
267
268
        @param other The value to move.
269
    */
270
    BOOST_JSON_DECL
271
    value(value&& other) noexcept;
272
273
    /** Move constructor
274
275
        The value is constructed with the contents of
276
        `other` by move semantics, using the specified
277
        memory resource:
278
279
        @li If `*other.storage() == *sp`, ownership of
280
        the underlying memory is transferred in constant
281
        time, with no possibility of exceptions.
282
        After construction, the moved-from value becomes
283
        a null value with its current storage pointer.
284
285
        @li If `*other.storage() != *sp`, an
286
        element-wise copy is performed if
287
        `other.is_structured() == true`, which may throw.
288
        In this case, the moved-from value is not
289
        changed.
290
291
        @par Complexity
292
        Constant or linear in the size of `other`.
293
294
        @par Exception Safety
295
        Strong guarantee.
296
        Calls to `memory_resource::allocate` may throw.
297
298
        @param other The value to move.
299
300
        @param sp A pointer to the @ref memory_resource
301
        to use. The container will acquire shared
302
        ownership of the memory resource.
303
    */
304
    BOOST_JSON_DECL
305
    value(
306
        value&& other,
307
        storage_ptr sp);
308
309
    //------------------------------------------------------
310
    //
311
    // Conversion
312
    //
313
    //------------------------------------------------------
314
315
    /** Construct a null.
316
317
        A null value is a monostate.
318
319
        @par Complexity
320
        Constant.
321
322
        @par Exception Safety
323
        No-throw guarantee.
324
325
        @param sp A pointer to the @ref memory_resource
326
        to use. The container will acquire shared
327
        ownership of the memory resource.
328
    */
329
    value(
330
        std::nullptr_t,
331
        storage_ptr sp = {}) noexcept
332
        : sca_(std::move(sp))
333
8.22k
    {
334
8.22k
    }
335
336
    /** Construct a bool.
337
338
        This constructs a `bool` value using
339
        the specified memory resource.
340
341
        @par Complexity
342
        Constant.
343
344
        @par Exception Safety
345
        No-throw guarantee.
346
347
        @param b The initial value.
348
349
        @param sp A pointer to the @ref memory_resource
350
        to use. The container will acquire shared
351
        ownership of the memory resource.
352
    */
353
#ifdef BOOST_JSON_DOCS
354
    value(
355
        bool b,
356
        storage_ptr sp = {}) noexcept;
357
#else
358
    template<class T
359
        ,class = typename std::enable_if<
360
            std::is_same<T, bool>::value>::type
361
    >
362
    value(
363
        T b,
364
        storage_ptr sp = {}) noexcept
365
        : sca_(b, std::move(sp))
366
4.64k
    {
367
4.64k
    }
368
#endif
369
370
    /** Construct a `std::int64_t`.
371
372
        @par Complexity
373
        Constant.
374
375
        @par Exception Safety
376
        No-throw guarantee.
377
378
        @param i The initial value.
379
380
        @param sp A pointer to the @ref memory_resource
381
        to use. The container will acquire shared
382
        ownership of the memory resource.
383
    */
384
    value(
385
        signed char i,
386
        storage_ptr sp = {}) noexcept
387
        : sca_(static_cast<std::int64_t>(
388
            i), std::move(sp))
389
    {
390
    }
391
392
    /** Construct a `std::int64_t`.
393
394
        @par Complexity
395
        Constant.
396
397
        @par Exception Safety
398
        No-throw guarantee.
399
400
        @param i The initial value.
401
402
        @param sp A pointer to the @ref memory_resource
403
        to use. The container will acquire shared
404
        ownership of the memory resource.
405
    */
406
    value(
407
        short i,
408
        storage_ptr sp = {}) noexcept
409
        : sca_(static_cast<std::int64_t>(
410
            i), std::move(sp))
411
    {
412
    }
413
414
    /** Construct a `std::int64_t`.
415
416
        @par Complexity
417
        Constant.
418
419
        @par Exception Safety
420
        No-throw guarantee.
421
422
        @param i The initial value.
423
424
        @param sp A pointer to the @ref memory_resource
425
        to use. The container will acquire shared
426
        ownership of the memory resource.
427
    */
428
    value(
429
        int i,
430
        storage_ptr sp = {}) noexcept
431
        : sca_(static_cast<std::int64_t>(i),
432
            std::move(sp))
433
    {
434
    }
435
436
    /** Construct a `std::int64_t`.
437
438
        @par Complexity
439
        Constant.
440
441
        @par Exception Safety
442
        No-throw guarantee.
443
444
        @param i The initial value.
445
446
        @param sp A pointer to the @ref memory_resource
447
        to use. The container will acquire shared
448
        ownership of the memory resource.
449
    */
450
    value(
451
        long i,
452
        storage_ptr sp = {}) noexcept
453
        : sca_(static_cast<std::int64_t>(i),
454
            std::move(sp))
455
3.01M
    {
456
3.01M
    }
457
458
    /** Construct a `std::int64_t`.
459
460
        @par Complexity
461
        Constant.
462
463
        @par Exception Safety
464
        No-throw guarantee.
465
466
        @param i The initial value.
467
468
        @param sp A pointer to the @ref memory_resource
469
        to use. The container will acquire shared
470
        ownership of the memory resource.
471
    */
472
    value(
473
        long long i,
474
        storage_ptr sp = {}) noexcept
475
        : sca_(static_cast<std::int64_t>(i),
476
            std::move(sp))
477
    {
478
    }
479
480
    /** Construct a `std::uint64_t`.
481
482
        @par Complexity
483
        Constant.
484
485
        @par Exception Safety
486
        No-throw guarantee.
487
488
        @param u The initial value.
489
490
        @param sp A pointer to the @ref memory_resource
491
        to use. The container will acquire shared
492
        ownership of the memory resource.
493
    */
494
    value(
495
        unsigned char u,
496
        storage_ptr sp = {}) noexcept
497
        : sca_(static_cast<std::uint64_t>(
498
            u), std::move(sp))
499
    {
500
    }
501
502
    /** Construct a `std::uint64_t`.
503
504
        @par Complexity
505
        Constant.
506
507
        @par Exception Safety
508
        No-throw guarantee.
509
510
        @param u The initial value.
511
512
        @param sp A pointer to the @ref memory_resource
513
        to use. The container will acquire shared
514
        ownership of the memory resource.
515
    */
516
    value(
517
        unsigned short u,
518
        storage_ptr sp = {}) noexcept
519
        : sca_(static_cast<std::uint64_t>(u),
520
            std::move(sp))
521
    {
522
    }
523
524
    /** Construct a `std::uint64_t`.
525
526
        @par Complexity
527
        Constant.
528
529
        @par Exception Safety
530
        No-throw guarantee.
531
532
        @param u The initial value.
533
534
        @param sp A pointer to the @ref memory_resource
535
        to use. The container will acquire shared
536
        ownership of the memory resource.
537
    */
538
    value(
539
        unsigned int u,
540
        storage_ptr sp = {}) noexcept
541
        : sca_(static_cast<std::uint64_t>(u),
542
            std::move(sp))
543
    {
544
    }
545
546
    /** Construct a `std::uint64_t`.
547
548
        @par Complexity
549
        Constant.
550
551
        @par Exception Safety
552
        No-throw guarantee.
553
554
        @param u The initial value.
555
556
        @param sp A pointer to the @ref memory_resource
557
        to use. The container will acquire shared
558
        ownership of the memory resource.
559
    */
560
    value(
561
        unsigned long u,
562
        storage_ptr sp = {}) noexcept
563
        : sca_(static_cast<std::uint64_t>(u),
564
            std::move(sp))
565
2.33k
    {
566
2.33k
    }
567
568
    /** Construct a `std::uint64_t`.
569
570
        @par Complexity
571
        Constant.
572
573
        @par Exception Safety
574
        No-throw guarantee.
575
576
        @param u The initial value.
577
578
        @param sp A pointer to the @ref memory_resource
579
        to use. The container will acquire shared
580
        ownership of the memory resource.
581
    */
582
    value(
583
        unsigned long long u,
584
        storage_ptr sp = {}) noexcept
585
        : sca_(static_cast<std::uint64_t>(u),
586
            std::move(sp))
587
    {
588
    }
589
590
    /** Construct a `double`.
591
592
        @par Complexity
593
        Constant.
594
595
        @par Exception Safety
596
        No-throw guarantee.
597
598
        @param d The initial value.
599
600
        @param sp A pointer to the @ref memory_resource
601
        to use. The container will acquire shared
602
        ownership of the memory resource.
603
    */
604
    value(
605
        double d,
606
        storage_ptr sp = {}) noexcept
607
        : sca_(d, std::move(sp))
608
32.1k
    {
609
32.1k
    }
610
611
    /** Construct a @ref string.
612
613
        The string is constructed with a copy of the
614
        string view `s`, using the specified memory resource.
615
616
        @par Complexity
617
        Linear in `s.size()`.
618
619
        @par Exception Safety
620
        Strong guarantee.
621
        Calls to `memory_resource::allocate` may throw.
622
623
        @param s The string view to construct with.
624
625
        @param sp A pointer to the @ref memory_resource
626
        to use. The container will acquire shared
627
        ownership of the memory resource.
628
    */
629
    value(
630
        string_view s,
631
        storage_ptr sp = {})
632
        : str_(s, std::move(sp))
633
20.5k
    {
634
20.5k
    }
635
636
    /** Construct a @ref string.
637
638
        The string is constructed with a copy of the
639
        null-terminated string `s`, using the specified
640
        memory resource.
641
642
        @par Complexity
643
        Linear in `std::strlen(s)`.
644
645
        @par Exception Safety
646
        Strong guarantee.
647
        Calls to `memory_resource::allocate` may throw.
648
649
        @param s The null-terminated string to construct
650
        with.
651
652
        @param sp A pointer to the @ref memory_resource
653
        to use. The container will acquire shared
654
        ownership of the memory resource.
655
    */
656
    value(
657
        char const* s,
658
        storage_ptr sp = {})
659
        : str_(s, std::move(sp))
660
0
    {
661
0
    }
662
663
    /** Construct a @ref string.
664
665
        The value is constructed from `other`, using the
666
        same memory resource. To transfer ownership, use `std::move`:
667
668
        @par Example
669
        @code
670
        string str = "The Boost C++ Library Collection";
671
672
        // transfer ownership
673
        value jv( std::move(str) );
674
675
        assert( str.empty() );
676
        assert( *str.storage() == *jv.storage() );
677
        @endcode
678
679
        @par Complexity
680
        Constant.
681
682
        @par Exception Safety
683
        No-throw guarantee.
684
685
        @param other The string to construct with.
686
    */
687
    value(
688
        string other) noexcept
689
        : str_(std::move(other))
690
0
    {
691
0
    }
692
693
    /** Construct a @ref string.
694
695
        The value is copy constructed from `other`,
696
        using the specified memory resource.
697
698
        @par Complexity
699
        Linear in `other.size()`.
700
701
        @par Exception Safety
702
        Strong guarantee.
703
        Calls to `memory_resource::allocate` may throw.
704
705
        @param other The string to construct with.
706
707
        @param sp A pointer to the @ref memory_resource
708
        to use. The container will acquire shared
709
        ownership of the memory resource.
710
    */
711
    value(
712
        string const& other,
713
        storage_ptr sp)
714
        : str_(
715
            other,
716
            std::move(sp))
717
0
    {
718
0
    }
719
720
    /** Construct a @ref string.
721
722
        The value is move constructed from `other`,
723
        using the specified memory resource.
724
725
        @par Complexity
726
        Constant or linear in `other.size()`.
727
728
        @par Exception Safety
729
        Strong guarantee.
730
        Calls to `memory_resource::allocate` may throw.
731
732
        @param other The string to construct with.
733
734
        @param sp A pointer to the @ref memory_resource
735
        to use. The container will acquire shared
736
        ownership of the memory resource.
737
    */
738
    value(
739
        string&& other,
740
        storage_ptr sp)
741
        : str_(
742
            std::move(other),
743
            std::move(sp))
744
0
    {
745
0
    }
746
747
    /** Construct a @ref string.
748
749
        This is the fastest way to construct
750
        an empty string, using the specified
751
        memory resource. The variable @ref string_kind
752
        may be passed as the first parameter
753
        to select this overload:
754
755
        @par Example
756
        @code
757
        // Construct an empty string
758
759
        value jv( string_kind );
760
        @endcode
761
762
        @par Complexity
763
        Constant.
764
765
        @par Exception Safety
766
        No-throw guarantee.
767
768
        @param sp A pointer to the @ref memory_resource
769
        to use. The container will acquire shared
770
        ownership of the memory resource.
771
772
        @see @ref string_kind
773
    */
774
    value(
775
        string_kind_t,
776
        storage_ptr sp = {}) noexcept
777
        : str_(std::move(sp))
778
10.2k
    {
779
10.2k
    }
780
781
    /** Construct an @ref array.
782
783
        The value is constructed from `other`, using the
784
        same memory resource. To transfer ownership, use `std::move`:
785
786
        @par Example
787
        @code
788
        array arr( {1, 2, 3, 4, 5} );
789
790
        // transfer ownership
791
        value jv( std::move(arr) );
792
793
        assert( arr.empty() );
794
        assert( *arr.storage() == *jv.storage() );
795
        @endcode
796
797
        @par Complexity
798
        Constant.
799
800
        @par Exception Safety
801
        No-throw guarantee.
802
803
        @param other The array to construct with.
804
    */
805
    value(array other) noexcept
806
        : arr_(std::move(other))
807
0
    {
808
0
    }
809
810
    /** Construct an @ref array.
811
812
        The value is copy constructed from `other`,
813
        using the specified memory resource.
814
815
        @par Complexity
816
        Linear in `other.size()`.
817
818
        @par Exception Safety
819
        Strong guarantee.
820
        Calls to `memory_resource::allocate` may throw.
821
822
        @param other The array to construct with.
823
824
        @param sp A pointer to the @ref memory_resource
825
        to use. The container will acquire shared
826
        ownership of the memory resource.
827
    */
828
    value(
829
        array const& other,
830
        storage_ptr sp)
831
        : arr_(
832
            other,
833
            std::move(sp))
834
0
    {
835
0
    }
836
837
    /** Construct an @ref array.
838
839
        The value is move-constructed from `other`,
840
        using the specified memory resource.
841
842
        @par Complexity
843
        Constant or linear in `other.size()`.
844
845
        @par Exception Safety
846
        Strong guarantee.
847
        Calls to `memory_resource::allocate` may throw.
848
849
        @param other The array to construct with.
850
851
        @param sp A pointer to the @ref memory_resource
852
        to use. The container will acquire shared
853
        ownership of the memory resource.
854
    */
855
    value(
856
        array&& other,
857
        storage_ptr sp)
858
        : arr_(
859
            std::move(other),
860
            std::move(sp))
861
0
    {
862
0
    }
863
864
    /** Construct an @ref array.
865
866
        This is the fastest way to construct
867
        an empty array, using the specified
868
        memory resource. The variable @ref array_kind
869
        may be passed as the first parameter
870
        to select this overload:
871
872
        @par Example
873
        @code
874
        // Construct an empty array
875
876
        value jv( array_kind );
877
        @endcode
878
879
        @par Complexity
880
        Constant.
881
882
        @par Exception Safety
883
        No-throw guarantee.
884
885
        @param sp A pointer to the @ref memory_resource
886
        to use. The container will acquire shared
887
        ownership of the memory resource.
888
889
        @see @ref array_kind
890
    */
891
    value(
892
        array_kind_t,
893
        storage_ptr sp = {}) noexcept
894
        : arr_(std::move(sp))
895
    {
896
    }
897
898
    /** Construct an @ref object.
899
900
        The value is constructed from `other`, using the
901
        same memory resource. To transfer ownership, use `std::move`:
902
903
        @par Example
904
        @code
905
        object obj( {{"a",1}, {"b",2}, {"c"},3}} );
906
907
        // transfer ownership
908
        value jv( std::move(obj) );
909
910
        assert( obj.empty() );
911
        assert( *obj.storage() == *jv.storage() );
912
        @endcode
913
914
        @par Complexity
915
        Constant.
916
917
        @par Exception Safety
918
        No-throw guarantee.
919
920
        @param other The object to construct with.
921
    */
922
    value(object other) noexcept
923
        : obj_(std::move(other))
924
0
    {
925
0
    }
926
927
    /** Construct an @ref object.
928
929
        The value is copy constructed from `other`,
930
        using the specified memory resource.
931
932
        @par Complexity
933
        Linear in `other.size()`.
934
935
        @par Exception Safety
936
        Strong guarantee.
937
        Calls to `memory_resource::allocate` may throw.
938
939
        @param other The object to construct with.
940
941
        @param sp A pointer to the @ref memory_resource
942
        to use. The container will acquire shared
943
        ownership of the memory resource.
944
    */
945
    value(
946
        object const& other,
947
        storage_ptr sp)
948
        : obj_(
949
            other,
950
            std::move(sp))
951
0
    {
952
0
    }
953
954
    /** Construct an @ref object.
955
956
        The value is move constructed from `other`,
957
        using the specified memory resource.
958
959
        @par Complexity
960
        Constant or linear in `other.size()`.
961
962
        @par Exception Safety
963
        Strong guarantee.
964
        Calls to `memory_resource::allocate` may throw.
965
966
        @param other The object to construct with.
967
968
        @param sp A pointer to the @ref memory_resource
969
        to use. The container will acquire shared
970
        ownership of the memory resource.
971
    */
972
    value(
973
        object&& other,
974
        storage_ptr sp)
975
        : obj_(
976
            std::move(other),
977
            std::move(sp))
978
0
    {
979
0
    }
980
981
    /** Construct an @ref object.
982
983
        This is the fastest way to construct
984
        an empty object, using the specified
985
        memory resource. The variable @ref object_kind
986
        may be passed as the first parameter
987
        to select this overload:
988
989
        @par Example
990
        @code
991
        // Construct an empty object
992
993
        value jv( object_kind );
994
        @endcode
995
996
        @par Complexity
997
        Constant.
998
999
        @par Exception Safety
1000
        No-throw guarantee.
1001
1002
        @param sp A pointer to the @ref memory_resource
1003
        to use. The container will acquire shared
1004
        ownership of the memory resource.
1005
1006
        @see @ref object_kind
1007
    */
1008
    value(
1009
        object_kind_t,
1010
        storage_ptr sp = {}) noexcept
1011
        : obj_(std::move(sp))
1012
    {
1013
    }
1014
1015
    /** Construct from an initializer-list
1016
1017
        If the initializer list consists of key/value
1018
        pairs, an @ref object is created. Otherwise
1019
        an @ref array is created. The contents of the
1020
        initializer list are copied to the newly constructed
1021
        value using the specified memory resource.
1022
1023
        @par Complexity
1024
        Linear in `init.size()`.
1025
1026
        @par Exception Safety
1027
        Strong guarantee.
1028
        Calls to `memory_resource::allocate` may throw.
1029
1030
        @param init The initializer list to construct from.
1031
1032
        @param sp A pointer to the @ref memory_resource
1033
        to use. The container will acquire shared
1034
        ownership of the memory resource.
1035
    */
1036
    BOOST_JSON_DECL
1037
    value(
1038
        std::initializer_list<value_ref> init,
1039
        storage_ptr sp = {});
1040
1041
    //------------------------------------------------------
1042
    //
1043
    // Assignment
1044
    //
1045
    //------------------------------------------------------
1046
1047
    /** Copy assignment.
1048
1049
        The contents of the value are replaced with an
1050
        element-wise copy of the contents of `other`.
1051
1052
        @par Complexity
1053
        Linear in the size of `*this` plus `other`.
1054
1055
        @par Exception Safety
1056
        Strong guarantee.
1057
        Calls to `memory_resource::allocate` may throw.
1058
1059
        @param other The value to copy.
1060
    */
1061
    BOOST_JSON_DECL
1062
    value&
1063
    operator=(value const& other);
1064
1065
    /** Move assignment.
1066
1067
        The contents of the value are replaced with the
1068
        contents of `other` using move semantics:
1069
1070
        @li If `*other.storage() == *sp`, ownership of
1071
        the underlying memory is transferred in constant
1072
        time, with no possibility of exceptions.
1073
        After assignment, the moved-from value becomes
1074
        a null with its current storage pointer.
1075
1076
        @li If `*other.storage() != *sp`, an
1077
        element-wise copy is performed if
1078
        `other.is_structured() == true`, which may throw.
1079
        In this case, the moved-from value is not
1080
        changed.
1081
1082
        @par Complexity
1083
        Constant, or linear in
1084
        `this->size()` plus `other.size()`.
1085
1086
        @par Exception Safety
1087
        Strong guarantee.
1088
        Calls to `memory_resource::allocate` may throw.
1089
1090
        @param other The value to assign from.
1091
    */
1092
    BOOST_JSON_DECL
1093
    value&
1094
    operator=(value&& other);
1095
1096
    /** Assignment.
1097
1098
        Replace `*this` with the value formed by
1099
        constructing from `init` and `this->storage()`.
1100
        If the initializer list consists of key/value
1101
        pairs, the resulting @ref object is assigned.
1102
        Otherwise an @ref array is assigned. The contents
1103
        of the initializer list are moved to `*this`
1104
        using the existing memory resource.
1105
1106
        @par Complexity
1107
        Linear in `init.size()`.
1108
1109
        @par Exception Safety
1110
        Strong guarantee.
1111
        Calls to `memory_resource::allocate` may throw.
1112
1113
        @param init The initializer list to assign from.
1114
    */
1115
    BOOST_JSON_DECL
1116
    value&
1117
    operator=(
1118
        std::initializer_list<value_ref> init);
1119
1120
    /** Assignment.
1121
1122
        Replace `*this` with null.
1123
1124
        @par Exception Safety
1125
        No-throw guarantee.
1126
1127
        @par Complexity
1128
        Linear in the size of `*this`.
1129
    */
1130
    value&
1131
    operator=(std::nullptr_t) noexcept
1132
    {
1133
        if(is_scalar())
1134
        {
1135
            sca_.k = json::kind::null;
1136
        }
1137
        else
1138
        {
1139
            ::new(&sca_) scalar(
1140
                destroy());
1141
        }
1142
        return *this;
1143
    }
1144
1145
    /** Assignment.
1146
1147
        Replace `*this` with `b`.
1148
1149
        @par Exception Safety
1150
        No-throw guarantee.
1151
1152
        @par Complexity
1153
        Linear in the size of `*this`.
1154
1155
        @param b The new value.
1156
    */
1157
#ifdef BOOST_JSON_DOCS
1158
    value& operator=(bool b) noexcept;
1159
#else
1160
    template<class T
1161
        ,class = typename std::enable_if<
1162
            std::is_same<T, bool>::value>::type
1163
    >
1164
    value& operator=(T b) noexcept
1165
    {
1166
        if(is_scalar())
1167
        {
1168
            sca_.b = b;
1169
            sca_.k = json::kind::bool_;
1170
        }
1171
        else
1172
        {
1173
            ::new(&sca_) scalar(
1174
                b, destroy());
1175
        }
1176
        return *this;
1177
    }
1178
#endif
1179
1180
    /** Assignment.
1181
1182
        Replace `*this` with `i`.
1183
1184
        @par Exception Safety
1185
        No-throw guarantee.
1186
1187
        @par Complexity
1188
        Linear in the size of `*this`.
1189
1190
        @param i The new value.
1191
    */
1192
    /** @{ */
1193
    value& operator=(signed char i) noexcept
1194
    {
1195
        return operator=(
1196
            static_cast<long long>(i));
1197
    }
1198
1199
    value& operator=(short i) noexcept
1200
    {
1201
        return operator=(
1202
            static_cast<long long>(i));
1203
    }
1204
1205
    value& operator=(int i) noexcept
1206
    {
1207
        return operator=(
1208
            static_cast<long long>(i));
1209
    }
1210
1211
    value& operator=(long i) noexcept
1212
    {
1213
        return operator=(
1214
            static_cast<long long>(i));
1215
    }
1216
1217
    value& operator=(long long i) noexcept
1218
    {
1219
        if(is_scalar())
1220
        {
1221
            sca_.i = i;
1222
            sca_.k = json::kind::int64;
1223
        }
1224
        else
1225
        {
1226
            ::new(&sca_) scalar(static_cast<
1227
                std::int64_t>(i), destroy());
1228
        }
1229
        return *this;
1230
    }
1231
    /** @} */
1232
1233
    /** Assignment.
1234
1235
        Replace `*this` with `i`.
1236
1237
        @par Exception Safety
1238
        No-throw guarantee.
1239
1240
        @par Complexity
1241
        Linear in the size of `*this`.
1242
1243
        @param u The new value.
1244
    */
1245
    /** @{ */
1246
    value& operator=(unsigned char u) noexcept
1247
    {
1248
        return operator=(static_cast<
1249
            unsigned long long>(u));
1250
    }
1251
1252
    value& operator=(unsigned short u) noexcept
1253
    {
1254
        return operator=(static_cast<
1255
            unsigned long long>(u));
1256
    }
1257
1258
    value& operator=(unsigned int u) noexcept
1259
    {
1260
        return operator=(static_cast<
1261
            unsigned long long>(u));
1262
    }
1263
1264
    value& operator=(unsigned long u) noexcept
1265
    {
1266
        return operator=(static_cast<
1267
            unsigned long long>(u));
1268
    }
1269
1270
    value& operator=(unsigned long long u) noexcept
1271
    {
1272
        if(is_scalar())
1273
        {
1274
            sca_.u = u;
1275
            sca_.k = json::kind::uint64;
1276
        }
1277
        else
1278
        {
1279
            ::new(&sca_) scalar(static_cast<
1280
                std::uint64_t>(u), destroy());
1281
        }
1282
        return *this;
1283
    }
1284
    /** @} */
1285
1286
    /** Assignment.
1287
1288
        Replace `*this` with `d`.
1289
1290
        @par Exception Safety
1291
        No-throw guarantee.
1292
1293
        @par Complexity
1294
        Linear in the size of `*this`.
1295
1296
        @param d The new value.
1297
    */
1298
    value& operator=(double d) noexcept
1299
    {
1300
        if(is_scalar())
1301
        {
1302
            sca_.d = d;
1303
            sca_.k = json::kind::double_;
1304
        }
1305
        else
1306
        {
1307
            ::new(&sca_) scalar(
1308
                d, destroy());
1309
        }
1310
        return *this;
1311
    }
1312
1313
    /** Assignment.
1314
1315
        Replace `*this` with a copy of the string `s`.
1316
1317
        @par Exception Safety
1318
        Strong guarantee.
1319
        Calls to `memory_resource::allocate` may throw.
1320
1321
        @par Complexity
1322
        Linear in the sum of sizes of `*this` and `s`
1323
1324
        @param s The new string.
1325
    */
1326
    /** @{ */
1327
    BOOST_JSON_DECL value& operator=(string_view s);
1328
    BOOST_JSON_DECL value& operator=(char const* s);
1329
    BOOST_JSON_DECL value& operator=(string const& s);
1330
    /** @} */
1331
1332
    /** Assignment.
1333
1334
        The contents of the value are replaced with the
1335
        contents of `s` using move semantics:
1336
1337
        @li If `*other.storage() == *this->storage()`,
1338
        ownership of the underlying memory is transferred
1339
        in constant time, with no possibility of exceptions.
1340
        After assignment, the moved-from string becomes
1341
        empty with its current storage pointer.
1342
1343
        @li If `*other.storage() != *this->storage()`, an
1344
        element-wise copy is performed, which may throw.
1345
        In this case, the moved-from string is not
1346
        changed.
1347
1348
        @par Complexity
1349
        Constant, or linear in the size of `*this` plus `s.size()`.
1350
1351
        @par Exception Safety
1352
        Strong guarantee.
1353
        Calls to `memory_resource::allocate` may throw.
1354
1355
        @param s The string to move-assign from.
1356
    */
1357
    BOOST_JSON_DECL value& operator=(string&& s);
1358
1359
    /** Assignment.
1360
1361
        Replace `*this` with a copy of the array `arr`.
1362
1363
        @par Exception Safety
1364
        Strong guarantee.
1365
        Calls to `memory_resource::allocate` may throw.
1366
1367
        @par Complexity
1368
        Linear in the sum of sizes of `*this` and `arr`
1369
1370
        @param arr The new array.
1371
    */
1372
    BOOST_JSON_DECL value& operator=(array const& arr);
1373
1374
    /** Assignment.
1375
1376
        The contents of the value are replaced with the
1377
        contents of `arr` using move semantics:
1378
1379
        @li If `*arr.storage() == *this->storage()`,
1380
        ownership of the underlying memory is transferred
1381
        in constant time, with no possibility of exceptions.
1382
        After assignment, the moved-from array becomes
1383
        empty with its current storage pointer.
1384
1385
        @li If `*arr.storage() != *this->storage()`, an
1386
        element-wise copy is performed, which may throw.
1387
        In this case, the moved-from array is not
1388
        changed.
1389
1390
        @par Complexity
1391
        Constant, or linear in the size of `*this` plus `arr.size()`.
1392
1393
        @par Exception Safety
1394
        Strong guarantee.
1395
        Calls to `memory_resource::allocate` may throw.
1396
1397
        @param arr The array to move-assign from.
1398
    */
1399
    BOOST_JSON_DECL value& operator=(array&& arr);
1400
1401
    /** Assignment.
1402
1403
        Replace `*this` with a copy of the obect `obj`.
1404
1405
        @par Exception Safety
1406
        Strong guarantee.
1407
        Calls to `memory_resource::allocate` may throw.
1408
1409
        @par Complexity
1410
        Linear in the sum of sizes of `*this` and `obj`
1411
1412
        @param obj The new object.
1413
    */
1414
    BOOST_JSON_DECL value& operator=(object const& obj);
1415
1416
    /** Assignment.
1417
1418
        The contents of the value are replaced with the
1419
        contents of `obj` using move semantics:
1420
1421
        @li If `*obj.storage() == *this->storage()`,
1422
        ownership of the underlying memory is transferred
1423
        in constant time, with no possibility of exceptions.
1424
        After assignment, the moved-from object becomes
1425
        empty with its current storage pointer.
1426
1427
        @li If `*obj.storage() != *this->storage()`, an
1428
        element-wise copy is performed, which may throw.
1429
        In this case, the moved-from object is not
1430
        changed.
1431
1432
        @par Complexity
1433
        Constant, or linear in the size of `*this` plus `obj.size()`.
1434
1435
        @par Exception Safety
1436
        Strong guarantee.
1437
        Calls to `memory_resource::allocate` may throw.
1438
1439
        @param obj The object to move-assign from.
1440
    */
1441
    BOOST_JSON_DECL value& operator=(object&& obj);
1442
1443
    //------------------------------------------------------
1444
    //
1445
    // Modifiers
1446
    //
1447
    //------------------------------------------------------
1448
1449
    /** Change the kind to null, discarding the previous contents.
1450
1451
        The value is replaced with a null,
1452
        destroying the previous contents.
1453
1454
        @par Complexity
1455
        Linear in the size of `*this`.
1456
1457
        @par Exception Safety
1458
        No-throw guarantee.
1459
    */
1460
    void
1461
    emplace_null() noexcept
1462
    {
1463
        *this = nullptr;
1464
    }
1465
1466
    /** Return a reference to a `bool`, changing the kind and replacing the contents.
1467
1468
        The value is replaced with a `bool`
1469
        initialized to `false`, destroying the
1470
        previous contents.
1471
1472
        @par Complexity
1473
        Linear in the size of `*this`.
1474
1475
        @par Exception Safety
1476
        No-throw guarantee.
1477
    */
1478
    bool&
1479
    emplace_bool() noexcept
1480
    {
1481
        *this = false;
1482
        return sca_.b;
1483
    }
1484
1485
    /** Return a reference to a `std::int64_t`, changing the kind and replacing the contents.
1486
1487
        The value is replaced with a `std::int64_t`
1488
        initialized to zero, destroying the
1489
        previous contents.
1490
1491
        @par Complexity
1492
        Linear in the size of `*this`.
1493
1494
        @par Exception Safety
1495
        No-throw guarantee.
1496
    */
1497
    std::int64_t&
1498
    emplace_int64() noexcept
1499
    {
1500
        *this = std::int64_t{};
1501
        return sca_.i;
1502
    }
1503
1504
    /** Return a reference to a `std::uint64_t`, changing the kind and replacing the contents.
1505
1506
        The value is replaced with a `std::uint64_t`
1507
        initialized to zero, destroying the
1508
        previous contents.
1509
1510
        @par Complexity
1511
        Linear in the size of `*this`.
1512
1513
        @par Exception Safety
1514
        No-throw guarantee.
1515
    */
1516
    std::uint64_t&
1517
    emplace_uint64() noexcept
1518
    {
1519
        *this = std::uint64_t{};
1520
        return sca_.u;
1521
    }
1522
1523
    /** Return a reference to a `double`, changing the kind and replacing the contents.
1524
1525
        The value is replaced with a `double`
1526
        initialized to zero, destroying the
1527
        previous contents.
1528
1529
        @par Complexity
1530
        Linear in the size of `*this`.
1531
1532
        @par Exception Safety
1533
        No-throw guarantee.
1534
    */
1535
    double&
1536
    emplace_double() noexcept
1537
    {
1538
        *this = double{};
1539
        return sca_.d;
1540
    }
1541
1542
    /** Return a reference to a @ref string, changing the kind and replacing the contents.
1543
1544
        The value is replaced with an empty @ref string
1545
        using the current memory resource, destroying the
1546
        previous contents.
1547
1548
        @par Complexity
1549
        Linear in the size of `*this`.
1550
1551
        @par Exception Safety
1552
        No-throw guarantee.
1553
    */
1554
    BOOST_JSON_DECL
1555
    string&
1556
    emplace_string() noexcept;
1557
1558
    /** Return a reference to an @ref array, changing the kind and replacing the contents.
1559
1560
        The value is replaced with an empty @ref array
1561
        using the current memory resource, destroying the
1562
        previous contents.
1563
1564
        @par Complexity
1565
        Linear in the size of `*this`.
1566
1567
        @par Exception Safety
1568
        No-throw guarantee.
1569
    */
1570
    BOOST_JSON_DECL
1571
    array&
1572
    emplace_array() noexcept;
1573
1574
    /** Return a reference to an @ref object, changing the kind and replacing the contents.
1575
1576
        The contents are replaced with an empty @ref object
1577
        using the current @ref memory_resource. All
1578
        previously obtained iterators and references
1579
        obtained beforehand are invalidated.
1580
1581
        @par Complexity
1582
        Linear in the size of `*this`.
1583
1584
        @par Exception Safety
1585
        No-throw guarantee.
1586
    */
1587
    BOOST_JSON_DECL
1588
    object&
1589
    emplace_object() noexcept;
1590
1591
    /** Swap the given values.
1592
1593
        Exchanges the contents of this value with another
1594
        value. Ownership of the respective @ref memory_resource
1595
        objects is not transferred:
1596
1597
        @li If `*other.storage() == *this->storage()`,
1598
        ownership of the underlying memory is swapped in
1599
        constant time, with no possibility of exceptions.
1600
        All iterators and references remain valid.
1601
1602
        @li If `*other.storage() != *this->storage()`,
1603
        the contents are logically swapped by making copies,
1604
        which can throw. In this case all iterators and
1605
        references are invalidated.
1606
1607
        @par Complexity
1608
        Constant or linear in the sum of the sizes of
1609
        the values.
1610
1611
        @par Exception Safety
1612
        Strong guarantee.
1613
        Calls to `memory_resource::allocate` may throw.
1614
1615
        @param other The value to swap with.
1616
        If `this == &other`, this function call has no effect.
1617
    */
1618
    BOOST_JSON_DECL
1619
    void
1620
    swap(value& other);
1621
1622
    /** Swap the given values.
1623
1624
        Exchanges the contents of value `lhs` with
1625
        another value `rhs`. Ownership of the respective
1626
        @ref memory_resource objects is not transferred.
1627
1628
        @li If `*lhs.storage() == *rhs.storage()`,
1629
        ownership of the underlying memory is swapped in
1630
        constant time, with no possibility of exceptions.
1631
        All iterators and references remain valid.
1632
1633
        @li If `*lhs.storage() != *rhs.storage`,
1634
        the contents are logically swapped by a copy,
1635
        which can throw. In this case all iterators and
1636
        references are invalidated.
1637
1638
        @par Effects
1639
        @code
1640
        lhs.swap( rhs );
1641
        @endcode
1642
1643
        @par Complexity
1644
        Constant or linear in the sum of the sizes of
1645
        the values.
1646
1647
        @par Exception Safety
1648
        Strong guarantee.
1649
        Calls to `memory_resource::allocate` may throw.
1650
1651
        @param lhs The value to exchange.
1652
1653
        @param rhs The value to exchange.
1654
        If `&lhs == &rhs`, this function call has no effect.
1655
1656
        @see @ref value::swap
1657
    */
1658
    friend
1659
    void
1660
    swap(value& lhs, value& rhs)
1661
    {
1662
        lhs.swap(rhs);
1663
    }
1664
1665
    //------------------------------------------------------
1666
    //
1667
    // Observers
1668
    //
1669
    //------------------------------------------------------
1670
1671
    /** Returns the kind of this JSON value.
1672
1673
        This function returns the discriminating
1674
        enumeration constant of type @ref json::kind
1675
        corresponding to the underlying representation
1676
        stored in the container.
1677
1678
        @par Complexity
1679
        Constant.
1680
1681
        @par Exception Safety
1682
        No-throw guarantee.
1683
    */
1684
    json::kind
1685
    kind() const noexcept
1686
    {
1687
        return static_cast<json::kind>(
1688
            static_cast<unsigned char>(
1689
                sca_.k) & 0x3f);
1690
    }
1691
1692
    /** Return `true` if this is an array
1693
1694
        This function is used to determine if the underlying
1695
        representation is a certain kind.
1696
1697
        @par Effects
1698
        @code
1699
        return this->kind() == kind::array;
1700
        @endcode
1701
1702
        @par Complexity
1703
        Constant.
1704
1705
        @par Exception Safety
1706
        No-throw guarantee.
1707
    */
1708
    bool
1709
    is_array() const noexcept
1710
    {
1711
        return kind() == json::kind::array;
1712
    }
1713
1714
    /** Return `true` if this is an object
1715
1716
        This function is used to determine if the underlying
1717
        representation is a certain kind.
1718
1719
        @par Effects
1720
        @code
1721
        return this->kind() == kind::object;
1722
        @endcode
1723
1724
        @par Complexity
1725
        Constant.
1726
1727
        @par Exception Safety
1728
        No-throw guarantee.
1729
    */
1730
    bool
1731
    is_object() const noexcept
1732
    {
1733
        return kind() == json::kind::object;
1734
    }
1735
1736
    /** Return `true` if this is a string
1737
1738
        This function is used to determine if the underlying
1739
        representation is a certain kind.
1740
1741
        @par Effects
1742
        @code
1743
        return this->kind() == kind::string;
1744
        @endcode
1745
1746
        @par Complexity
1747
        Constant.
1748
1749
        @par Exception Safety
1750
        No-throw guarantee.
1751
    */
1752
    bool
1753
    is_string() const noexcept
1754
    {
1755
        return kind() == json::kind::string;
1756
    }
1757
1758
    /** Return `true` if this is a signed integer
1759
1760
        This function is used to determine if the underlying
1761
        representation is a certain kind.
1762
1763
        @par Effects
1764
        @code
1765
        return this->kind() == kind::int64;
1766
        @endcode
1767
1768
        @par Complexity
1769
        Constant.
1770
1771
        @par Exception Safety
1772
        No-throw guarantee.
1773
    */
1774
    bool
1775
    is_int64() const noexcept
1776
    {
1777
        return kind() == json::kind::int64;
1778
    }
1779
1780
    /** Return `true` if this is a unsigned integer
1781
1782
        This function is used to determine if the underlying
1783
        representation is a certain kind.
1784
1785
        @par Effects
1786
        @code
1787
        return this->kind() == kind::uint64;
1788
        @endcode
1789
1790
        @par Complexity
1791
        Constant.
1792
1793
        @par Exception Safety
1794
        No-throw guarantee.
1795
    */
1796
    bool
1797
    is_uint64() const noexcept
1798
    {
1799
        return kind() == json::kind::uint64;
1800
    }
1801
1802
    /** Return `true` if this is a double
1803
1804
        This function is used to determine if the underlying
1805
        representation is a certain kind.
1806
1807
        @par Effects
1808
        @code
1809
        return this->kind() == kind::double_;
1810
        @endcode
1811
1812
        @par Complexity
1813
        Constant.
1814
1815
        @par Exception Safety
1816
        No-throw guarantee.
1817
    */
1818
    bool
1819
    is_double() const noexcept
1820
    {
1821
        return kind() == json::kind::double_;
1822
    }
1823
1824
    /** Return `true` if this is a bool
1825
1826
        This function is used to determine if the underlying
1827
        representation is a certain kind.
1828
1829
        @par Effects
1830
        @code
1831
        return this->kind() == kind::bool_;
1832
        @endcode
1833
1834
        @par Complexity
1835
        Constant.
1836
1837
        @par Exception Safety
1838
        No-throw guarantee.
1839
    */
1840
    bool
1841
    is_bool() const noexcept
1842
    {
1843
        return kind() == json::kind::bool_;
1844
    }
1845
1846
    /** Returns true if this is a null.
1847
1848
        This function is used to determine if the underlying
1849
        representation is a certain kind.
1850
1851
        @par Effects
1852
        @code
1853
        return this->kind() == kind::null;
1854
        @endcode
1855
1856
        @par Complexity
1857
        Constant.
1858
1859
        @par Exception Safety
1860
        No-throw guarantee.
1861
    */
1862
    bool
1863
    is_null() const noexcept
1864
0
    {
1865
0
        return kind() == json::kind::null;
1866
0
    }
1867
1868
    /** Returns true if this is an array or object.
1869
1870
        This function returns `true` if
1871
        @ref kind() is either `kind::object` or
1872
        `kind::array`.
1873
1874
        @par Complexity
1875
        Constant.
1876
1877
        @par Exception Safety
1878
        No-throw guarantee.
1879
    */
1880
    bool
1881
    is_structured() const noexcept
1882
    {
1883
        // VFALCO Could use bit 0x20 for this
1884
        return
1885
           kind() == json::kind::object ||
1886
           kind() == json::kind::array;
1887
    }
1888
1889
    /** Returns true if this is not an array or object.
1890
1891
        This function returns `true` if
1892
        @ref kind() is neither `kind::object` nor
1893
        `kind::array`.
1894
1895
        @par Complexity
1896
        Constant.
1897
1898
        @par Exception Safety
1899
        No-throw guarantee.
1900
    */
1901
    bool
1902
    is_primitive() const noexcept
1903
    {
1904
        // VFALCO Could use bit 0x20 for this
1905
        return
1906
           sca_.k != json::kind::object &&
1907
           sca_.k != json::kind::array;
1908
    }
1909
1910
    /** Returns true if this is a number.
1911
1912
        This function returns `true` when
1913
        @ref kind() is one of the following values:
1914
        `kind::int64`, `kind::uint64`, or
1915
        `kind::double_`.
1916
1917
        @par Complexity
1918
        Constant.
1919
1920
        @par Exception Safety
1921
        No-throw guarantee.
1922
    */
1923
    bool
1924
    is_number() const noexcept
1925
    {
1926
        // VFALCO Could use bit 0x40 for this
1927
        return
1928
            kind() == json::kind::int64 ||
1929
            kind() == json::kind::uint64 ||
1930
            kind() == json::kind::double_;
1931
    }
1932
1933
    //------------------------------------------------------
1934
1935
    /** Return an @ref array pointer if this is an array, else return `nullptr`
1936
1937
        If `this->kind() == kind::array`, returns a pointer
1938
        to the underlying array. Otherwise, returns `nullptr`.
1939
1940
        @par Example
1941
        The return value is used in both a boolean context and
1942
        to assign a variable:
1943
        @code
1944
        if( auto p = jv.if_array() )
1945
            return *p;
1946
        @endcode
1947
1948
        @par Complexity
1949
        Constant.
1950
1951
        @par Exception Safety
1952
        No-throw guarantee.
1953
    */
1954
    array const*
1955
    if_array() const noexcept
1956
    {
1957
        if(kind() == json::kind::array)
1958
            return &arr_;
1959
        return nullptr;
1960
    }
1961
1962
    /** Return an @ref array pointer if this is an array, else return `nullptr`
1963
1964
        If `this->kind() == kind::array`, returns a pointer
1965
        to the underlying array. Otherwise, returns `nullptr`.
1966
1967
        @par Example
1968
        The return value is used in both a boolean context and
1969
        to assign a variable:
1970
        @code
1971
        if( auto p = jv.if_array() )
1972
            return *p;
1973
        @endcode
1974
1975
        @par Complexity
1976
        Constant.
1977
1978
        @par Exception Safety
1979
        No-throw guarantee.
1980
    */
1981
    array*
1982
    if_array() noexcept
1983
    {
1984
        if(kind() == json::kind::array)
1985
            return &arr_;
1986
        return nullptr;
1987
    }
1988
1989
    /** Return an @ref object pointer if this is an object, else return `nullptr`
1990
1991
        If `this->kind() == kind::object`, returns a pointer
1992
        to the underlying object. Otherwise, returns `nullptr`.
1993
1994
        @par Example
1995
        The return value is used in both a boolean context and
1996
        to assign a variable:
1997
        @code
1998
        if( auto p = jv.if_object() )
1999
            return *p;
2000
        @endcode
2001
2002
        @par Complexity
2003
        Constant.
2004
2005
        @par Exception Safety
2006
        No-throw guarantee.
2007
    */
2008
    object const*
2009
    if_object() const noexcept
2010
    {
2011
        if(kind() == json::kind::object)
2012
            return &obj_;
2013
        return nullptr;
2014
    }
2015
2016
    /** Return an @ref object pointer if this is an object, else return `nullptr`
2017
2018
        If `this->kind() == kind::object`, returns a pointer
2019
        to the underlying object. Otherwise, returns `nullptr`.
2020
2021
        @par Example
2022
        The return value is used in both a boolean context and
2023
        to assign a variable:
2024
        @code
2025
        if( auto p = jv.if_object() )
2026
            return *p;
2027
        @endcode
2028
2029
        @par Complexity
2030
        Constant.
2031
2032
        @par Exception Safety
2033
        No-throw guarantee.
2034
    */
2035
    object*
2036
    if_object() noexcept
2037
    {
2038
        if(kind() == json::kind::object)
2039
            return &obj_;
2040
        return nullptr;
2041
    }
2042
2043
    /** Return a @ref string pointer if this is a string, else return `nullptr`
2044
2045
        If `this->kind() == kind::string`, returns a pointer
2046
        to the underlying object. Otherwise, returns `nullptr`.
2047
2048
        @par Example
2049
        The return value is used in both a boolean context and
2050
        to assign a variable:
2051
        @code
2052
        if( auto p = jv.if_string() )
2053
            return *p;
2054
        @endcode
2055
2056
        @par Complexity
2057
        Constant.
2058
2059
        @par Exception Safety
2060
        No-throw guarantee.
2061
    */
2062
    string const*
2063
    if_string() const noexcept
2064
    {
2065
        if(kind() == json::kind::string)
2066
            return &str_;
2067
        return nullptr;
2068
    }
2069
2070
    /** Return a @ref string pointer if this is a string, else return `nullptr`
2071
2072
        If `this->kind() == kind::string`, returns a pointer
2073
        to the underlying object. Otherwise, returns `nullptr`.
2074
2075
        @par Example
2076
        The return value is used in both a boolean context and
2077
        to assign a variable:
2078
        @code
2079
        if( auto p = jv.if_string() )
2080
            return *p;
2081
        @endcode
2082
2083
        @par Complexity
2084
        Constant.
2085
2086
        @par Exception Safety
2087
        No-throw guarantee.
2088
    */
2089
    string*
2090
    if_string() noexcept
2091
    {
2092
        if(kind() == json::kind::string)
2093
            return &str_;
2094
        return nullptr;
2095
    }
2096
2097
    /** Return an `int64_t` pointer if this is a signed integer, else return `nullptr`
2098
2099
        If `this->kind() == kind::int64`, returns a pointer
2100
        to the underlying integer. Otherwise, returns `nullptr`.
2101
2102
        @par Example
2103
        The return value is used in both a boolean context and
2104
        to assign a variable:
2105
        @code
2106
        if( auto p = jv.if_int64() )
2107
            return *p;
2108
        @endcode
2109
2110
        @par Complexity
2111
        Constant.
2112
2113
        @par Exception Safety
2114
        No-throw guarantee.
2115
    */
2116
    std::int64_t const*
2117
    if_int64() const noexcept
2118
    {
2119
        if(kind() == json::kind::int64)
2120
            return &sca_.i;
2121
        return nullptr;
2122
    }
2123
2124
    /** Return an `int64_t` pointer if this is a signed integer, else return `nullptr`
2125
2126
        If `this->kind() == kind::int64`, returns a pointer
2127
        to the underlying integer. Otherwise, returns `nullptr`.
2128
2129
        @par Example
2130
        The return value is used in both a boolean context and
2131
        to assign a variable:
2132
        @code
2133
        if( auto p = jv.if_int64() )
2134
            return *p;
2135
        @endcode
2136
2137
        @par Complexity
2138
        Constant.
2139
2140
        @par Exception Safety
2141
        No-throw guarantee.
2142
    */
2143
    std::int64_t*
2144
    if_int64() noexcept
2145
    {
2146
        if(kind() == json::kind::int64)
2147
            return &sca_.i;
2148
        return nullptr;
2149
    }
2150
2151
    /** Return a `uint64_t` pointer if this is an unsigned integer, else return `nullptr`
2152
2153
        If `this->kind() == kind::uint64`, returns a pointer
2154
        to the underlying unsigned integer. Otherwise, returns
2155
        `nullptr`.
2156
2157
        @par Example
2158
        The return value is used in both a boolean context and
2159
        to assign a variable:
2160
        @code
2161
        if( auto p = jv.if_uint64() )
2162
            return *p;
2163
        @endcode
2164
2165
        @par Complexity
2166
        Constant.
2167
2168
        @par Exception Safety
2169
        No-throw guarantee.
2170
    */
2171
    std::uint64_t const*
2172
    if_uint64() const noexcept
2173
    {
2174
        if(kind() == json::kind::uint64)
2175
            return &sca_.u;
2176
        return nullptr;
2177
    }
2178
2179
    /** Return a `uint64_t` pointer if this is an unsigned integer, else return `nullptr`
2180
2181
        If `this->kind() == kind::uint64`, returns a pointer
2182
        to the underlying unsigned integer. Otherwise, returns
2183
        `nullptr`.
2184
2185
        @par Example
2186
        The return value is used in both a boolean context and
2187
        to assign a variable:
2188
        @code
2189
        if( auto p = jv.if_uint64() )
2190
            return *p;
2191
        @endcode
2192
2193
        @par Complexity
2194
        Constant.
2195
2196
        @par Exception Safety
2197
        No-throw guarantee.
2198
    */
2199
    std::uint64_t*
2200
    if_uint64() noexcept
2201
    {
2202
        if(kind() == json::kind::uint64)
2203
            return &sca_.u;
2204
        return nullptr;
2205
    }
2206
2207
    /** Return a `double` pointer if this is a double, else return `nullptr`
2208
2209
        If `this->kind() == kind::double_`, returns a pointer
2210
        to the underlying double. Otherwise, returns
2211
        `nullptr`.
2212
2213
        @par Example
2214
        The return value is used in both a boolean context and
2215
        to assign a variable:
2216
        @code
2217
        if( auto p = jv.if_double() )
2218
            return *p;
2219
        @endcode
2220
2221
        @par Complexity
2222
        Constant.
2223
2224
        @par Exception Safety
2225
        No-throw guarantee.
2226
    */
2227
    double const*
2228
    if_double() const noexcept
2229
    {
2230
        if(kind() == json::kind::double_)
2231
            return &sca_.d;
2232
        return nullptr;
2233
    }
2234
2235
    /** Return a `double` pointer if this is a double, else return `nullptr`
2236
2237
        If `this->kind() == kind::double_`, returns a pointer
2238
        to the underlying double. Otherwise, returns
2239
        `nullptr`.
2240
2241
        @par Example
2242
        The return value is used in both a boolean context and
2243
        to assign a variable:
2244
        @code
2245
        if( auto p = jv.if_double() )
2246
            return *p;
2247
        @endcode
2248
2249
        @par Complexity
2250
        Constant.
2251
2252
        @par Exception Safety
2253
        No-throw guarantee.
2254
    */
2255
    double*
2256
    if_double() noexcept
2257
    {
2258
        if(kind() == json::kind::double_)
2259
            return &sca_.d;
2260
        return nullptr;
2261
    }
2262
2263
    /** Return a `bool` pointer if this is a boolean, else return `nullptr`
2264
2265
        If `this->kind() == kind::bool_`, returns a pointer
2266
        to the underlying boolean. Otherwise, returns
2267
        `nullptr`.
2268
2269
        @par Example
2270
        The return value is used in both a boolean context and
2271
        to assign a variable:
2272
        @code
2273
        if( auto p = jv.if_bool() )
2274
            return *p;
2275
        @endcode
2276
2277
        @par Complexity
2278
        Constant.
2279
2280
        @par Exception Safety
2281
        No-throw guarantee.
2282
    */
2283
    bool const*
2284
    if_bool() const noexcept
2285
    {
2286
        if(kind() == json::kind::bool_)
2287
            return &sca_.b;
2288
        return nullptr;
2289
    }
2290
2291
    /** Return a `bool` pointer if this is a boolean, else return `nullptr`
2292
2293
        If `this->kind() == kind::bool_`, returns a pointer
2294
        to the underlying boolean. Otherwise, returns
2295
        `nullptr`.
2296
2297
        @par Example
2298
        The return value is used in both a boolean context and
2299
        to assign a variable:
2300
        @code
2301
        if( auto p = jv.if_bool() )
2302
            return *p;
2303
        @endcode
2304
2305
        @par Complexity
2306
        Constant.
2307
2308
        @par Exception Safety
2309
        No-throw guarantee.
2310
    */
2311
    bool*
2312
    if_bool() noexcept
2313
    {
2314
        if(kind() == json::kind::bool_)
2315
            return &sca_.b;
2316
        return nullptr;
2317
    }
2318
2319
    //------------------------------------------------------
2320
2321
    /** Return the stored number cast to an arithmetic type.
2322
2323
        This function attempts to return the stored value
2324
        converted to the arithmetic type `T` which may not
2325
        be `bool`:
2326
2327
        @li If `T` is an integral type and the stored
2328
        value is a number which can be losslessly converted,
2329
        the conversion is performed without error and the
2330
        converted number is returned.
2331
2332
        @li If `T` is an integral type and the stored value
2333
        is a number which cannot be losslessly converted,
2334
        then the operation fails with an error.
2335
2336
        @li If `T` is a floating point type and the stored
2337
        value is a number, the conversion is performed
2338
        without error. The converted number is returned,
2339
        with a possible loss of precision.
2340
2341
        @li Otherwise, if the stored value is not a number;
2342
        that is, if `this->is_number()` returns `false`, then
2343
        the operation fails with an error.
2344
2345
        @par Constraints
2346
        @code
2347
        std::is_arithmetic< T >::value && ! std::is_same< T, bool >::value
2348
        @endcode
2349
2350
        @par Complexity
2351
        Constant.
2352
2353
        @par Exception Safety
2354
        No-throw guarantee.
2355
2356
        @return The converted number.
2357
2358
        @param ec Set to the error, if any occurred.
2359
    */
2360
/** @{ */
2361
    template<class T>
2362
#ifdef BOOST_JSON_DOCS
2363
    T
2364
#else
2365
    typename std::enable_if<
2366
        std::is_arithmetic<T>::value &&
2367
        ! std::is_same<T, bool>::value,
2368
            T>::type
2369
#endif
2370
    to_number(error_code& ec) const noexcept
2371
    {
2372
        error e;
2373
        auto result = to_number<T>(e);
2374
        BOOST_JSON_FAIL(ec, e);
2375
        return result;
2376
    }
2377
2378
    template<class T>
2379
#ifdef BOOST_JSON_DOCS
2380
    T
2381
#else
2382
    typename std::enable_if<
2383
        std::is_arithmetic<T>::value &&
2384
        ! std::is_same<T, bool>::value,
2385
            T>::type
2386
#endif
2387
    to_number(std::error_code& ec) const noexcept
2388
    {
2389
        error_code jec;
2390
        auto result = to_number<T>(jec);
2391
        ec = jec;
2392
        return result;
2393
    }
2394
/** @} */
2395
2396
    /** Return the stored number cast to an arithmetic type.
2397
2398
        This function attempts to return the stored value
2399
        converted to the arithmetic type `T` which may not
2400
        be `bool`:
2401
2402
        @li If `T` is an integral type and the stored
2403
        value is a number which can be losslessly converted,
2404
        the conversion is performed without error and the
2405
        converted number is returned.
2406
2407
        @li If `T` is an integral type and the stored value
2408
        is a number which cannot be losslessly converted,
2409
        then the operation fails with an error.
2410
2411
        @li If `T` is a floating point type and the stored
2412
        value is a number, the conversion is performed
2413
        without error. The converted number is returned,
2414
        with a possible loss of precision.
2415
2416
        @li Otherwise, if the stored value is not a number;
2417
        that is, if `this->is_number()` returns `false`, then
2418
        the operation fails with an error.
2419
2420
        @par Constraints
2421
        @code
2422
        std::is_arithmetic< T >::value && ! std::is_same< T, bool >::value
2423
        @endcode
2424
2425
        @par Complexity
2426
        Constant.
2427
2428
        @return The converted number.
2429
2430
        @throw system_error on error.
2431
    */
2432
    template<class T>
2433
#ifdef BOOST_JSON_DOCS
2434
    T
2435
#else
2436
    typename std::enable_if<
2437
        std::is_arithmetic<T>::value &&
2438
        ! std::is_same<T, bool>::value,
2439
            T>::type
2440
#endif
2441
    to_number() const
2442
    {
2443
        error e;
2444
        auto result = to_number<T>(e);
2445
        if( e != error() )
2446
        {
2447
            BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2448
            detail::throw_system_error( e, &loc );
2449
        }
2450
        return result;
2451
    }
2452
2453
    //------------------------------------------------------
2454
    //
2455
    // Accessors
2456
    //
2457
    //------------------------------------------------------
2458
2459
    /** Return the memory resource associated with the value.
2460
2461
        This returns a pointer to the memory resource
2462
        that was used to construct the value.
2463
2464
        @par Complexity
2465
        Constant.
2466
2467
        @par Exception Safety
2468
        No-throw guarantee.
2469
    */
2470
    storage_ptr const&
2471
    storage() const noexcept
2472
922k
    {
2473
922k
        return sp_;
2474
922k
    }
2475
2476
    /** Return the associated @ref memory_resource
2477
2478
        This function returns an instance of
2479
        @ref polymorphic_allocator constructed from the
2480
        associated @ref memory_resource.
2481
2482
        @par Complexity
2483
        Constant.
2484
2485
        @par Exception Safety
2486
        No-throw guarantee.
2487
    */
2488
    allocator_type
2489
    get_allocator() const noexcept
2490
    {
2491
        return sp_.get();
2492
    }
2493
2494
    //------------------------------------------------------
2495
2496
    /** Return a reference to the underlying `object`, or throw an exception.
2497
2498
        If @ref is_object() is `true`, returns
2499
        a reference to the underlying @ref object,
2500
        otherwise throws an exception.
2501
2502
        @par Complexity
2503
        Constant.
2504
2505
        @par Exception Safety
2506
        Strong guarantee.
2507
2508
        @throw system_error `! this->is_object()`
2509
    */
2510
    /* @{ */
2511
    object&
2512
    as_object() &
2513
    {
2514
        auto const& self = *this;
2515
        return const_cast<object&>( self.as_object() );
2516
    }
2517
2518
    object&&
2519
    as_object() &&
2520
    {
2521
        return std::move( as_object() );
2522
    }
2523
2524
    object const&
2525
    as_object() const&
2526
    {
2527
        if( is_object() )
2528
            return obj_;
2529
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2530
        detail::throw_system_error( error::not_object, &loc );
2531
    }
2532
    /* @} */
2533
2534
    /** Return a reference to the underlying @ref array, or throw an exception.
2535
2536
        If @ref is_array() is `true`, returns
2537
        a reference to the underlying @ref array,
2538
        otherwise throws an exception.
2539
2540
        @par Complexity
2541
        Constant.
2542
2543
        @par Exception Safety
2544
        Strong guarantee.
2545
2546
        @throw system_error `! this->is_array()`
2547
    */
2548
    /* @{ */
2549
    array&
2550
    as_array() &
2551
    {
2552
        auto const& self = *this;
2553
        return const_cast<array&>( self.as_array() );
2554
    }
2555
2556
    array&&
2557
    as_array() &&
2558
    {
2559
        return std::move( as_array() );
2560
    }
2561
2562
    array const&
2563
    as_array() const&
2564
    {
2565
        if( is_array() )
2566
            return arr_;
2567
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2568
        detail::throw_system_error( error::not_array, &loc );
2569
    }
2570
    /* @} */
2571
2572
    /** Return a reference to the underlying `string`, or throw an exception.
2573
2574
        If @ref is_string() is `true`, returns
2575
        a reference to the underlying @ref string,
2576
        otherwise throws an exception.
2577
2578
        @par Complexity
2579
        Constant.
2580
2581
        @par Exception Safety
2582
        Strong guarantee.
2583
2584
        @throw system_error `! this->is_string()`
2585
    */
2586
    /* @{ */
2587
    string&
2588
    as_string() &
2589
    {
2590
        auto const& self = *this;
2591
        return const_cast<string&>( self.as_string() );
2592
    }
2593
2594
    string&&
2595
    as_string() &&
2596
    {
2597
        return std::move( as_string() );
2598
    }
2599
2600
    string const&
2601
    as_string() const&
2602
    {
2603
        if( is_string() )
2604
            return str_;
2605
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2606
        detail::throw_system_error( error::not_string, &loc );
2607
    }
2608
    /* @} */
2609
2610
    /** Return a reference to the underlying `std::int64_t`, or throw an exception.
2611
2612
        If @ref is_int64() is `true`, returns
2613
        a reference to the underlying `std::int64_t`,
2614
        otherwise throws an exception.
2615
2616
        @par Complexity
2617
        Constant.
2618
2619
        @par Exception Safety
2620
        Strong guarantee.
2621
2622
        @throw system_error `! this->is_int64()`
2623
    */
2624
    std::int64_t&
2625
    as_int64()
2626
    {
2627
        if( is_int64() )
2628
            return sca_.i;
2629
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2630
        detail::throw_system_error( error::not_int64, &loc );
2631
    }
2632
2633
    /** Return the underlying `std::int64_t`, or throw an exception.
2634
2635
        If @ref is_int64() is `true`, returns
2636
        the underlying `std::int64_t`,
2637
        otherwise throws an exception.
2638
2639
        @par Complexity
2640
        Constant.
2641
2642
        @par Exception Safety
2643
        Strong guarantee.
2644
2645
        @throw system_error `! this->is_int64()`
2646
    */
2647
    std::int64_t
2648
    as_int64() const
2649
    {
2650
        if( is_int64() )
2651
            return sca_.i;
2652
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2653
        detail::throw_system_error( error::not_int64, &loc );
2654
    }
2655
2656
    /** Return a reference to the underlying `std::uint64_t`, or throw an exception.
2657
2658
        If @ref is_uint64() is `true`, returns
2659
        a reference to the underlying `std::uint64_t`,
2660
        otherwise throws an exception.
2661
2662
        @par Complexity
2663
        Constant.
2664
2665
        @par Exception Safety
2666
        Strong guarantee.
2667
2668
        @throw system_error `! this->is_uint64()`
2669
    */
2670
    std::uint64_t&
2671
    as_uint64()
2672
    {
2673
        if( is_uint64() )
2674
            return sca_.u;
2675
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2676
        detail::throw_system_error( error::not_uint64, &loc );
2677
    }
2678
2679
    /** Return the underlying `std::uint64_t`, or throw an exception.
2680
2681
        If @ref is_uint64() is `true`, returns
2682
        the underlying `std::uint64_t`,
2683
        otherwise throws an exception.
2684
2685
        @par Complexity
2686
        Constant.
2687
2688
        @par Exception Safety
2689
        Strong guarantee.
2690
2691
        @throw system_error `! this->is_uint64()`
2692
    */
2693
    std::uint64_t
2694
    as_uint64() const
2695
    {
2696
        if( is_uint64() )
2697
            return sca_.u;
2698
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2699
        detail::throw_system_error( error::not_uint64, &loc );
2700
    }
2701
2702
    /** Return a reference to the underlying `double`, or throw an exception.
2703
2704
        If @ref is_double() is `true`, returns
2705
        a reference to the underlying `double`,
2706
        otherwise throws an exception.
2707
2708
        @par Complexity
2709
        Constant.
2710
2711
        @par Exception Safety
2712
        Strong guarantee.
2713
2714
        @throw system_error `! this->is_double()`
2715
    */
2716
    double&
2717
    as_double()
2718
    {
2719
        if( is_double() )
2720
            return sca_.d;
2721
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2722
        detail::throw_system_error( error::not_double, &loc );
2723
    }
2724
2725
    /** Return the underlying `double`, or throw an exception.
2726
2727
        If @ref is_double() is `true`, returns
2728
        the underlying `double`,
2729
        otherwise throws an exception.
2730
2731
        @par Complexity
2732
        Constant.
2733
2734
        @par Exception Safety
2735
        Strong guarantee.
2736
2737
        @throw system_error `! this->is_double()`
2738
    */
2739
    double
2740
    as_double() const
2741
    {
2742
        if( is_double() )
2743
            return sca_.d;
2744
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2745
        detail::throw_system_error( error::not_double, &loc );
2746
    }
2747
2748
    /** Return a reference to the underlying `bool`, or throw an exception.
2749
2750
        If @ref is_bool() is `true`, returns
2751
        a reference to the underlying `bool`,
2752
        otherwise throws an exception.
2753
2754
        @par Complexity
2755
        Constant.
2756
2757
        @par Exception Safety
2758
        Strong guarantee.
2759
2760
        @throw system_error `! this->is_bool()`
2761
    */
2762
    bool&
2763
    as_bool()
2764
    {
2765
        if( is_bool() )
2766
            return sca_.b;
2767
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2768
        detail::throw_system_error( error::not_bool, &loc );
2769
    }
2770
2771
    /** Return the underlying `bool`, or throw an exception.
2772
2773
        If @ref is_bool() is `true`, returns
2774
        the underlying `bool`,
2775
        otherwise throws an exception.
2776
2777
        @par Complexity
2778
        Constant.
2779
2780
        @par Exception Safety
2781
        Strong guarantee.
2782
2783
        @throw system_error `! this->is_bool()`
2784
    */
2785
    bool
2786
    as_bool() const
2787
    {
2788
        if( is_bool() )
2789
            return sca_.b;
2790
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
2791
        detail::throw_system_error( error::not_bool, &loc );
2792
    }
2793
2794
    //------------------------------------------------------
2795
2796
    /** Return a reference to the underlying `object`, without checking.
2797
2798
        This is the fastest way to access the underlying
2799
        representation when the kind is known in advance.
2800
2801
        @par Preconditions
2802
2803
        @code
2804
        this->is_object()
2805
        @endcode
2806
2807
        @par Complexity
2808
        Constant.
2809
2810
        @par Exception Safety
2811
        No-throw guarantee.
2812
    */
2813
    /* @{ */
2814
    object&
2815
    get_object() & noexcept
2816
0
    {
2817
0
        BOOST_ASSERT(is_object());
2818
0
        return obj_;
2819
0
    }
2820
2821
    object&&
2822
    get_object() && noexcept
2823
    {
2824
        BOOST_ASSERT(is_object());
2825
        return std::move(obj_);
2826
    }
2827
2828
    object const&
2829
    get_object() const& noexcept
2830
0
    {
2831
0
        BOOST_ASSERT(is_object());
2832
0
        return obj_;
2833
0
    }
2834
    /* @} */
2835
2836
    /** Return a reference to the underlying `array`, without checking.
2837
2838
        This is the fastest way to access the underlying
2839
        representation when the kind is known in advance.
2840
2841
        @par Preconditions
2842
2843
        @code
2844
        this->is_array()
2845
        @endcode
2846
2847
        @par Complexity
2848
        Constant.
2849
2850
        @par Exception Safety
2851
        No-throw guarantee.
2852
    */
2853
    /* @{ */
2854
    array&
2855
    get_array() & noexcept
2856
0
    {
2857
0
        BOOST_ASSERT(is_array());
2858
0
        return arr_;
2859
0
    }
2860
2861
    array&&
2862
    get_array() && noexcept
2863
    {
2864
        BOOST_ASSERT(is_array());
2865
        return std::move(arr_);
2866
    }
2867
2868
    array const&
2869
    get_array() const& noexcept
2870
0
    {
2871
0
        BOOST_ASSERT(is_array());
2872
0
        return arr_;
2873
0
    }
2874
    /* @} */
2875
2876
    /** Return a reference to the underlying `string`, without checking.
2877
2878
        This is the fastest way to access the underlying
2879
        representation when the kind is known in advance.
2880
2881
        @par Preconditions
2882
2883
        @code
2884
        this->is_string()
2885
        @endcode
2886
2887
        @par Complexity
2888
        Constant.
2889
2890
        @par Exception Safety
2891
        No-throw guarantee.
2892
    */
2893
    /* @{ */
2894
    string&
2895
    get_string() & noexcept
2896
10.2k
    {
2897
10.2k
        BOOST_ASSERT(is_string());
2898
10.2k
        return str_;
2899
10.2k
    }
2900
2901
    string&&
2902
    get_string() && noexcept
2903
    {
2904
        BOOST_ASSERT(is_string());
2905
        return std::move(str_);
2906
    }
2907
2908
    string const&
2909
    get_string() const& noexcept
2910
0
    {
2911
0
        BOOST_ASSERT(is_string());
2912
0
        return str_;
2913
0
    }
2914
    /* @} */
2915
2916
    /** Return a reference to the underlying `std::int64_t`, without checking.
2917
2918
        This is the fastest way to access the underlying
2919
        representation when the kind is known in advance.
2920
2921
        @par Preconditions
2922
2923
        @code
2924
        this->is_int64()
2925
        @endcode
2926
2927
        @par Complexity
2928
        Constant.
2929
2930
        @par Exception Safety
2931
        No-throw guarantee.
2932
    */
2933
    std::int64_t&
2934
    get_int64() noexcept
2935
    {
2936
        BOOST_ASSERT(is_int64());
2937
        return sca_.i;
2938
    }
2939
2940
    /** Return the underlying `std::int64_t`, without checking.
2941
2942
        This is the fastest way to access the underlying
2943
        representation when the kind is known in advance.
2944
2945
        @par Preconditions
2946
2947
        @code
2948
        this->is_int64()
2949
        @endcode
2950
2951
        @par Complexity
2952
        Constant.
2953
2954
        @par Exception Safety
2955
        No-throw guarantee.
2956
    */
2957
    std::int64_t
2958
    get_int64() const noexcept
2959
0
    {
2960
0
        BOOST_ASSERT(is_int64());
2961
0
        return sca_.i;
2962
0
    }
2963
2964
    /** Return a reference to the underlying `std::uint64_t`, without checking.
2965
2966
        This is the fastest way to access the underlying
2967
        representation when the kind is known in advance.
2968
2969
        @par Preconditions
2970
2971
        @code
2972
        this->is_uint64()
2973
        @endcode
2974
2975
        @par Complexity
2976
        Constant.
2977
2978
        @par Exception Safety
2979
        No-throw guarantee.
2980
    */
2981
    std::uint64_t&
2982
    get_uint64() noexcept
2983
    {
2984
        BOOST_ASSERT(is_uint64());
2985
        return sca_.u;
2986
    }
2987
2988
    /** Return the underlying `std::uint64_t`, without checking.
2989
2990
        This is the fastest way to access the underlying
2991
        representation when the kind is known in advance.
2992
2993
        @par Preconditions
2994
2995
        @code
2996
        this->is_uint64()
2997
        @endcode
2998
2999
        @par Complexity
3000
        Constant.
3001
3002
        @par Exception Safety
3003
        No-throw guarantee.
3004
    */
3005
    std::uint64_t
3006
    get_uint64() const noexcept
3007
0
    {
3008
0
        BOOST_ASSERT(is_uint64());
3009
0
        return sca_.u;
3010
0
    }
3011
3012
    /** Return a reference to the underlying `double`, without checking.
3013
3014
        This is the fastest way to access the underlying
3015
        representation when the kind is known in advance.
3016
3017
        @par Preconditions
3018
3019
        @code
3020
        this->is_double()
3021
        @endcode
3022
3023
        @par Complexity
3024
        Constant.
3025
3026
        @par Exception Safety
3027
        No-throw guarantee.
3028
    */
3029
    double&
3030
    get_double() noexcept
3031
    {
3032
        BOOST_ASSERT(is_double());
3033
        return sca_.d;
3034
    }
3035
3036
    /** Return the underlying `double`, without checking.
3037
3038
        This is the fastest way to access the underlying
3039
        representation when the kind is known in advance.
3040
3041
        @par Preconditions
3042
3043
        @code
3044
        this->is_double()
3045
        @endcode
3046
3047
        @par Complexity
3048
        Constant.
3049
3050
        @par Exception Safety
3051
        No-throw guarantee.
3052
    */
3053
    double
3054
    get_double() const noexcept
3055
0
    {
3056
0
        BOOST_ASSERT(is_double());
3057
0
        return sca_.d;
3058
0
    }
3059
3060
    /** Return a reference to the underlying `bool`, without checking.
3061
3062
        This is the fastest way to access the underlying
3063
        representation when the kind is known in advance.
3064
3065
        @par Preconditions
3066
3067
        @code
3068
        this->is_bool()
3069
        @endcode
3070
3071
        @par Complexity
3072
        Constant.
3073
3074
        @par Exception Safety
3075
        No-throw guarantee.
3076
    */
3077
    bool&
3078
    get_bool() noexcept
3079
    {
3080
        BOOST_ASSERT(is_bool());
3081
        return sca_.b;
3082
    }
3083
3084
    /** Return the underlying `bool`, without checking.
3085
3086
        This is the fastest way to access the underlying
3087
        representation when the kind is known in advance.
3088
3089
        @par Preconditions
3090
3091
        @code
3092
        this->is_bool()
3093
        @endcode
3094
3095
        @par Complexity
3096
        Constant.
3097
3098
        @par Exception Safety
3099
        No-throw guarantee.
3100
    */
3101
    bool
3102
    get_bool() const noexcept
3103
0
    {
3104
0
        BOOST_ASSERT(is_bool());
3105
0
        return sca_.b;
3106
0
    }
3107
3108
    //------------------------------------------------------
3109
3110
    /** Access an element, with bounds checking.
3111
3112
        This function is used to access elements of
3113
        the underlying object, or throw an exception
3114
        if the value is not an object.
3115
3116
        @par Complexity
3117
        Constant.
3118
3119
        @par Exception Safety
3120
        Strong guarantee.
3121
3122
        @param key The key of the element to find.
3123
3124
        @return `this->as_object().at( key )`.
3125
    */
3126
/** @{ */
3127
    value&
3128
    at(string_view key) &
3129
    {
3130
        return as_object().at(key);
3131
    }
3132
3133
    value&&
3134
    at(string_view key) &&
3135
    {
3136
        return std::move( as_object() ).at(key);
3137
    }
3138
3139
    value const&
3140
    at(string_view key) const&
3141
    {
3142
        return as_object().at(key);
3143
    }
3144
/** @} */
3145
3146
    /** Access an element, with bounds checking.
3147
3148
        This function is used to access elements of
3149
        the underlying array, or throw an exception
3150
        if the value is not an array.
3151
3152
        @par Complexity
3153
        Constant.
3154
3155
        @par Exception Safety
3156
        Strong guarantee.
3157
3158
        @param pos A zero-based array index.
3159
3160
        @return `this->as_array().at( pos )`.
3161
    */
3162
/** @{ */
3163
    value &
3164
    at(std::size_t pos) &
3165
    {
3166
        return as_array().at(pos);
3167
    }
3168
3169
    value&&
3170
    at(std::size_t pos) &&
3171
    {
3172
        return std::move( as_array() ).at(pos);
3173
    }
3174
3175
    value const&
3176
    at(std::size_t pos) const&
3177
    {
3178
        return as_array().at(pos);
3179
    }
3180
/** @} */
3181
3182
    /** Access an element via JSON Pointer.
3183
3184
        This function is used to access a (potentially nested)
3185
        element of the value using a JSON Pointer string.
3186
3187
        @par Complexity
3188
        Linear in the sizes of `ptr` and underlying array, object, or string.
3189
3190
        @par Exception Safety
3191
        Strong guarantee.
3192
3193
        @param ptr JSON Pointer string.
3194
3195
        @return reference to the element identified by `ptr`.
3196
3197
        @throw system_error if an error occurs.
3198
3199
        @see
3200
        <a href="https://datatracker.ietf.org/doc/html/rfc6901">
3201
            RFC 6901 - JavaScript Object Notation (JSON) Pointer</a>
3202
    */
3203
/** @{ */
3204
    BOOST_JSON_DECL
3205
    value const&
3206
    at_pointer(string_view ptr) const&;
3207
3208
    inline
3209
    value&&
3210
    at_pointer(string_view ptr) &&;
3211
3212
    inline
3213
    value&
3214
    at_pointer(string_view ptr) &;
3215
/** @} */
3216
3217
    /** Access an element via JSON Pointer.
3218
3219
        This function is used to access a (potentially nested)
3220
        element of the value using a JSON Pointer string.
3221
3222
        @par Complexity
3223
        Linear in the sizes of `ptr` and underlying array, object, or string.
3224
3225
        @par Exception Safety
3226
        No-throw guarantee.
3227
3228
        @param ptr JSON Pointer string.
3229
3230
        @param ec Set to the error, if any occurred.
3231
3232
        @return pointer to the element identified by `ptr`.
3233
3234
        @see
3235
        <a href="https://datatracker.ietf.org/doc/html/rfc6901">
3236
            RFC 6901 - JavaScript Object Notation (JSON) Pointer</a>
3237
    */
3238
/** @{ */
3239
    BOOST_JSON_DECL
3240
    value const*
3241
    find_pointer(string_view ptr, error_code& ec) const noexcept;
3242
3243
    BOOST_JSON_DECL
3244
    value*
3245
    find_pointer(string_view ptr, error_code& ec) noexcept;
3246
3247
    BOOST_JSON_DECL
3248
    value const*
3249
    find_pointer(string_view ptr, std::error_code& ec) const noexcept;
3250
3251
    BOOST_JSON_DECL
3252
    value*
3253
    find_pointer(string_view ptr, std::error_code& ec) noexcept;
3254
/** @} */
3255
3256
    //------------------------------------------------------
3257
3258
    /** Set an element via JSON Pointer.
3259
3260
        This function is used to insert or assign to a potentially nested
3261
        element of the value using a JSON Pointer string. The function may
3262
        create intermediate elements corresponding to pointer segments.
3263
        <br/>
3264
3265
        The particular conditions when and what kind of intermediate element
3266
        is created is governed by the `ptr` parameter.
3267
3268
        Each pointer token is considered in sequence. For each token
3269
3270
        - if the containing value is an @ref object, then a new `null`
3271
        element is created with key equal to unescaped token string; otherwise
3272
3273
        - if the containing value is an @ref array, and the token represents a
3274
        past-the-end marker, then a `null` element is appended to the array;
3275
        otherwise
3276
3277
        - if the containing value is an @ref array, and the token represents a
3278
        number, then if the difference between the number and array's size
3279
        is smaller than `opts.max_created_elements`, then the size of the
3280
        array is increased, so that the number can reference an element in the
3281
        array; otherwise
3282
3283
        - if the containing value is of different @ref kind and
3284
          `opts.replace_any_scalar` is `true`, or the value is `null`, then
3285
3286
           - if `opts.create_arrays` is `true` and the token either represents
3287
             past-the-end marker or a number, then the value is replaced with
3288
             an empty array and the token is considered again; otherwise
3289
3290
           - if `opts.create_objects` is `true`, then the value is replaced
3291
             with an empty object and the token is considered again; otherwise
3292
3293
        - an error is produced.
3294
3295
        @par Complexity
3296
        Linear in the sum of size of `ptr`, size of underlying array, object,
3297
        or string and `opts.max_created_elements`.
3298
3299
        @par Exception Safety
3300
        Basic guarantee.
3301
        Calls to `memory_resource::allocate` may throw.
3302
3303
        @param sv JSON Pointer string.
3304
3305
        @param ref The value to assign to pointed element.
3306
3307
        @param opts The options for the algorithm.
3308
3309
        @return Reference to the element identified by `ptr`.
3310
3311
        @see @ref set_pointer_options,
3312
        <a href="https://datatracker.ietf.org/doc/html/rfc6901">
3313
            RFC 6901 - JavaScript Object Notation (JSON) Pointer</a>.
3314
    */
3315
    BOOST_JSON_DECL
3316
    value&
3317
    set_at_pointer(
3318
        string_view sv,
3319
        value_ref ref,
3320
        set_pointer_options const& opts = {} );
3321
3322
    /** Set an element via JSON Pointer.
3323
3324
        This function is used to insert or assign to a potentially nested
3325
        element of the value using a JSON Pointer string. The function may
3326
        create intermediate elements corresponding to pointer segments.
3327
        <br/>
3328
3329
        The particular conditions when and what kind of intermediate element
3330
        is created is governed by the `ptr` parameter.
3331
3332
        Each pointer token is considered in sequence. For each token
3333
3334
        - if the containing value is an @ref object, then a new `null`
3335
          element is created with key equal to unescaped token string;
3336
          otherwise
3337
3338
        - if the containing value is an @ref array, and the token represents a
3339
          past-the-end marker, then a `null` element is appended to the array;
3340
          otherwise
3341
3342
        - if the containing value is an @ref array, and the token represents a
3343
          number, then if the difference between the number and array's size
3344
          is smaller than `opts.max_created_elements`, then the size of the
3345
          array is increased, so that the number can reference an element in the
3346
          array; otherwise
3347
3348
        - if the containing value is of different @ref kind and
3349
          `opts.replace_any_scalar` is `true`, or the value is `null`, then
3350
3351
           - if `opts.create_arrays` is `true` and the token either represents
3352
             past-the-end marker or a number, then the value is replaced with
3353
             an empty array and the token is considered again; otherwise
3354
3355
           - if `opts.create_objects` is `true`, then the value is replaced
3356
             with an empty object and the token is considered again; otherwise
3357
3358
        - an error is produced.
3359
3360
        @par Complexity
3361
        Linear in the sum of size of `ptr`, size of underlying array, object,
3362
        or string and `opts.max_created_elements`.
3363
3364
        @par Exception Safety
3365
        Basic guarantee.
3366
        Calls to `memory_resource::allocate` may throw.
3367
3368
        @param sv JSON Pointer string.
3369
3370
        @param ref The value to assign to pointed element.
3371
3372
        @param ec Set to the error, if any occurred.
3373
3374
        @param opts The options for the algorithm.
3375
3376
        @return Pointer to the element identified by `ptr`.
3377
3378
        @see @ref set_pointer_options,
3379
        <a href="https://datatracker.ietf.org/doc/html/rfc6901">
3380
            RFC 6901 - JavaScript Object Notation (JSON) Pointer</a>.
3381
    */
3382
/** @{ */
3383
    BOOST_JSON_DECL
3384
    value*
3385
    set_at_pointer(
3386
        string_view sv,
3387
        value_ref ref,
3388
        error_code& ec,
3389
        set_pointer_options const& opts = {} );
3390
3391
    BOOST_JSON_DECL
3392
    value*
3393
    set_at_pointer(
3394
        string_view sv,
3395
        value_ref ref,
3396
        std::error_code& ec,
3397
        set_pointer_options const& opts = {} );
3398
/** @} */
3399
3400
    //------------------------------------------------------
3401
3402
    /** Return `true` if two values are equal.
3403
3404
        Two values are equal when they are the
3405
        same kind and their referenced values
3406
        are equal, or when they are both integral
3407
        types and their integral representations
3408
        are equal.
3409
3410
        @par Complexity
3411
        Constant or linear in the size of
3412
        the array, object, or string.
3413
3414
        @par Exception Safety
3415
        No-throw guarantee.
3416
    */
3417
    // inline friend speeds up overload resolution
3418
    friend
3419
    bool
3420
    operator==(
3421
        value const& lhs,
3422
        value const& rhs) noexcept
3423
0
    {
3424
0
        return lhs.equal(rhs);
3425
0
    }
3426
3427
    /** Return `true` if two values are not equal.
3428
3429
        Two values are equal when they are the
3430
        same kind and their referenced values
3431
        are equal, or when they are both integral
3432
        types and their integral representations
3433
        are equal.
3434
3435
        @par Complexity
3436
        Constant or linear in the size of
3437
        the array, object, or string.
3438
3439
        @par Exception Safety
3440
        No-throw guarantee.
3441
    */
3442
    friend
3443
    bool
3444
    operator!=(
3445
        value const& lhs,
3446
        value const& rhs) noexcept
3447
0
    {
3448
0
        return ! (lhs == rhs);
3449
0
    }
3450
3451
    /** Serialize @ref value to an output stream.
3452
3453
        This function serializes a `value` as JSON into the output stream.
3454
3455
        @return Reference to `os`.
3456
3457
        @par Complexity
3458
        Constant or linear in the size of `jv`.
3459
3460
        @par Exception Safety
3461
        Strong guarantee.
3462
        Calls to `memory_resource::allocate` may throw.
3463
3464
        @param os The output stream to serialize to.
3465
3466
        @param jv The value to serialize.
3467
    */
3468
    BOOST_JSON_DECL
3469
    friend
3470
    std::ostream&
3471
    operator<<(
3472
        std::ostream& os,
3473
        value const& jv);
3474
3475
    /** Parse @ref value from an input stream.
3476
3477
        This function parses JSON from an input stream into a `value`. If
3478
        parsing fails, `std::ios_base::failbit` will be set for `is` and
3479
        `jv` will be left unchanged. Regardless of whether `skipws` flag is set
3480
        on `is`, consumes whitespace before and after JSON, because whitespace
3481
        is considered a part of JSON. Behaves as [_FormattedInputFunction_]
3482
        (https://en.cppreference.com/w/cpp/named_req/FormattedInputFunction).<br>
3483
3484
        Note: this operator cannot assume that the stream only contains a
3485
        single JSON document, which may result in **very underwhelming
3486
        performance**, if the stream isn't cooperative. If you know that your
3487
        input consists of a single JSON document, consider using @ref parse
3488
        function instead.
3489
3490
        @return Reference to `is`.
3491
3492
        @par Complexity
3493
        Linear in the size of JSON data.
3494
3495
        @par Exception Safety
3496
        Basic guarantee.
3497
        Calls to `memory_resource::allocate` may throw.
3498
        The stream may throw as configured by
3499
        [`std::ios::exceptions`](https://en.cppreference.com/w/cpp/io/basic_ios/exceptions).
3500
3501
        @param is The input stream to parse from.
3502
3503
        @param jv The value to parse into.
3504
3505
        @see @ref parse.
3506
    */
3507
    BOOST_JSON_DECL
3508
    friend
3509
    std::istream&
3510
    operator>>(
3511
        std::istream& is,
3512
        value& jv);
3513
3514
    /** Helper for `boost::hash` support
3515
3516
        Computes a hash value for `jv`. This function is used by
3517
        `boost::hash<value>`. Similar overloads for @ref array, @ref object,
3518
        and @ref string do not exist, because those types are supported by
3519
        `boost::hash` out of the box.
3520
3521
        @return hash value for `jv`.
3522
3523
        @param jv `value` for which a hash is to be computed.
3524
3525
        @see [Boost.ContainerHash](https://boost.org/libs/container_hash).
3526
     */
3527
#ifndef BOOST_JSON_DOCS
3528
    template<
3529
        class T,
3530
        typename std::enable_if<
3531
            std::is_same< detail::remove_cvref<T>, value >::value >::type*
3532
                = nullptr>
3533
    friend
3534
    std::size_t
3535
    hash_value( T const& jv ) noexcept
3536
#else
3537
    friend
3538
    inline
3539
    std::size_t
3540
    hash_value( value const& jv ) noexcept
3541
#endif
3542
0
    {
3543
0
        return detail::hash_value_impl(jv);
3544
0
    }
3545
3546
private:
3547
    static
3548
    void
3549
    relocate(
3550
        value* dest,
3551
        value const& src) noexcept
3552
925k
    {
3553
925k
        std::memcpy(
3554
925k
            static_cast<void*>(dest),
3555
925k
            &src,
3556
925k
            sizeof(src));
3557
925k
    }
3558
3559
    BOOST_JSON_DECL
3560
    storage_ptr
3561
    destroy() noexcept;
3562
3563
    BOOST_JSON_DECL
3564
    bool
3565
    equal(value const& other) const noexcept;
3566
3567
    template<class T>
3568
    auto
3569
    to_number(error& e) const noexcept ->
3570
        typename std::enable_if<
3571
            std::is_signed<T>::value &&
3572
            ! std::is_floating_point<T>::value,
3573
                T>::type
3574
    {
3575
        if(sca_.k == json::kind::int64)
3576
        {
3577
            auto const i = sca_.i;
3578
            if( i >= (std::numeric_limits<T>::min)() &&
3579
                i <= (std::numeric_limits<T>::max)())
3580
            {
3581
                e = {};
3582
                return static_cast<T>(i);
3583
            }
3584
            e = error::not_exact;
3585
        }
3586
        else if(sca_.k == json::kind::uint64)
3587
        {
3588
            auto const u = sca_.u;
3589
            if(u <= static_cast<std::uint64_t>((
3590
                std::numeric_limits<T>::max)()))
3591
            {
3592
                e = {};
3593
                return static_cast<T>(u);
3594
            }
3595
            e = error::not_exact;
3596
        }
3597
        else if(sca_.k == json::kind::double_)
3598
        {
3599
            auto const d = sca_.d;
3600
            if( d >= static_cast<double>(
3601
                    (detail::to_number_limit<T>::min)()) &&
3602
                d <= static_cast<double>(
3603
                    (detail::to_number_limit<T>::max)()) &&
3604
                static_cast<T>(d) == d)
3605
            {
3606
                e = {};
3607
                return static_cast<T>(d);
3608
            }
3609
            e = error::not_exact;
3610
        }
3611
        else
3612
        {
3613
            e = error::not_number;
3614
        }
3615
        return T{};
3616
    }
3617
3618
    template<class T>
3619
    auto
3620
    to_number(error& e) const noexcept ->
3621
        typename std::enable_if<
3622
            std::is_unsigned<T>::value &&
3623
            ! std::is_same<T, bool>::value,
3624
                T>::type
3625
    {
3626
        if(sca_.k == json::kind::int64)
3627
        {
3628
            auto const i = sca_.i;
3629
            if( i >= 0 && static_cast<std::uint64_t>(i) <=
3630
                (std::numeric_limits<T>::max)())
3631
            {
3632
                e = {};
3633
                return static_cast<T>(i);
3634
            }
3635
            e = error::not_exact;
3636
        }
3637
        else if(sca_.k == json::kind::uint64)
3638
        {
3639
            auto const u = sca_.u;
3640
            if(u <= (std::numeric_limits<T>::max)())
3641
            {
3642
                e = {};
3643
                return static_cast<T>(u);
3644
            }
3645
            e = error::not_exact;
3646
        }
3647
        else if(sca_.k == json::kind::double_)
3648
        {
3649
            auto const d = sca_.d;
3650
            if( d >= 0 &&
3651
                d <= (detail::to_number_limit<T>::max)() &&
3652
                static_cast<T>(d) == d)
3653
            {
3654
                e = {};
3655
                return static_cast<T>(d);
3656
            }
3657
            e = error::not_exact;
3658
        }
3659
        else
3660
        {
3661
            e = error::not_number;
3662
        }
3663
        return T{};
3664
    }
3665
3666
    template<class T>
3667
    auto
3668
    to_number(error& e) const noexcept ->
3669
        typename std::enable_if<
3670
            std::is_floating_point<
3671
                T>::value, T>::type
3672
    {
3673
        if(sca_.k == json::kind::int64)
3674
        {
3675
            e = {};
3676
            return static_cast<T>(sca_.i);
3677
        }
3678
        if(sca_.k == json::kind::uint64)
3679
        {
3680
            e = {};
3681
            return static_cast<T>(sca_.u);
3682
        }
3683
        if(sca_.k == json::kind::double_)
3684
        {
3685
            e = {};
3686
            return static_cast<T>(sca_.d);
3687
        }
3688
        e = error::not_number;
3689
        return {};
3690
    }
3691
};
3692
3693
// Make sure things are as big as we think they should be
3694
#if BOOST_JSON_ARCH == 64
3695
BOOST_STATIC_ASSERT(sizeof(value) == 24);
3696
#elif BOOST_JSON_ARCH == 32
3697
BOOST_STATIC_ASSERT(sizeof(value) == 16);
3698
#else
3699
# error Unknown architecture
3700
#endif
3701
3702
//----------------------------------------------------------
3703
3704
/** A key/value pair.
3705
3706
    This is the type of element used by the @ref object
3707
    container.
3708
*/
3709
class key_value_pair
3710
{
3711
#ifndef BOOST_JSON_DOCS
3712
    friend struct detail::access;
3713
    using access = detail::access;
3714
#endif
3715
3716
    BOOST_JSON_DECL
3717
    static char const empty_[1];
3718
3719
    inline
3720
    key_value_pair(
3721
        pilfered<json::value> k,
3722
        pilfered<json::value> v) noexcept;
3723
3724
public:
3725
    /// Copy assignment (deleted).
3726
    key_value_pair&
3727
    operator=(key_value_pair const&) = delete;
3728
3729
    /** Destructor.
3730
3731
        The value is destroyed and all internally
3732
        allocated memory is freed.
3733
    */
3734
    ~key_value_pair() noexcept
3735
922k
    {
3736
922k
        auto const& sp = value_.storage();
3737
922k
        if(sp.is_not_shared_and_deallocate_is_trivial())
3738
0
            return;
3739
922k
        if(key_ == empty_)
3740
0
            return;
3741
922k
        sp->deallocate(const_cast<char*>(key_),
3742
922k
            len_ + 1, alignof(char));
3743
922k
    }
3744
3745
    /** Copy constructor.
3746
3747
        This constructs a key/value pair with a
3748
        copy of another key/value pair, using
3749
        the same memory resource as `other`.
3750
3751
        @par Exception Safety
3752
        Strong guarantee.
3753
        Calls to `memory_resource::allocate` may throw.
3754
3755
        @param other The key/value pair to copy.
3756
    */
3757
    key_value_pair(
3758
        key_value_pair const& other)
3759
        : key_value_pair(other,
3760
            other.storage())
3761
0
    {
3762
0
    }
3763
3764
    /** Copy constructor.
3765
3766
        This constructs a key/value pair with a
3767
        copy of another key/value pair, using
3768
        the specified memory resource.
3769
3770
        @par Exception Safety
3771
        Strong guarantee.
3772
        Calls to `memory_resource::allocate` may throw.
3773
3774
        @param other The key/value pair to copy.
3775
3776
        @param sp A pointer to the @ref memory_resource
3777
        to use. The element will acquire shared
3778
        ownership of the memory resource.
3779
    */
3780
    BOOST_JSON_DECL
3781
    key_value_pair(
3782
        key_value_pair const& other,
3783
        storage_ptr sp);
3784
3785
    /** Move constructor.
3786
3787
        The pair is constructed by acquiring
3788
        ownership of the contents of `other` and
3789
        shared ownership of `other`'s memory resource.
3790
3791
        @note
3792
3793
        After construction, the moved-from pair holds an
3794
        empty key, and a null value with its current
3795
        storage pointer.
3796
3797
        @par Complexity
3798
        Constant.
3799
3800
        @par Exception Safety
3801
        No-throw guarantee.
3802
3803
        @param other The pair to move.
3804
    */
3805
    key_value_pair(
3806
        key_value_pair&& other) noexcept
3807
        : value_(std::move(other.value_))
3808
        , key_(detail::exchange(
3809
            other.key_, empty_))
3810
        , len_(detail::exchange(
3811
            other.len_, 0))
3812
    {
3813
    }
3814
3815
    /** Pilfer constructor.
3816
3817
        The pair is constructed by acquiring ownership
3818
        of the contents of `other` using pilfer semantics.
3819
        This is more efficient than move construction, when
3820
        it is known that the moved-from object will be
3821
        immediately destroyed afterwards.
3822
3823
        @par Complexity
3824
        Constant.
3825
3826
        @par Exception Safety
3827
        No-throw guarantee.
3828
3829
        @param other The value to pilfer. After pilfer
3830
        construction, `other` is not in a usable state
3831
        and may only be destroyed.
3832
3833
        @see @ref pilfer,
3834
            <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
3835
                Valueless Variants Considered Harmful</a>
3836
    */
3837
    key_value_pair(
3838
        pilfered<key_value_pair> other) noexcept
3839
        : value_(pilfer(other.get().value_))
3840
        , key_(detail::exchange(
3841
            other.get().key_, empty_))
3842
        , len_(detail::exchange(
3843
            other.get().len_, 0))
3844
0
    {
3845
0
    }
3846
3847
    /** Constructor.
3848
3849
        This constructs a key/value pair.
3850
3851
        @par Exception Safety
3852
        Strong guarantee.
3853
        Calls to `memory_resource::allocate` may throw.
3854
3855
        @param key The key string to use.
3856
3857
        @param args Optional arguments forwarded to
3858
        the @ref value constructor.
3859
    */
3860
    template<class... Args>
3861
    explicit
3862
    key_value_pair(
3863
        string_view key,
3864
        Args&&... args)
3865
        : value_(std::forward<Args>(args)...)
3866
0
    {
3867
0
        if(key.size() > string::max_size())
3868
0
        {
3869
0
            BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
3870
0
            detail::throw_system_error( error::key_too_large, &loc );
3871
0
        }
3872
0
        auto s = reinterpret_cast<
3873
0
            char*>(value_.storage()->
3874
0
                allocate(key.size() + 1, alignof(char)));
3875
0
        std::memcpy(s, key.data(), key.size());
3876
0
        s[key.size()] = 0;
3877
0
        key_ = s;
3878
0
        len_ = static_cast<
3879
0
            std::uint32_t>(key.size());
3880
0
    }
Unexecuted instantiation: boost::json::key_value_pair::key_value_pair<boost::json::value>(boost::core::basic_string_view<char>, boost::json::value&&)
Unexecuted instantiation: boost::json::key_value_pair::key_value_pair<decltype(nullptr), boost::json::storage_ptr&>(boost::core::basic_string_view<char>, decltype(nullptr)&&, boost::json::storage_ptr&)
Unexecuted instantiation: boost::json::key_value_pair::key_value_pair<boost::json::value, boost::json::storage_ptr&>(boost::core::basic_string_view<char>, boost::json::value&&, boost::json::storage_ptr&)
3881
3882
    /** Constructor.
3883
3884
        This constructs a key/value pair. A
3885
        copy of the specified value is made,
3886
        using the specified memory resource.
3887
3888
        @par Exception Safety
3889
        Strong guarantee.
3890
        Calls to `memory_resource::allocate` may throw.
3891
3892
        @param p A `std::pair` with the key
3893
            string and @ref value to construct with.
3894
3895
        @param sp A pointer to the @ref memory_resource
3896
        to use. The element will acquire shared
3897
        ownership of the memory resource.
3898
    */
3899
    explicit
3900
    key_value_pair(
3901
        std::pair<
3902
            string_view,
3903
            json::value> const& p,
3904
        storage_ptr sp = {})
3905
        : key_value_pair(
3906
            p.first,
3907
            p.second,
3908
            std::move(sp))
3909
    {
3910
    }
3911
3912
    /** Constructor.
3913
3914
        This constructs a key/value pair.
3915
        Ownership of the specified value is
3916
        transferred by move construction.
3917
3918
        @par Exception Safety
3919
        Strong guarantee.
3920
        Calls to `memory_resource::allocate` may throw.
3921
3922
        @param p A `std::pair` with the key
3923
            string and @ref value to construct with.
3924
3925
        @param sp A pointer to the @ref memory_resource
3926
        to use. The element will acquire shared
3927
        ownership of the memory resource.
3928
    */
3929
    explicit
3930
    key_value_pair(
3931
        std::pair<
3932
            string_view,
3933
            json::value>&& p,
3934
        storage_ptr sp = {})
3935
        : key_value_pair(
3936
            p.first,
3937
            std::move(p).second,
3938
            std::move(sp))
3939
    {
3940
    }
3941
3942
    /** Return the associated memory resource.
3943
3944
        This returns a pointer to the memory
3945
        resource used to construct the value.
3946
3947
        @par Complexity
3948
        Constant.
3949
3950
        @par Exception Safety
3951
        No-throw guarantee.
3952
    */
3953
    storage_ptr const&
3954
    storage() const noexcept
3955
0
    {
3956
0
        return value_.storage();
3957
0
    }
3958
3959
    /** Return the key of this element.
3960
3961
        After construction, the key may
3962
        not be modified.
3963
3964
        @par Complexity
3965
        Constant.
3966
3967
        @par Exception Safety
3968
        No-throw guarantee.
3969
    */
3970
    string_view const
3971
    key() const noexcept
3972
2.76M
    {
3973
2.76M
        return { key_, len_ };
3974
2.76M
    }
3975
3976
    /** Return the key of this element as a null-terminated string.
3977
3978
        @par Complexity
3979
        Constant.
3980
3981
        @par Exception Safety
3982
        No-throw guarantee.
3983
    */
3984
    char const*
3985
    key_c_str() const noexcept
3986
    {
3987
        return key_;
3988
    }
3989
3990
    /** Return the value of this element.
3991
3992
        @par Complexity
3993
        Constant.
3994
3995
        @par Exception Safety
3996
        No-throw guarantee.
3997
    */
3998
    /* @{ */
3999
    json::value const&
4000
    value() const& noexcept
4001
0
    {
4002
0
        return value_;
4003
0
    }
4004
4005
    json::value&&
4006
    value() && noexcept
4007
    {
4008
        return std::move( value() );
4009
    }
4010
4011
    json::value&
4012
    value() & noexcept
4013
0
    {
4014
0
        return value_;
4015
0
    }
4016
    /* @} */
4017
4018
private:
4019
    json::value value_;
4020
    char const* key_;
4021
    std::uint32_t len_;
4022
    std::uint32_t next_;
4023
};
4024
4025
//----------------------------------------------------------
4026
4027
#ifdef BOOST_JSON_DOCS
4028
4029
/** Tuple-like element access.
4030
4031
    This overload permits the key and value
4032
    of a `key_value_pair` to be accessed
4033
    by index. For example:
4034
4035
    @code
4036
4037
    key_value_pair kvp("num", 42);
4038
4039
    string_view key = get<0>(kvp);
4040
    value& jv = get<1>(kvp);
4041
4042
    @endcode
4043
4044
    @par Structured Bindings
4045
4046
    When using C++17 or greater, objects of type
4047
    @ref key_value_pair may be used to initialize
4048
    structured bindings:
4049
4050
    @code
4051
4052
    key_value_pair kvp("num", 42);
4053
4054
    auto& [key, value] = kvp;
4055
4056
    @endcode
4057
4058
    Depending on the value of `I`, the return type will be:
4059
4060
    @li `string_view const` if `I == 0`, or
4061
4062
    @li `value&`, `value const&`, or `value&&` if `I == 1`.
4063
4064
    Any other value for `I` is ill-formed.
4065
4066
    @tparam I The element index to access.
4067
4068
    @par Constraints
4069
4070
    `std::is_same_v< std::remove_cvref_t<T>, key_value_pair >`
4071
4072
    @return `kvp.key()` if `I == 0`, or `kvp.value()`
4073
    if `I == 1`.
4074
4075
    @param kvp The @ref key_value_pair object
4076
    to access.
4077
*/
4078
template<
4079
    std::size_t I,
4080
    class T>
4081
__see_below__
4082
get(T&& kvp) noexcept;
4083
4084
#else
4085
4086
template<std::size_t I>
4087
auto
4088
get(key_value_pair const&) noexcept ->
4089
    typename std::conditional<I == 0,
4090
        string_view const,
4091
        value const&>::type
4092
{
4093
    static_assert(I == 0,
4094
        "key_value_pair index out of range");
4095
}
4096
4097
template<std::size_t I>
4098
auto
4099
get(key_value_pair&) noexcept ->
4100
    typename std::conditional<I == 0,
4101
        string_view const,
4102
        value&>::type
4103
{
4104
    static_assert(I == 0,
4105
        "key_value_pair index out of range");
4106
}
4107
4108
template<std::size_t I>
4109
auto
4110
get(key_value_pair&&) noexcept ->
4111
    typename std::conditional<I == 0,
4112
        string_view const,
4113
        value&&>::type
4114
{
4115
    static_assert(I == 0,
4116
        "key_value_pair index out of range");
4117
}
4118
4119
/** Extracts a key_value_pair's key using tuple-like interface
4120
*/
4121
template<>
4122
inline
4123
string_view const
4124
get<0>(key_value_pair const& kvp) noexcept
4125
0
{
4126
0
    return kvp.key();
4127
0
}
4128
4129
/** Extracts a key_value_pair's key using tuple-like interface
4130
*/
4131
template<>
4132
inline
4133
string_view const
4134
get<0>(key_value_pair& kvp) noexcept
4135
{
4136
    return kvp.key();
4137
}
4138
4139
/** Extracts a key_value_pair's key using tuple-like interface
4140
*/
4141
template<>
4142
inline
4143
string_view const
4144
get<0>(key_value_pair&& kvp) noexcept
4145
{
4146
    return kvp.key();
4147
}
4148
4149
/** Extracts a key_value_pair's value using tuple-like interface
4150
*/
4151
template<>
4152
inline
4153
value const&
4154
get<1>(key_value_pair const& kvp) noexcept
4155
0
{
4156
0
    return kvp.value();
4157
0
}
4158
4159
/** Extracts a key_value_pair's value using tuple-like interface
4160
*/
4161
template<>
4162
inline
4163
value&
4164
get<1>(key_value_pair& kvp) noexcept
4165
{
4166
    return kvp.value();
4167
}
4168
4169
/** Extracts a key_value_pair's value using tuple-like interface
4170
*/
4171
template<>
4172
inline
4173
value&&
4174
get<1>(key_value_pair&& kvp) noexcept
4175
{
4176
    return std::move(kvp.value());
4177
}
4178
4179
#endif
4180
4181
} // namespace json
4182
} // namespace boost
4183
4184
#ifdef __clang__
4185
# pragma clang diagnostic push
4186
# pragma clang diagnostic ignored "-Wmismatched-tags"
4187
#endif
4188
4189
#ifndef BOOST_JSON_DOCS
4190
4191
namespace std {
4192
4193
/** Tuple-like size access for key_value_pair
4194
*/
4195
template<>
4196
struct tuple_size< ::boost::json::key_value_pair >
4197
    : std::integral_constant<std::size_t, 2>
4198
{
4199
};
4200
4201
/** Tuple-like access for the key type of key_value_pair
4202
*/
4203
template<>
4204
struct tuple_element<0, ::boost::json::key_value_pair>
4205
{
4206
    using type = ::boost::json::string_view const;
4207
};
4208
4209
/** Tuple-like access for the value type of key_value_pair
4210
*/
4211
template<>
4212
struct tuple_element<1, ::boost::json::key_value_pair>
4213
{
4214
    using type = ::boost::json::value&;
4215
};
4216
4217
/** Tuple-like access for the value type of key_value_pair
4218
*/
4219
template<>
4220
struct tuple_element<1, ::boost::json::key_value_pair const>
4221
{
4222
    using type = ::boost::json::value const&;
4223
};
4224
4225
} // std
4226
4227
#endif
4228
4229
// std::hash specialization
4230
#ifndef BOOST_JSON_DOCS
4231
namespace std {
4232
template <>
4233
struct hash< ::boost::json::value > {
4234
    BOOST_JSON_DECL
4235
    std::size_t
4236
    operator()(::boost::json::value const& jv) const noexcept;
4237
};
4238
} // std
4239
#endif
4240
4241
4242
#ifdef __clang__
4243
# pragma clang diagnostic pop
4244
#endif
4245
4246
// These are here because value, array,
4247
// and object form cyclic references.
4248
4249
#include <boost/json/detail/impl/array.hpp>
4250
#include <boost/json/impl/array.hpp>
4251
#include <boost/json/impl/object.hpp>
4252
#include <boost/json/impl/value.hpp>
4253
4254
// These must come after array and object
4255
#include <boost/json/impl/value_ref.hpp>
4256
4257
#endif