// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/json // #ifndef BOOST_JSON_VALUE_REF_HPP #define BOOST_JSON_VALUE_REF_HPP #include #include #include #include #include #include BOOST_JSON_NS_BEGIN #ifndef BOOST_JSON_DOCS class value; class object; class array; class string; #endif //---------------------------------------------------------- /** The type used in initializer lists. This type is used in initializer lists for lazy construction of and assignment to the container types @ref value, @ref array, and @ref object. The two types of initializer lists used are: @li `std::initializer_list< value_ref >` for constructing or assigning a @ref value or @ref array, and @li `std::initializer_list< std::pair< string_view, value_ref > >` for constructing or assigning an @ref object. A `value_ref` uses reference semantics. Creation of the actual container from the initializer list is lazily deferred until the list is used. This means that the @ref memory_resource used to construct a container can be specified after the point where the initializer list is specified. @par Example This example demonstrates how a user-defined type containing a JSON value can be constructed from an initializer list: @code class my_type { value jv_; public: my_type( std::initializer_list< value_ref > init ) : jv_(init) { } }; @endcode @note Never declare a variable of type `std::initializer_list` except in function parameter lists, otherwise the behavior may be undefined. @see @ref value, @ref array, @ref object */ class value_ref { friend class value; friend class object; friend class array; friend class value_ref_test; enum class what { str, ini, func, cfunc, strfunc, }; using init_list = std::initializer_list; struct func_type { value(*f)(void*, storage_ptr); void* p; }; struct cfunc_type { value(*f)(void const*, storage_ptr); void const* p; }; union arg_type { string_view str_; init_list init_list_; signed char schar_; short short_; int int_; long long_; long long long_long_; unsigned char uchar_; unsigned short ushort_; unsigned int uint_; unsigned long ulong_; unsigned long long ulong_long_; float float_; double double_; bool bool_; std::nullptr_t nullptr_; arg_type() {} explicit arg_type(string_view t) noexcept : str_(t) {} explicit arg_type(init_list t) noexcept : init_list_(t) {} explicit arg_type(signed char t) noexcept : schar_(t) {} explicit arg_type(short t) noexcept : short_(t) {} explicit arg_type(int t) noexcept : int_(t) {} explicit arg_type(long t) noexcept : long_(t) {} explicit arg_type(long long t) noexcept : long_long_(t) {} explicit arg_type(unsigned char t) noexcept : uchar_(t) {} explicit arg_type(unsigned short t) noexcept : ushort_(t) {} explicit arg_type(unsigned int t) noexcept : uint_(t) {} explicit arg_type(unsigned long t) noexcept : ulong_(t) {} explicit arg_type(unsigned long long t) noexcept : ulong_long_(t) {} explicit arg_type(float t) noexcept : float_(t) {} explicit arg_type(double t) noexcept : double_(t) {} explicit arg_type(bool t) noexcept : bool_(t) {} explicit arg_type(std::nullptr_t) noexcept : nullptr_() {} }; template using is_builtin = std::integral_constant::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value>; arg_type arg_; #ifndef BOOST_JSON_DOCS // VFALCO doc toolchain erroneously // displays private, anonymous unions as public union { func_type f_; cfunc_type cf_; }; #endif what what_; public: /// Constructor value_ref( value_ref const&) = default; /// Constructor #ifdef BOOST_JSON_DOCS value_ref(string_view s) noexcept; #else template< class T ,class = typename std::enable_if< std::is_constructible< string_view, T>::value>::type > value_ref( T const& t) noexcept : arg_(string_view(t)) , what_(what::str) { } #endif /// Constructor template value_ref( T const& t #ifndef BOOST_JSON_DOCS ,typename std::enable_if< ! std::is_constructible< string_view, T>::value && ! std::is_same::value >::type* = 0 #endif ) noexcept : cf_{&from_const, &t} , what_(what::cfunc) { } /// Constructor template value_ref( T&& t #ifndef BOOST_JSON_DOCS ,typename std::enable_if< (! std::is_constructible< string_view, T>::value || std::is_same::value) && ! std::is_same>::value && std::is_same> ::value>::type* = 0 #endif ) noexcept : f_{&from_rvalue< detail::remove_cvref>, &t} , what_(std::is_same::value ? what::strfunc : what::func) { } /// Constructor #ifdef BOOST_JSON_DOCS value_ref(bool b) noexcept; #else template< class Bool ,class = typename std::enable_if< std::is_same::value>::type > value_ref( Bool b) noexcept : arg_(b) , cf_{&from_builtin, &arg_.bool_} , what_(what::cfunc) { } #endif /// Constructor value_ref( std::initializer_list< value_ref> t) noexcept : arg_(t) , what_(what::ini) { } /// Constructor value_ref(signed char t) noexcept : arg_(t) , cf_{&from_builtin, &arg_.schar_} , what_(what::cfunc) { } /// Constructor value_ref(short t) noexcept : arg_(t) , cf_{&from_builtin, &arg_.short_} , what_(what::cfunc) { } /// Constructor value_ref(int t) noexcept : arg_(t) , cf_{&from_builtin, &arg_.int_} , what_(what::cfunc) { } /// Constructor value_ref(long t) noexcept : arg_(t) , cf_{&from_builtin< long>, &arg_.long_} , what_(what::cfunc) { } /// Constructor value_ref(long long t) noexcept : arg_(t) , cf_{&from_builtin< long long>, &arg_.long_long_} , what_(what::cfunc) { } /// Constructor value_ref(unsigned char t) noexcept : arg_(t) , cf_{&from_builtin< unsigned char>, &arg_.uchar_} , what_(what::cfunc) { } /// Constructor value_ref(unsigned short t) noexcept : arg_(t) , cf_{&from_builtin< unsigned short>, &arg_.ushort_} , what_(what::cfunc) { } /// Constructor value_ref(unsigned int t) noexcept : arg_(t) , cf_{&from_builtin< unsigned int>, &arg_.uint_} , what_(what::cfunc) { } /// Constructor value_ref(unsigned long t) noexcept : arg_(t) , cf_{&from_builtin< unsigned long>, &arg_.ulong_} , what_(what::cfunc) { } /// Constructor value_ref(unsigned long long t) noexcept : arg_(t) , cf_{&from_builtin< unsigned long long>, &arg_.ulong_long_} , what_(what::cfunc) { } /// Constructor value_ref(float t) noexcept : arg_(t) , cf_{&from_builtin< float>, &arg_.float_} , what_(what::cfunc) { } /// Constructor value_ref(double t) noexcept : arg_(t) , cf_{&from_builtin< double>, &arg_.double_} , what_(what::cfunc) { } /// Constructor value_ref(std::nullptr_t) noexcept : arg_(nullptr) , cf_{&from_builtin< std::nullptr_t>, &arg_.nullptr_} , what_(what::cfunc) { } #ifndef BOOST_JSON_DOCS // Not public //private: // VFALCO Why is this needed? /** Operator conversion to @ref value This allows creation of a @ref value from an initializer list element. */ BOOST_JSON_DECL operator value() const; #endif private: template static value from_builtin( void const* p, storage_ptr sp) noexcept; template static value from_const( void const* p, storage_ptr sp); template static value from_rvalue( void* p, storage_ptr sp); static BOOST_JSON_DECL value from_init_list( void const* p, storage_ptr sp); inline bool is_key_value_pair() const noexcept; static inline bool maybe_object( std::initializer_list< value_ref> init) noexcept; inline string_view get_string() const noexcept; BOOST_JSON_DECL value make_value( storage_ptr sp) const; BOOST_JSON_DECL static value make_value( std::initializer_list< value_ref> init, storage_ptr sp); BOOST_JSON_DECL static object make_object( std::initializer_list init, storage_ptr sp); BOOST_JSON_DECL static array make_array( std::initializer_list< value_ref> init, storage_ptr sp); BOOST_JSON_DECL static void write_array( value* dest, std::initializer_list< value_ref> init, storage_ptr const& sp); }; BOOST_JSON_NS_END // Must be included here for this file to stand alone #include // includes are at the bottom of //#include //#include #endif