Coverage Report

Created: 2026-03-09 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boost/boost/json/value_ref.hpp
Line
Count
Source
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
//
4
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
//
7
// Official repository: https://github.com/boostorg/json
8
//
9
10
#ifndef BOOST_JSON_VALUE_REF_HPP
11
#define BOOST_JSON_VALUE_REF_HPP
12
13
#include <boost/json/detail/config.hpp>
14
#include <boost/json/storage_ptr.hpp>
15
#include <boost/json/string.hpp>
16
#include <initializer_list>
17
#include <type_traits>
18
#include <utility>
19
20
namespace boost {
21
namespace json {
22
23
#ifndef BOOST_JSON_DOCS
24
class value;
25
class object;
26
class array;
27
class string;
28
#endif
29
30
//----------------------------------------------------------
31
32
/** The type used in initializer lists.
33
34
    This type is used in initializer lists for lazy construction of and
35
    assignment to the container types @ref value, @ref array, and @ref object.
36
    The two types of initializer lists used are:
37
38
    @li `std::initializer_list< value_ref >` for constructing or assigning
39
        a @ref value or @ref array, and
40
    @li `std::initializer_list< std::pair< string_view, value_ref > >` for
41
        constructing or assigning an @ref object.
42
43
    A `value_ref` uses reference semantics. Creation of the actual container
44
    from the initializer list is lazily deferred until the list is used. This
45
    means that the @ref boost::container::pmr::memory_resource used to
46
    construct a container can be specified after the point where the
47
    initializer list is specified. Also, the usage of this type allows to avoid
48
    constructing a @ref value until it's necessary.
49
50
    @par Example
51
    This example demonstrates how a user-defined type containing a JSON value
52
    can be constructed from an initializer list:
53
54
    @code
55
    class my_type
56
    {
57
        value jv_;
58
59
    public:
60
        my_type( std::initializer_list<value_ref> init )
61
            : jv_(init)
62
        {
63
        }
64
    };
65
    @endcode
66
67
    @warning `value_ref` does not take ownership of the objects it was
68
    constructed with. If those objects' lifetimes end before the `value_ref`
69
    object is used, you will get undefined behavior. Because of this it is
70
    advised against declaring a variable of type
71
    `std::initializer_list<value_ref>` except in function parameter lists.
72
73
    @see @ref value, @ref array, @ref object, @ref value::set_at_pointer.
74
*/
75
class value_ref
76
{
77
    friend class value;
78
    friend class object;
79
    friend class array;
80
81
    friend class value_ref_test;
82
83
    enum class what
84
    {
85
        str,
86
        ini,
87
        func,
88
        cfunc,
89
        strfunc,
90
    };
91
92
    using init_list =
93
        std::initializer_list<value_ref>;
94
95
    struct func_type
96
    {
97
        value(*f)(void*, storage_ptr);
98
        void* p;
99
    };
100
101
    struct cfunc_type
102
    {
103
        value(*f)(void const*, storage_ptr);
104
        void const* p;
105
    };
106
107
    union arg_type
108
    {
109
        string_view         str_;
110
        init_list           init_list_;
111
112
        signed char         schar_;
113
        short               short_;
114
        int                 int_;
115
        long                long_;
116
        long long           long_long_;
117
        unsigned char       uchar_;
118
        unsigned short      ushort_;
119
        unsigned int        uint_;
120
        unsigned long       ulong_;
121
        unsigned long long  ulong_long_;
122
        float               float_;
123
        double              double_;
124
        bool                bool_;
125
        std::nullptr_t      nullptr_;
126
127
0
        arg_type() {}
128
0
        explicit arg_type(string_view t) noexcept : str_(t) {}
129
0
        explicit arg_type(init_list t) noexcept : init_list_(t) {}
130
0
        explicit arg_type(signed char t) noexcept : schar_(t) {}
131
0
        explicit arg_type(short t) noexcept : short_(t) {}
132
0
        explicit arg_type(int t) noexcept : int_(t) {}
133
0
        explicit arg_type(long t) noexcept : long_(t) {}
134
0
        explicit arg_type(long long t) noexcept : long_long_(t) {}
135
0
        explicit arg_type(unsigned char t) noexcept : uchar_(t) {}
136
0
        explicit arg_type(unsigned short t) noexcept : ushort_(t) {}
137
0
        explicit arg_type(unsigned int t) noexcept : uint_(t) {}
138
0
        explicit arg_type(unsigned long t) noexcept : ulong_(t) {}
139
0
        explicit arg_type(unsigned long long t) noexcept : ulong_long_(t) {}
140
0
        explicit arg_type(float t) noexcept : float_(t) {}
141
0
        explicit arg_type(double t) noexcept : double_(t) {}
142
0
        explicit arg_type(bool t) noexcept : bool_(t) {}
143
0
        explicit arg_type(std::nullptr_t) noexcept : nullptr_() {}
144
    };
145
146
    arg_type arg_;
147
#ifndef BOOST_JSON_DOCS
148
    // VFALCO doc toolchain erroneously
149
    // displays private, anonymous unions as public
150
    union
151
    {
152
        func_type f_;
153
        cfunc_type cf_;
154
    };
155
#endif
156
    what what_;
157
158
public:
159
    /** Constructors.
160
161
        @li **(1)** copy constructor.
162
        @li **(2)** move constructor.
163
        @li **(3)** the constructed value stores a reference to `t`'s character
164
            array.
165
        @li **(4)** the constructed value stores a `const` reference to `t`.
166
        @li **(5)** the constructed value stores an rvalue reference to `t`.
167
        @li **(6)** the constructed value stores a copy of `b`.
168
        @li **(7)**--**(18)** the constructed value stores a copy of `t`.
169
        @li **(19)** the constrcuted value stores `nullptr`.
170
        @li **(20)** the constrcuted value stores a copy of `init`.
171
172
        In addition the constructed object stores a pointer to a function that
173
        captures the type information necessary to construct a @ref value from
174
        the stored data.
175
176
        @warning The overloads that accept references do not take ownership of
177
        referenced objects. The caller is responsible for making sure those
178
        objects do not go out of scope before the `value_ref` object is used.
179
        It is advised you only use `value_ref` (or any type that contains a
180
        `value_ref` subobject) as function parameters or take special care to
181
        not invoke undefeined behavior.
182
183
        @par Complexity
184
        @li **(1)**--**(19)** constant.
185
        @li **(20)** linear in `init.size()`.
186
187
        @par Exception Safety
188
        No-throw guarantee.
189
190
        @{
191
    */
192
    value_ref(
193
        value_ref const&) = default;
194
195
    /// Overload
196
    value_ref(
197
        value_ref&&) = default;
198
199
    /// Overload
200
#ifdef BOOST_JSON_DOCS
201
    value_ref(string_view s) noexcept;
202
#else
203
    template<
204
        class T
205
        ,class = typename
206
            std::enable_if<
207
                std::is_constructible<
208
                    string_view, T>::value>::type
209
    >
210
    value_ref(
211
        T const& t) noexcept
212
        : arg_(string_view(t))
213
        , what_(what::str)
214
    {
215
    }
216
#endif
217
218
    /// Overload
219
    template<class T>
220
    value_ref(
221
        T const& t
222
#ifndef BOOST_JSON_DOCS
223
        ,typename std::enable_if<
224
            ! std::is_constructible<
225
                string_view, T>::value &&
226
            ! std::is_same<bool, T>::value
227
                >::type* = 0
228
#endif
229
        ) noexcept
230
        : cf_{&from_const<T>, &t}
231
        , what_(what::cfunc)
232
    {
233
    }
234
235
    /// Overload
236
    template<class T>
237
    value_ref(
238
        T&& t
239
#ifndef BOOST_JSON_DOCS
240
        ,typename std::enable_if<
241
            (! std::is_constructible<
242
                string_view, T>::value ||
243
            std::is_same<string, T>::value) &&
244
            ! std::is_same<bool,
245
                detail::remove_cvref<T>>::value &&
246
            std::is_same<T, detail::remove_cvref<T>>
247
                ::value>::type* = 0
248
#endif
249
        ) noexcept
250
        : f_{&from_rvalue<
251
            detail::remove_cvref<T>>, &t}
252
        , what_(std::is_same<string, T>::value ?
253
                what::strfunc : what::func)
254
    {
255
    }
256
257
    /// Overload
258
#ifdef BOOST_JSON_DOCS
259
    value_ref(bool b) noexcept;
260
#else
261
    template<
262
        class T
263
        ,class = typename std::enable_if<
264
            std::is_same<T, bool>::value>::type
265
    >
266
    value_ref(
267
        T b) noexcept
268
        : arg_(b)
269
        , cf_{&from_builtin<bool>, &arg_.bool_}
270
        , what_(what::cfunc)
271
    {
272
    }
273
#endif
274
275
    /// Overload
276
    value_ref(signed char t) noexcept
277
        : arg_(t)
278
        , cf_{&from_builtin<signed char>, &arg_.schar_}
279
        , what_(what::cfunc)
280
0
    {
281
0
    }
282
283
    /// Overload
284
    value_ref(short t) noexcept
285
        : arg_(t)
286
        , cf_{&from_builtin<short>, &arg_.short_}
287
        , what_(what::cfunc)
288
0
    {
289
0
    }
290
291
    /// Overload
292
    value_ref(int t) noexcept
293
        : arg_(t)
294
        , cf_{&from_builtin<int>, &arg_.int_}
295
        , what_(what::cfunc)
296
0
    {
297
0
    }
298
299
    /// Overload
300
    value_ref(long t) noexcept
301
        : arg_(t)
302
        , cf_{&from_builtin<
303
            long>, &arg_.long_}
304
        , what_(what::cfunc)
305
0
    {
306
0
    }
307
308
    /// Overload
309
    value_ref(long long t) noexcept
310
        : arg_(t)
311
        , cf_{&from_builtin<
312
            long long>, &arg_.long_long_}
313
        , what_(what::cfunc)
314
0
    {
315
0
    }
316
317
    /// Overload
318
    value_ref(unsigned char t) noexcept
319
        : arg_(t)
320
        , cf_{&from_builtin<
321
            unsigned char>, &arg_.uchar_}
322
        , what_(what::cfunc)
323
0
    {
324
0
    }
325
326
    /// Overload
327
    value_ref(unsigned short t) noexcept
328
        : arg_(t)
329
        , cf_{&from_builtin<
330
            unsigned short>, &arg_.ushort_}
331
        , what_(what::cfunc)
332
0
    {
333
0
    }
334
335
    /// Overload
336
    value_ref(unsigned int t) noexcept
337
        : arg_(t)
338
        , cf_{&from_builtin<
339
            unsigned int>, &arg_.uint_}
340
        , what_(what::cfunc)
341
0
    {
342
0
    }
343
344
    /// Overload
345
    value_ref(unsigned long t) noexcept
346
        : arg_(t)
347
        , cf_{&from_builtin<
348
            unsigned long>, &arg_.ulong_}
349
        , what_(what::cfunc)
350
0
    {
351
0
    }
352
353
    /// Overload
354
    value_ref(unsigned long long t) noexcept
355
        : arg_(t)
356
        , cf_{&from_builtin<
357
            unsigned long long>, &arg_.ulong_long_}
358
        , what_(what::cfunc)
359
0
    {
360
0
    }
361
362
    /// Overload
363
    value_ref(float t) noexcept
364
        : arg_(t)
365
        , cf_{&from_builtin<
366
            float>, &arg_.float_}
367
        , what_(what::cfunc)
368
0
    {
369
0
    }
370
371
    /// Overload
372
    value_ref(double t) noexcept
373
        : arg_(t)
374
        , cf_{&from_builtin<
375
            double>, &arg_.double_}
376
        , what_(what::cfunc)
377
0
    {
378
0
    }
379
380
    /// Overload
381
    value_ref(std::nullptr_t) noexcept
382
        : arg_(nullptr)
383
        , cf_{&from_builtin<
384
            std::nullptr_t>, &arg_.nullptr_}
385
        , what_(what::cfunc)
386
0
    {
387
0
    }
388
389
    /// Overload
390
    value_ref(
391
        std::initializer_list<value_ref> init) noexcept
392
        : arg_(init)
393
        , what_(what::ini)
394
0
    {
395
0
    }
396
397
    /// @}
398
399
#ifndef BOOST_JSON_DOCS
400
// Not public
401
//private:
402
    // VFALCO Why is this needed?
403
    /** Operator conversion to @ref value
404
405
        This allows creation of a @ref value from
406
        an initializer list element.
407
    */
408
    BOOST_JSON_DECL
409
    operator value() const;
410
#endif
411
412
private:
413
    template<class T>
414
    static
415
    value
416
    from_builtin(
417
        void const* p,
418
        storage_ptr sp) noexcept;
419
420
    template<class T>
421
    static
422
    value
423
    from_const(
424
        void const* p,
425
        storage_ptr sp);
426
427
    template<class T>
428
    static
429
    value
430
    from_rvalue(
431
        void* p,
432
        storage_ptr sp);
433
434
    static
435
    BOOST_JSON_DECL
436
    value
437
    from_init_list(
438
        void const* p,
439
        storage_ptr sp);
440
441
    inline
442
    bool
443
    is_key_value_pair() const noexcept;
444
445
    static
446
    inline
447
    bool
448
    maybe_object(
449
        std::initializer_list<
450
            value_ref> init) noexcept;
451
452
    inline
453
    string_view
454
    get_string() const noexcept;
455
456
    BOOST_JSON_DECL
457
    value
458
    make_value(
459
        storage_ptr sp) const;
460
461
    BOOST_JSON_DECL
462
    static
463
    value
464
    make_value(
465
        std::initializer_list<
466
            value_ref> init,
467
        storage_ptr sp);
468
469
    BOOST_JSON_DECL
470
    static
471
    object
472
    make_object(
473
        std::initializer_list<value_ref> init,
474
        storage_ptr sp);
475
476
    BOOST_JSON_DECL
477
    static
478
    array
479
    make_array(
480
        std::initializer_list<
481
            value_ref> init,
482
        storage_ptr sp);
483
484
    BOOST_JSON_DECL
485
    static
486
    void
487
    write_array(
488
        value* dest,
489
        std::initializer_list<
490
            value_ref> init,
491
        storage_ptr const& sp);
492
};
493
494
} // namespace json
495
} // namespace boost
496
497
// Must be included here for this file to stand alone
498
#include <boost/json/value.hpp>
499
500
// includes are at the bottom of <boost/json/value.hpp>
501
//#include <boost/json/impl/value.hpp>
502
//#include <boost/json/impl/value.ipp>
503
504
#endif