GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: value_ref.hpp
Date: 2025-12-23 17:22:01
Exec Total Coverage
Lines: 114 114 100.0%
Functions: 55 57 96.5%
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 125 arg_type() {}
137 911 explicit arg_type(string_view t) noexcept : str_(t) {}
138 655 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 2684 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 #ifdef BOOST_JSON_DOCS
174 value_ref(string_view s) noexcept;
175 #else
176 template<
177 class T
178 ,class = typename
179 std::enable_if<
180 std::is_constructible<
181 string_view, T>::value>::type
182 >
183 1819 value_ref(
184 T const& t) noexcept
185 1819 : arg_(string_view(t))
186 1819 , what_(what::str)
187 {
188
189 1819 }
190 #endif
191
192 /// Constructor
193 template<class T>
194 42 value_ref(
195 T const& t
196 #ifndef BOOST_JSON_DOCS
197 ,typename std::enable_if<
198 ! std::is_constructible<
199 string_view, T>::value &&
200 ! std::is_same<bool, T>::value
201 >::type* = 0
202 #endif
203 ) noexcept
204 42 : cf_{&from_const<T>, &t}
205 42 , what_(what::cfunc)
206 {
207 42 }
208
209 /// Constructor
210 template<class T>
211 184 value_ref(
212 T&& t
213 #ifndef BOOST_JSON_DOCS
214 ,typename std::enable_if<
215 (! std::is_constructible<
216 string_view, T>::value ||
217 std::is_same<string, T>::value) &&
218 ! std::is_same<bool,
219 detail::remove_cvref<T>>::value &&
220 std::is_same<T, detail::remove_cvref<T>>
221 ::value>::type* = 0
222 #endif
223 ) noexcept
224 184 : f_{&from_rvalue<
225 detail::remove_cvref<T>>, &t}
226 184 , what_(std::is_same<string, T>::value ?
227 184 what::strfunc : what::func)
228 {
229 184 }
230
231 /// Constructor
232 #ifdef BOOST_JSON_DOCS
233 value_ref(bool b) noexcept;
234 #else
235 template<
236 class T
237 ,class = typename std::enable_if<
238 std::is_same<T, bool>::value>::type
239 >
240 287 value_ref(
241 T b) noexcept
242 287 : arg_(b)
243 287 , cf_{&from_builtin<bool>, &arg_.bool_}
244 287 , what_(what::cfunc)
245 {
246 287 }
247 #endif
248
249 /// Constructor
250 655 value_ref(
251 std::initializer_list<
252 value_ref> t) noexcept
253 655 : arg_(t)
254 655 , what_(what::ini)
255 {
256 655 }
257
258 /// Constructor
259 1 value_ref(signed char t) noexcept
260 1 : arg_(t)
261 1 , cf_{&from_builtin<signed char>, &arg_.schar_}
262 1 , what_(what::cfunc)
263 {
264 1 }
265
266 /// Constructor
267 3 value_ref(short t) noexcept
268 3 : arg_(t)
269 3 , cf_{&from_builtin<short>, &arg_.short_}
270 3 , what_(what::cfunc)
271 {
272 3 }
273
274 /// Constructor
275 2684 value_ref(int t) noexcept
276 2684 : arg_(t)
277 2684 , cf_{&from_builtin<int>, &arg_.int_}
278 2684 , what_(what::cfunc)
279 {
280 2684 }
281
282 /// Constructor
283 3 value_ref(long t) noexcept
284 3 : arg_(t)
285 3 , cf_{&from_builtin<
286 3 long>, &arg_.long_}
287 3 , what_(what::cfunc)
288 {
289 3 }
290
291 /// Constructor
292 3 value_ref(long long t) noexcept
293 3 : arg_(t)
294 3 , cf_{&from_builtin<
295 3 long long>, &arg_.long_long_}
296 3 , what_(what::cfunc)
297 {
298 3 }
299
300 /// Constructor
301 21 value_ref(unsigned char t) noexcept
302 21 : arg_(t)
303 21 , cf_{&from_builtin<
304 21 unsigned char>, &arg_.uchar_}
305 21 , what_(what::cfunc)
306 {
307 21 }
308
309 /// Constructor
310 3 value_ref(unsigned short t) noexcept
311 3 : arg_(t)
312 3 , cf_{&from_builtin<
313 3 unsigned short>, &arg_.ushort_}
314 3 , what_(what::cfunc)
315 {
316 3 }
317
318 /// Constructor
319 45 value_ref(unsigned int t) noexcept
320 45 : arg_(t)
321 45 , cf_{&from_builtin<
322 45 unsigned int>, &arg_.uint_}
323 45 , what_(what::cfunc)
324 {
325 45 }
326
327 /// Constructor
328 3 value_ref(unsigned long t) noexcept
329 3 : arg_(t)
330 3 , cf_{&from_builtin<
331 3 unsigned long>, &arg_.ulong_}
332 3 , what_(what::cfunc)
333 {
334 3 }
335
336 /// Constructor
337 3 value_ref(unsigned long long t) noexcept
338 3 : arg_(t)
339 3 , cf_{&from_builtin<
340 3 unsigned long long>, &arg_.ulong_long_}
341 3 , what_(what::cfunc)
342 {
343 3 }
344
345 /// Constructor
346 18 value_ref(float t) noexcept
347 18 : arg_(t)
348 18 , cf_{&from_builtin<
349 18 float>, &arg_.float_}
350 18 , what_(what::cfunc)
351 {
352 18 }
353
354 /// Constructor
355 34 value_ref(double t) noexcept
356 34 : arg_(t)
357 34 , cf_{&from_builtin<
358 34 double>, &arg_.double_}
359 34 , what_(what::cfunc)
360 {
361 34 }
362
363 /// Constructor
364 88 value_ref(std::nullptr_t) noexcept
365 88 : arg_(nullptr)
366 88 , cf_{&from_builtin<
367 88 std::nullptr_t>, &arg_.nullptr_}
368 88 , what_(what::cfunc)
369 {
370 88 }
371
372 #ifndef BOOST_JSON_DOCS
373 // Not public
374 //private:
375 // VFALCO Why is this needed?
376 /** Operator conversion to @ref value
377
378 This allows creation of a @ref value from
379 an initializer list element.
380 */
381 BOOST_JSON_DECL
382 operator value() const;
383 #endif
384
385 private:
386 template<class T>
387 static
388 value
389 from_builtin(
390 void const* p,
391 storage_ptr sp) noexcept;
392
393 template<class T>
394 static
395 value
396 from_const(
397 void const* p,
398 storage_ptr sp);
399
400 template<class T>
401 static
402 value
403 from_rvalue(
404 void* p,
405 storage_ptr sp);
406
407 static
408 BOOST_JSON_DECL
409 value
410 from_init_list(
411 void const* p,
412 storage_ptr sp);
413
414 inline
415 bool
416 is_key_value_pair() const noexcept;
417
418 static
419 inline
420 bool
421 maybe_object(
422 std::initializer_list<
423 value_ref> init) noexcept;
424
425 inline
426 string_view
427 get_string() const noexcept;
428
429 BOOST_JSON_DECL
430 value
431 make_value(
432 storage_ptr sp) const;
433
434 BOOST_JSON_DECL
435 static
436 value
437 make_value(
438 std::initializer_list<
439 value_ref> init,
440 storage_ptr sp);
441
442 BOOST_JSON_DECL
443 static
444 object
445 make_object(
446 std::initializer_list<value_ref> init,
447 storage_ptr sp);
448
449 BOOST_JSON_DECL
450 static
451 array
452 make_array(
453 std::initializer_list<
454 value_ref> init,
455 storage_ptr sp);
456
457 BOOST_JSON_DECL
458 static
459 void
460 write_array(
461 value* dest,
462 std::initializer_list<
463 value_ref> init,
464 storage_ptr const& sp);
465 };
466
467 } // namespace json
468 } // namespace boost
469
470 // Must be included here for this file to stand alone
471 #include <boost/json/value.hpp>
472
473 // includes are at the bottom of <boost/json/value.hpp>
474 //#include <boost/json/impl/value.hpp>
475 //#include <boost/json/impl/value.ipp>
476
477 #endif
478