/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 |