1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
3  
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4  
// Copyright (c) 2022 Dmitry Arkhipov (grisumbras@gmail.com)
4  
// Copyright (c) 2022 Dmitry Arkhipov (grisumbras@gmail.com)
5  
//
5  
//
6  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8  
//
8  
//
9  
// Official repository: https://github.com/boostorg/json
9  
// Official repository: https://github.com/boostorg/json
10  
//
10  
//
11  

11  

12  
#ifndef BOOST_JSON_VALUE_FROM_HPP
12  
#ifndef BOOST_JSON_VALUE_FROM_HPP
13  
#define BOOST_JSON_VALUE_FROM_HPP
13  
#define BOOST_JSON_VALUE_FROM_HPP
14  

14  

15  
#include <boost/core/detail/static_assert.hpp>
15  
#include <boost/core/detail/static_assert.hpp>
16  
#include <boost/json/detail/value_from.hpp>
16  
#include <boost/json/detail/value_from.hpp>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace json {
19  
namespace json {
20  

20  

21  
/** Convert an object of type `T` to @ref value.
21  
/** Convert an object of type `T` to @ref value.
22  

22  

23  
    This function attempts to convert an object
23  
    This function attempts to convert an object
24  
    of type `T` to @ref value using
24  
    of type `T` to @ref value using
25  

25  

26  
    @li one of @ref value's constructors,
26  
    @li one of @ref value's constructors,
27  

27  

28  
    @li a library-provided generic conversion, or
28  
    @li a library-provided generic conversion, or
29  

29  

30  
    @li a user-provided overload of `tag_invoke`.
30  
    @li a user-provided overload of `tag_invoke`.
31  

31  

32  
    Out of the function supports default constructible types satisfying
32  
    Out of the function supports default constructible types satisfying
33  
    {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
33  
    {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
34  
    `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
34  
    `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
35  
    and enums described using Boost.Describe.
35  
    and enums described using Boost.Describe.
36  

36  

37  
    Conversion of other types is done by calling an overload of `tag_invoke`
37  
    Conversion of other types is done by calling an overload of `tag_invoke`
38  
    found by argument-dependent lookup. Its signature should be similar to:
38  
    found by argument-dependent lookup. Its signature should be similar to:
39  

39  

40  
    @code
40  
    @code
41  
    template< class FullContext >
41  
    template< class FullContext >
42  
    void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& );
42  
    void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& );
43  
    @endcode
43  
    @endcode
44  

44  

45  
    or
45  
    or
46  

46  

47  
    @code
47  
    @code
48  
    void tag_invoke( value_from_tag, value&, T, const Context& );
48  
    void tag_invoke( value_from_tag, value&, T, const Context& );
49  
    @endcode
49  
    @endcode
50  

50  

51  
    or
51  
    or
52  

52  

53  
    @code
53  
    @code
54  
    void tag_invoke( value_from_tag, value&, T );
54  
    void tag_invoke( value_from_tag, value&, T );
55  
    @endcode
55  
    @endcode
56  

56  

57  
    The overloads are checked for existence in that order and the first that
57  
    The overloads are checked for existence in that order and the first that
58  
    matches will be selected. <br>
58  
    matches will be selected. <br>
59  

59  

60  
    The `ctx` argument can be used either as a tag type to provide conversions
60  
    The `ctx` argument can be used either as a tag type to provide conversions
61  
    for third-party types, or to pass extra data to the conversion function.
61  
    for third-party types, or to pass extra data to the conversion function.
62  

62  

63  
    Overloads **(2)** and **(4)** construct their return value using the
63  
    Overloads **(2)** and **(4)** construct their return value using the
64  
    @ref storage_ptr `sp`, which ensures that the memory resource is correctly
64  
    @ref storage_ptr `sp`, which ensures that the memory resource is correctly
65  
    propagated.
65  
    propagated.
66  

66  

67  
    @par Exception Safety
67  
    @par Exception Safety
68  
    Strong guarantee.
68  
    Strong guarantee.
69  

69  

70  
    @tparam T The type of the object to convert.
70  
    @tparam T The type of the object to convert.
71  

71  

72  
    @tparam Context The type of context passed to the conversion function.
72  
    @tparam Context The type of context passed to the conversion function.
73  

73  

74  
    @param t The object to convert.
74  
    @param t The object to convert.
75  

75  

76  
    @param ctx Context passed to the conversion function.
76  
    @param ctx Context passed to the conversion function.
77  

77  

78  
    @param jv @ref value out parameter.
78  
    @param jv @ref value out parameter.
79  

79  

80  
    @see @ref value_from_tag, @ref value_to,
80  
    @see @ref value_from_tag, @ref value_to,
81  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
81  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
82  
        tag_invoke: A general pattern for supporting customisable functions</a>
82  
        tag_invoke: A general pattern for supporting customisable functions</a>
83  
*/
83  
*/
84  
/// @{
84  
/// @{
85  
template< class T, class Context >
85  
template< class T, class Context >
86  
void
86  
void
87  
value_from(
87  
value_from(
88  
    T&& t,
88  
    T&& t,
89  
    Context const& ctx,
89  
    Context const& ctx,
90  
    value& jv)
90  
    value& jv)
91  
{
91  
{
92  
    using bare_T = detail::remove_cvref<T>;
92  
    using bare_T = detail::remove_cvref<T>;
93  
    BOOST_CORE_STATIC_ASSERT((
93  
    BOOST_CORE_STATIC_ASSERT((
94  
        detail::conversion_round_trips<
94  
        detail::conversion_round_trips<
95  
            Context, bare_T, detail::value_from_conversion>::value));
95  
            Context, bare_T, detail::value_from_conversion>::value));
96  
    using cat = detail::value_from_category<Context, bare_T>;
96  
    using cat = detail::value_from_category<Context, bare_T>;
97  
    detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx );
97  
    detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx );
98  
}
98  
}
99  

99  

100  
/** Overload
100  
/** Overload
101  
   @param t
101  
   @param t
102  
   @param ctx
102  
   @param ctx
103  
   @param sp A storage pointer referring to the memory resource to use for the
103  
   @param sp A storage pointer referring to the memory resource to use for the
104  
   returned @ref value.
104  
   returned @ref value.
105  

105  

106  
   @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
106  
   @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
107  
   Overloads **(1)** and **3** return `void` instead and pass their result via
107  
   Overloads **(1)** and **3** return `void` instead and pass their result via
108  
   the out parameter `jv`.
108  
   the out parameter `jv`.
109  
*/
109  
*/
110  
template< class T, class Context >
110  
template< class T, class Context >
111  
#ifndef BOOST_JSON_DOCS
111  
#ifndef BOOST_JSON_DOCS
112  
typename std::enable_if<
112  
typename std::enable_if<
113  
    !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
113  
    !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
114  
    !std::is_same< detail::remove_cvref<Context>, value >::value,
114  
    !std::is_same< detail::remove_cvref<Context>, value >::value,
115  
    value >::type
115  
    value >::type
116  
#else
116  
#else
117  
value
117  
value
118  
#endif
118  
#endif
119  
value_from(
119  
value_from(
120  
    T&& t,
120  
    T&& t,
121  
    Context const& ctx,
121  
    Context const& ctx,
122  
    storage_ptr sp = {})
122  
    storage_ptr sp = {})
123  
{
123  
{
124  
    value jv(std::move(sp));
124  
    value jv(std::move(sp));
125  
    value_from( static_cast<T&&>(t), ctx, jv );
125  
    value_from( static_cast<T&&>(t), ctx, jv );
126  
    return jv;
126  
    return jv;
127  
}
127  
}
128  

128  

129  
/// Overload
129  
/// Overload
130  
template<class T>
130  
template<class T>
131  
void
131  
void
132  
value_from(
132  
value_from(
133  
    T&& t,
133  
    T&& t,
134  
    value& jv)
134  
    value& jv)
135  
{
135  
{
136  
   value_from( static_cast<T&&>(t), detail::no_context(), jv );
136  
   value_from( static_cast<T&&>(t), detail::no_context(), jv );
137  
}
137  
}
138  

138  

139  
/// Overload
139  
/// Overload
140  
template<class T>
140  
template<class T>
141  
value
141  
value
142  
value_from(
142  
value_from(
143  
    T&& t,
143  
    T&& t,
144  
    storage_ptr sp = {})
144  
    storage_ptr sp = {})
145  
{
145  
{
146  
   return value_from(
146  
   return value_from(
147  
           static_cast<T&&>(t), detail::no_context(), std::move(sp) );
147  
           static_cast<T&&>(t), detail::no_context(), std::move(sp) );
148  
}
148  
}
149  
/// @}
149  
/// @}
150  

150  

151  
/** Determine if `T` can be converted to @ref value.
151  
/** Determine if `T` can be converted to @ref value.
152  

152  

153  
    If `T` can be converted to @ref value via a call to @ref value_from, the
153  
    If `T` can be converted to @ref value via a call to @ref value_from, the
154  
    static data member `value` is defined as `true`. Otherwise, `value` is
154  
    static data member `value` is defined as `true`. Otherwise, `value` is
155  
    defined as `false`.
155  
    defined as `false`.
156  

156  

157  
    @see @ref value_from.
157  
    @see @ref value_from.
158  
*/
158  
*/
159  
#ifdef BOOST_JSON_DOCS
159  
#ifdef BOOST_JSON_DOCS
160  
template<class T>
160  
template<class T>
161  
using has_value_from = __see_below__;
161  
using has_value_from = __see_below__;
162  
#else
162  
#else
163  
template<class T>
163  
template<class T>
164  
using has_value_from = detail::can_convert<
164  
using has_value_from = detail::can_convert<
165  
    detail::remove_cvref<T>, detail::value_from_conversion>;
165  
    detail::remove_cvref<T>, detail::value_from_conversion>;
166  
#endif
166  
#endif
167  

167  

168  
} // namespace json
168  
} // namespace json
169  
} // namespace boost
169  
} // namespace boost
170  

170  

171  
#endif
171  
#endif