100.00% Lines (13/13) 100.00% Functions (4/4)
TLA Baseline Branch
Line Hits Code Line Hits Code
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 of type `T` to @ref value using 23   This function attempts to convert an object of type `T` to @ref value using
24   24  
25   - one of @ref value's constructors, 25   - one of @ref value's constructors,
26   - a library-provided generic conversion, or 26   - a library-provided generic conversion, or
27   - a user-provided overload of `tag_invoke`. 27   - a user-provided overload of `tag_invoke`.
28   28  
29   In order to perform the conversion the function selects an appropriate 29   In order to perform the conversion the function selects an appropriate
30   implementation based on the types `T` and `Context` (if provided). 30   implementation based on the types `T` and `Context` (if provided).
31   31  
32   1. If `Context` is available and is not `std::tuple<C...>` 32   1. If `Context` is available and is not `std::tuple<C...>`
33   33  
34   a. check if `use_category<T, Context>::value` is not 34   a. check if `use_category<T, Context>::value` is not
35   @ref conversion_category::unknown; otherwise 35   @ref conversion_category::unknown; otherwise
36   36  
37   b. check if a `tag_invoke` overload from the list below that takes a 37   b. check if a `tag_invoke` overload from the list below that takes a
38   `Context const&` exists. 38   `Context const&` exists.
39   39  
40   2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat 40   2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat
41   steps **1** and **2** recursively for every `C` until either 41   steps **1** and **2** recursively for every `C` until either
42   step **1.a** or **1.b** succeeds for some `C`. 42   step **1.a** or **1.b** succeeds for some `C`.
43   43  
44   3. Failing that, 44   3. Failing that,
45   45  
46   a. check if `use_category<T>::value` is not 46   a. check if `use_category<T>::value` is not
47   @ref conversion_category::unknown; otherwise 47   @ref conversion_category::unknown; otherwise
48   48  
49   b. check if a `tag_invoke` overload from the list below that takes only 49   b. check if a `tag_invoke` overload from the list below that takes only
50   2 parameters exists; otherwise 50   2 parameters exists; otherwise
51   51  
52   c. check if `T` is one of @ref value, @ref array, @ref object, 52   c. check if `T` is one of @ref value, @ref array, @ref object,
53   or @ref string; otherwise 53   or @ref string; otherwise
54   54  
55   d. check if `T` matches one of the categories of types described in the 55   d. check if `T` matches one of the categories of types described in the
56   table "Conversion categories" in \<\<Value Conversion>> section. 56   table "Conversion categories" in \<\<Value Conversion>> section.
57   57  
58   These steps determine both the appropriate category of conversion for `T`, 58   These steps determine both the appropriate category of conversion for `T`,
59   and, if necessary, the effective context `C` that will be used for 59   and, if necessary, the effective context `C` that will be used for
60   conversion. If the category is selected on steps **1.a**, **3.a**, **3.c**, 60   conversion. If the category is selected on steps **1.a**, **3.a**, **3.c**,
61   or **3.d**, the library provides a suitable conversion implementation. 61   or **3.d**, the library provides a suitable conversion implementation.
62   If the category is selected on steps **2.b** or **3.b**, then a 62   If the category is selected on steps **2.b** or **3.b**, then a
63   user-provided `tag_invoke` overload is used. 63   user-provided `tag_invoke` overload is used.
64   64  
65   The overloads of `tag_invoke` that will be considered by this function 65   The overloads of `tag_invoke` that will be considered by this function
66   are in the following list. Overloads that appear higher in the list have 66   are in the following list. Overloads that appear higher in the list have
67   higher priority. 67   higher priority.
68   68  
69   @code 69   @code
70   template< class FullContext > 70   template< class FullContext >
71   void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& ); 71   void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& );
72   72  
73   void tag_invoke( value_from_tag, value&, T, const Context& ); 73   void tag_invoke( value_from_tag, value&, T, const Context& );
74   74  
75   void tag_invoke( value_from_tag, value&, T ); 75   void tag_invoke( value_from_tag, value&, T );
76   @endcode 76   @endcode
77   77  
78   The `ctx` argument can be used either as a tag type to provide conversions 78   The `ctx` argument can be used either as a tag type to provide conversions
79   for third-party types, or to pass extra data to the conversion function. 79   for third-party types, or to pass extra data to the conversion function.
80   80  
81   Overloads **(2)** and **(4)** construct their return value using the 81   Overloads **(2)** and **(4)** construct their return value using the
82   @ref storage_ptr `sp`, which ensures that the memory resource is correctly 82   @ref storage_ptr `sp`, which ensures that the memory resource is correctly
83   propagated. 83   propagated.
84   84  
85   @par Exception Safety 85   @par Exception Safety
86   Strong guarantee. 86   Strong guarantee.
87   87  
88   @tparam T The type of the object to convert. 88   @tparam T The type of the object to convert.
89   89  
90   @tparam Context The type of context passed to the conversion function. 90   @tparam Context The type of context passed to the conversion function.
91   91  
92   @param t The object to convert. 92   @param t The object to convert.
93   93  
94   @param ctx Context passed to the conversion function. 94   @param ctx Context passed to the conversion function.
95   95  
96   @param jv @ref value out parameter. 96   @param jv @ref value out parameter.
97   97  
98   @see @ref value_from_tag, @ref value_to, 98   @see @ref value_from_tag, @ref value_to,
99   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf"> 99   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
100   tag_invoke: A general pattern for supporting customisable functions</a> 100   tag_invoke: A general pattern for supporting customisable functions</a>
101   */ 101   */
102   /// @{ 102   /// @{
103   template< class T, class Context > 103   template< class T, class Context >
104   void 104   void
HITCBC 105   7088 value_from( 105   7088 value_from(
106   T&& t, 106   T&& t,
107   Context const& ctx, 107   Context const& ctx,
108   value& jv) 108   value& jv)
109   { 109   {
110   using bare_T = detail::remove_cvref<T>; 110   using bare_T = detail::remove_cvref<T>;
111   using cat = detail::value_from_category<Context, bare_T>; 111   using cat = detail::value_from_category<Context, bare_T>;
HITCBC 112   7088 detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx ); 112   7088 detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx );
HITCBC 113   7087 } 113   7087 }
114   114  
115   /** Overload 115   /** Overload
116   @param t 116   @param t
117   @param ctx 117   @param ctx
118   @param sp A storage pointer referring to the memory resource to use for the 118   @param sp A storage pointer referring to the memory resource to use for the
119   returned @ref value. 119   returned @ref value.
120   120  
121   @return Overloads **(2)** and **(4)** return `t` converted to @ref value. 121   @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
122   Overloads **(1)** and **3** return `void` instead and pass their result via 122   Overloads **(1)** and **3** return `void` instead and pass their result via
123   the out parameter `jv`. 123   the out parameter `jv`.
124   */ 124   */
125   template< class T, class Context > 125   template< class T, class Context >
126   #ifndef BOOST_JSON_DOCS 126   #ifndef BOOST_JSON_DOCS
127   typename std::enable_if< 127   typename std::enable_if<
128   !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value && 128   !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
129   !std::is_same< detail::remove_cvref<Context>, value >::value, 129   !std::is_same< detail::remove_cvref<Context>, value >::value,
130   value >::type 130   value >::type
131   #else 131   #else
132   value 132   value
133   #endif 133   #endif
HITCBC 134   7065 value_from( 134   7065 value_from(
135   T&& t, 135   T&& t,
136   Context const& ctx, 136   Context const& ctx,
137   storage_ptr sp = {}) 137   storage_ptr sp = {})
138   { 138   {
HITCBC 139   7065 value jv(std::move(sp)); 139   7065 value jv(std::move(sp));
HITCBC 140   7065 value_from( static_cast<T&&>(t), ctx, jv ); 140   7065 value_from( static_cast<T&&>(t), ctx, jv );
HITCBC 141   7064 return jv; 141   7064 return jv;
HITCBC 142   1 } 142   1 }
143   143  
144   /// Overload 144   /// Overload
145   template<class T> 145   template<class T>
146   void 146   void
HITCBC 147   23 value_from( 147   23 value_from(
148   T&& t, 148   T&& t,
149   value& jv) 149   value& jv)
150   { 150   {
HITCBC 151   23 value_from( static_cast<T&&>(t), detail::no_context(), jv ); 151   23 value_from( static_cast<T&&>(t), detail::no_context(), jv );
HITCBC 152   23 } 152   23 }
153   153  
154   /// Overload 154   /// Overload
155   template<class T> 155   template<class T>
156   value 156   value
HITCBC 157   308 value_from( 157   308 value_from(
158   T&& t, 158   T&& t,
159   storage_ptr sp = {}) 159   storage_ptr sp = {})
160   { 160   {
161   return value_from( 161   return value_from(
HITCBC 162   308 static_cast<T&&>(t), detail::no_context(), std::move(sp) ); 162   308 static_cast<T&&>(t), detail::no_context(), std::move(sp) );
163   } 163   }
164   /// @} 164   /// @}
165   165  
166   /** Determine if `T` can be converted to @ref value. 166   /** Determine if `T` can be converted to @ref value.
167   167  
168   If `T` can be converted to @ref value via a call to @ref value_from, the 168   If `T` can be converted to @ref value via a call to @ref value_from, the
169   static data member `value` is defined as `true`. Otherwise, `value` is 169   static data member `value` is defined as `true`. Otherwise, `value` is
170   defined as `false`. 170   defined as `false`.
171   171  
172   @see @ref value_from. 172   @see @ref value_from.
173   */ 173   */
174   #ifdef BOOST_JSON_DOCS 174   #ifdef BOOST_JSON_DOCS
175   template<class T> 175   template<class T>
176   using has_value_from = __see_below__; 176   using has_value_from = __see_below__;
177   #else 177   #else
178   template<class T> 178   template<class T>
179   using has_value_from = detail::can_convert< 179   using has_value_from = detail::can_convert<
180   detail::remove_cvref<T>, detail::value_from_conversion>; 180   detail::remove_cvref<T>, detail::value_from_conversion>;
181   #endif 181   #endif
182   182  
183   } // namespace json 183   } // namespace json
184   } // namespace boost 184   } // namespace boost
185   185  
186   #endif 186   #endif