GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: value_ref.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 114 114 100.0%
Functions: 54 56 96.4%
Branches: 0 0 -%

Line Branch Exec 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
35 lazy construction of and assignment to the
36 container types @ref value, @ref array,
37 and @ref object. The two types of initializer
38 lists used are:
39
40 @li `std::initializer_list< value_ref >` for
41 constructing or assigning a @ref value or
42 @ref array, and
43
44 @li `std::initializer_list< std::pair< string_view, value_ref > >`
45 for constructing or assigning an @ref object.
46
47 A `value_ref` uses reference semantics. Creation of the actual container
48 from the initializer list is lazily deferred until the list is used. This
49 means that the `boost::container::pmr::memory_resource` used to construct a
50 container can be specified after the point where the initializer list is
51 specified.
52
53 @par Example
54
55 This example demonstrates how a user-defined type
56 containing a JSON value can be constructed from
57 an initializer list:
58
59 @code
60
61 class my_type
62 {
63 value jv_;
64
65 public:
66 my_type( std::initializer_list< value_ref > init )
67 : jv_(init)
68 {
69 }
70 };
71
72 @endcode
73
74 @note Never declare a variable of type
75 `std::initializer_list` except in function
76 parameter lists, otherwise the behavior may
77 be undefined.
78
79 @see
80 @ref value,
81 @ref array,
82 @ref object
83 */
84 class value_ref
85 {
86 friend class value;
87 friend class object;
88 friend class array;
89
90 friend class value_ref_test;
91
92 enum class what
93 {
94 str,
95 ini,
96 func,
97 cfunc,
98 strfunc,
99 };
100
101 using init_list =
102 std::initializer_list<value_ref>;
103
104 struct func_type
105 {
106 value(*f)(void*, storage_ptr);
107 void* p;
108 };
109
110 struct cfunc_type
111 {
112 value(*f)(void const*, storage_ptr);
113 void const* p;
114 };
115
116 union arg_type
117 {
118 string_view str_;
119 init_list init_list_;
120
121 signed char schar_;
122 short short_;
123 int int_;
124 long long_;
125 long long long_long_;
126 unsigned char uchar_;
127 unsigned short ushort_;
128 unsigned int uint_;
129 unsigned long ulong_;
130 unsigned long long ulong_long_;
131 float float_;
132 double double_;
133 bool bool_;
134 std::nullptr_t nullptr_;
135
136 98 arg_type() {}
137 1002 explicit arg_type(string_view t) noexcept : str_(t) {}
138 674 explicit arg_type(init_list t) noexcept : init_list_(t) {}
139 1 explicit arg_type(signed char t) noexcept : schar_(t) {}
140 3 explicit arg_type(short t) noexcept : short_(t) {}
141 2728 explicit arg_type(int t) noexcept : int_(t) {}
142 3 explicit arg_type(long t) noexcept : long_(t) {}
143 3 explicit arg_type(long long t) noexcept : long_long_(t) {}
144 21 explicit arg_type(unsigned char t) noexcept : uchar_(t) {}
145 3 explicit arg_type(unsigned short t) noexcept : ushort_(t) {}
146 45 explicit arg_type(unsigned int t) noexcept : uint_(t) {}
147 3 explicit arg_type(unsigned long t) noexcept : ulong_(t) {}
148 3 explicit arg_type(unsigned long long t) noexcept : ulong_long_(t) {}
149 18 explicit arg_type(float t) noexcept : float_(t) {}
150 34 explicit arg_type(double t) noexcept : double_(t) {}
151 287 explicit arg_type(bool t) noexcept : bool_(t) {}
152 88 explicit arg_type(std::nullptr_t) noexcept : nullptr_() {}
153 };
154
155 arg_type arg_;
156 #ifndef BOOST_JSON_DOCS
157 // VFALCO doc toolchain erroneously
158 // displays private, anonymous unions as public
159 union
160 {
161 func_type f_;
162 cfunc_type cf_;
163 };
164 #endif
165 what what_;
166
167 public:
168 /// Constructor
169 value_ref(
170 value_ref const&) = default;
171
172 /// Constructor
173 value_ref(
174 value_ref&&) = default;
175
176 /// Constructor
177 #ifdef BOOST_JSON_DOCS
178 value_ref(string_view s) noexcept;
179 #else
180 template<
181 class T
182 ,class = typename
183 std::enable_if<
184 std::is_constructible<
185 string_view, T>::value>::type
186 >
187 2001 value_ref(
188 T const& t) noexcept
189 2001 : arg_(string_view(t))
190 2001 , what_(what::str)
191 {
192
193 2001 }
194 #endif
195
196 /// Constructor
197 template<class T>
198 42 value_ref(
199 T const& t
200 #ifndef BOOST_JSON_DOCS
201 ,typename std::enable_if<
202 ! std::is_constructible<
203 string_view, T>::value &&
204 ! std::is_same<bool, T>::value
205 >::type* = 0
206 #endif
207 ) noexcept
208 42 : cf_{&from_const<T>, &t}
209 42 , what_(what::cfunc)
210 {
211 42 }
212
213 /// Constructor
214 template<class T>
215 129 value_ref(
216 T&& t
217 #ifndef BOOST_JSON_DOCS
218 ,typename std::enable_if<
219 (! std::is_constructible<
220 string_view, T>::value ||
221 std::is_same<string, T>::value) &&
222 ! std::is_same<bool,
223 detail::remove_cvref<T>>::value &&
224 std::is_same<T, detail::remove_cvref<T>>
225 ::value>::type* = 0
226 #endif
227 ) noexcept
228 129 : f_{&from_rvalue<
229 detail::remove_cvref<T>>, &t}
230 129 , what_(std::is_same<string, T>::value ?
231 129 what::strfunc : what::func)
232 {
233 129 }
234
235 /// Constructor
236 #ifdef BOOST_JSON_DOCS
237 value_ref(bool b) noexcept;
238 #else
239 template<
240 class T
241 ,class = typename std::enable_if<
242 std::is_same<T, bool>::value>::type
243 >
244 287 value_ref(
245 T b) noexcept
246 287 : arg_(b)
247 287 , cf_{&from_builtin<bool>, &arg_.bool_}
248 287 , what_(what::cfunc)
249 {
250 287 }
251 #endif
252
253 /// Constructor
254 674 value_ref(
255 std::initializer_list<
256 value_ref> t) noexcept
257 674 : arg_(t)
258 674 , what_(what::ini)
259 {
260 674 }
261
262 /// Constructor
263 1 value_ref(signed char t) noexcept
264 1 : arg_(t)
265 1 , cf_{&from_builtin<signed char>, &arg_.schar_}
266 1 , what_(what::cfunc)
267 {
268 1 }
269
270 /// Constructor
271 3 value_ref(short t) noexcept
272 3 : arg_(t)
273 3 , cf_{&from_builtin<short>, &arg_.short_}
274 3 , what_(what::cfunc)
275 {
276 3 }
277
278 /// Constructor
279 2728 value_ref(int t) noexcept
280 2728 : arg_(t)
281 2728 , cf_{&from_builtin<int>, &arg_.int_}
282 2728 , what_(what::cfunc)
283 {
284 2728 }
285
286 /// Constructor
287 3 value_ref(long t) noexcept
288 3 : arg_(t)
289 3 , cf_{&from_builtin<
290 3 long>, &arg_.long_}
291 3 , what_(what::cfunc)
292 {
293 3 }
294
295 /// Constructor
296 3 value_ref(long long t) noexcept
297 3 : arg_(t)
298 3 , cf_{&from_builtin<
299 3 long long>, &arg_.long_long_}
300 3 , what_(what::cfunc)
301 {
302 3 }
303
304 /// Constructor
305 21 value_ref(unsigned char t) noexcept
306 21 : arg_(t)
307 21 , cf_{&from_builtin<
308 21 unsigned char>, &arg_.uchar_}
309 21 , what_(what::cfunc)
310 {
311 21 }
312
313 /// Constructor
314 3 value_ref(unsigned short t) noexcept
315 3 : arg_(t)
316 3 , cf_{&from_builtin<
317 3 unsigned short>, &arg_.ushort_}
318 3 , what_(what::cfunc)
319 {
320 3 }
321
322 /// Constructor
323 45 value_ref(unsigned int t) noexcept
324 45 : arg_(t)
325 45 , cf_{&from_builtin<
326 45 unsigned int>, &arg_.uint_}
327 45 , what_(what::cfunc)
328 {
329 45 }
330
331 /// Constructor
332 3 value_ref(unsigned long t) noexcept
333 3 : arg_(t)
334 3 , cf_{&from_builtin<
335 3 unsigned long>, &arg_.ulong_}
336 3 , what_(what::cfunc)
337 {
338 3 }
339
340 /// Constructor
341 3 value_ref(unsigned long long t) noexcept
342 3 : arg_(t)
343 3 , cf_{&from_builtin<
344 3 unsigned long long>, &arg_.ulong_long_}
345 3 , what_(what::cfunc)
346 {
347 3 }
348
349 /// Constructor
350 18 value_ref(float t) noexcept
351 18 : arg_(t)
352 18 , cf_{&from_builtin<
353 18 float>, &arg_.float_}
354 18 , what_(what::cfunc)
355 {
356 18 }
357
358 /// Constructor
359 34 value_ref(double t) noexcept
360 34 : arg_(t)
361 34 , cf_{&from_builtin<
362 34 double>, &arg_.double_}
363 34 , what_(what::cfunc)
364 {
365 34 }
366
367 /// Constructor
368 88 value_ref(std::nullptr_t) noexcept
369 88 : arg_(nullptr)
370 88 , cf_{&from_builtin<
371 88 std::nullptr_t>, &arg_.nullptr_}
372 88 , what_(what::cfunc)
373 {
374 88 }
375
376 #ifndef BOOST_JSON_DOCS
377 // Not public
378 //private:
379 // VFALCO Why is this needed?
380 /** Operator conversion to @ref value
381
382 This allows creation of a @ref value from
383 an initializer list element.
384 */
385 BOOST_JSON_DECL
386 operator value() const;
387 #endif
388
389 private:
390 template<class T>
391 static
392 value
393 from_builtin(
394 void const* p,
395 storage_ptr sp) noexcept;
396
397 template<class T>
398 static
399 value
400 from_const(
401 void const* p,
402 storage_ptr sp);
403
404 template<class T>
405 static
406 value
407 from_rvalue(
408 void* p,
409 storage_ptr sp);
410
411 static
412 BOOST_JSON_DECL
413 value
414 from_init_list(
415 void const* p,
416 storage_ptr sp);
417
418 inline
419 bool
420 is_key_value_pair() const noexcept;
421
422 static
423 inline
424 bool
425 maybe_object(
426 std::initializer_list<
427 value_ref> init) noexcept;
428
429 inline
430 string_view
431 get_string() const noexcept;
432
433 BOOST_JSON_DECL
434 value
435 make_value(
436 storage_ptr sp) const;
437
438 BOOST_JSON_DECL
439 static
440 value
441 make_value(
442 std::initializer_list<
443 value_ref> init,
444 storage_ptr sp);
445
446 BOOST_JSON_DECL
447 static
448 object
449 make_object(
450 std::initializer_list<value_ref> init,
451 storage_ptr sp);
452
453 BOOST_JSON_DECL
454 static
455 array
456 make_array(
457 std::initializer_list<
458 value_ref> init,
459 storage_ptr sp);
460
461 BOOST_JSON_DECL
462 static
463 void
464 write_array(
465 value* dest,
466 std::initializer_list<
467 value_ref> init,
468 storage_ptr const& sp);
469 };
470
471 } // namespace json
472 } // namespace boost
473
474 // Must be included here for this file to stand alone
475 #include <boost/json/value.hpp>
476
477 // includes are at the bottom of <boost/json/value.hpp>
478 //#include <boost/json/impl/value.hpp>
479 //#include <boost/json/impl/value.ipp>
480
481 #endif
482