Line data Source code
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 1002 : value_ref(
188 : T const& t) noexcept
189 1002 : : arg_(string_view(t))
190 1002 : , what_(what::str)
191 : {
192 :
193 1002 : }
194 : #endif
195 :
196 : /// Constructor
197 : template<class T>
198 22 : 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 22 : : cf_{&from_const<T>, &t}
209 22 : , what_(what::cfunc)
210 : {
211 22 : }
212 :
213 : /// Constructor
214 : template<class T>
215 76 : 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 76 : : f_{&from_rvalue<
229 : detail::remove_cvref<T>>, &t}
230 76 : , what_(std::is_same<string, T>::value ?
231 76 : what::strfunc : what::func)
232 : {
233 76 : }
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
|