123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- //
- // Copyright (c) 2019 Vinnie Falco ([email protected])
- //
- // 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 <boost/json/detail/config.hpp>
- #include <boost/json/storage_ptr.hpp>
- #include <boost/json/string.hpp>
- #include <initializer_list>
- #include <type_traits>
- #include <utility>
- namespace boost {
- namespace json {
- #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 `boost::container::pmr::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<value_ref>;
- 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_() {}
- };
- 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<class T>
- value_ref(
- T const& t
- #ifndef BOOST_JSON_DOCS
- ,typename std::enable_if<
- ! std::is_constructible<
- string_view, T>::value &&
- ! std::is_same<bool, T>::value
- >::type* = 0
- #endif
- ) noexcept
- : cf_{&from_const<T>, &t}
- , what_(what::cfunc)
- {
- }
- /// Constructor
- template<class T>
- value_ref(
- T&& t
- #ifndef BOOST_JSON_DOCS
- ,typename std::enable_if<
- (! std::is_constructible<
- string_view, T>::value ||
- std::is_same<string, T>::value) &&
- ! std::is_same<bool,
- detail::remove_cvref<T>>::value &&
- std::is_same<T, detail::remove_cvref<T>>
- ::value>::type* = 0
- #endif
- ) noexcept
- : f_{&from_rvalue<
- detail::remove_cvref<T>>, &t}
- , what_(std::is_same<string, T>::value ?
- what::strfunc : what::func)
- {
- }
- /// Constructor
- #ifdef BOOST_JSON_DOCS
- value_ref(bool b) noexcept;
- #else
- template<
- class T
- ,class = typename std::enable_if<
- std::is_same<T, bool>::value>::type
- >
- value_ref(
- T b) noexcept
- : arg_(b)
- , cf_{&from_builtin<bool>, &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<signed char>, &arg_.schar_}
- , what_(what::cfunc)
- {
- }
- /// Constructor
- value_ref(short t) noexcept
- : arg_(t)
- , cf_{&from_builtin<short>, &arg_.short_}
- , what_(what::cfunc)
- {
- }
- /// Constructor
- value_ref(int t) noexcept
- : arg_(t)
- , cf_{&from_builtin<int>, &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<class T>
- static
- value
- from_builtin(
- void const* p,
- storage_ptr sp) noexcept;
- template<class T>
- static
- value
- from_const(
- void const* p,
- storage_ptr sp);
- template<class T>
- 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<value_ref> 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);
- };
- } // namespace json
- } // namespace boost
- // Must be included here for this file to stand alone
- #include <boost/json/value.hpp>
- // includes are at the bottom of <boost/json/value.hpp>
- //#include <boost/json/impl/value.hpp>
- //#include <boost/json/impl/value.ipp>
- #endif
|