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 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 911 : value_ref(
184 : T const& t) noexcept
185 911 : : arg_(string_view(t))
186 911 : , what_(what::str)
187 : {
188 :
189 911 : }
190 : #endif
191 :
192 : /// Constructor
193 : template<class T>
194 22 : 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 22 : : cf_{&from_const<T>, &t}
205 22 : , what_(what::cfunc)
206 : {
207 22 : }
208 :
209 : /// Constructor
210 : template<class T>
211 103 : 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 103 : : f_{&from_rvalue<
225 : detail::remove_cvref<T>>, &t}
226 103 : , what_(std::is_same<string, T>::value ?
227 103 : what::strfunc : what::func)
228 : {
229 103 : }
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
|