100.00% Lines (9/9) 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_TO_HPP 12   #ifndef BOOST_JSON_VALUE_TO_HPP
13   #define BOOST_JSON_VALUE_TO_HPP 13   #define BOOST_JSON_VALUE_TO_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_to.hpp> 16   #include <boost/json/detail/value_to.hpp>
17   17  
18   namespace boost { 18   namespace boost {
19   namespace json { 19   namespace json {
20   20  
21   /** Convert a @ref value to an object of type `T`. 21   /** Convert a @ref value to an object of type `T`.
22   22  
23   This function attempts to convert a @ref value to `T` using 23   This function attempts to convert a @ref value to `T` using
24   24  
25   - one of @ref value's accessors, or 25   - one of @ref value's accessors, or
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   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context&, const FullContext& ); 71   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context&, const FullContext& );
72   72  
73   template< class FullContext > 73   template< class FullContext >
74   T tag_invoke( value_to_tag<T>, const value&, const Context&, const FullContext& ); 74   T tag_invoke( value_to_tag<T>, const value&, const Context&, const FullContext& );
75   75  
76   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& ); 76   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& );
77   77  
78   T tag_invoke( value_to_tag<T>, const value&, const Context& ); 78   T tag_invoke( value_to_tag<T>, const value&, const Context& );
79   79  
80   result<T> tag_invoke( try_value_to_tag<T>, const value& ); 80   result<T> tag_invoke( try_value_to_tag<T>, const value& );
81   81  
82   T tag_invoke( value_to_tag<T>, const value& ); 82   T tag_invoke( value_to_tag<T>, const value& );
83   @endcode 83   @endcode
84   84  
85   For `tag_invoke` overloads that take a parameter of type `value_to_tag<T>` 85   For `tag_invoke` overloads that take a parameter of type `value_to_tag<T>`
86   the object returned by a call to that overload is returned by the function 86   the object returned by a call to that overload is returned by the function
87   as the result of the conversion. For overloads that take a parameter of 87   as the result of the conversion. For overloads that take a parameter of
88   type `try_value_to_tag<T>` if the returned `result` contains a value, that 88   type `try_value_to_tag<T>` if the returned `result` contains a value, that
89   value is returned as the result of the conversion. Otherwise, an exception 89   value is returned as the result of the conversion. Otherwise, an exception
90   of type @ref boost::system::system_error that stores the error is thrown. 90   of type @ref boost::system::system_error that stores the error is thrown.
91   91  
92   The `ctx` argument can be used either as a tag type to provide conversions 92   The `ctx` argument can be used either as a tag type to provide conversions
93   for third-party types, or to pass extra data to the conversion function. 93   for third-party types, or to pass extra data to the conversion function.
94   94  
95   Overload **(3)** is **deleted** and participates in overload resolution 95   Overload **(3)** is **deleted** and participates in overload resolution
96   only when `U` is not @ref value. The overload exists to prevent unintented 96   only when `U` is not @ref value. The overload exists to prevent unintented
97   creation of temporary @ref value instances, e.g. 97   creation of temporary @ref value instances, e.g.
98   98  
99   @code 99   @code
100   auto flag = value_to<bool>(true); 100   auto flag = value_to<bool>(true);
101   @endcode 101   @endcode
102   102  
103   @par Constraints 103   @par Constraints
104   @code 104   @code
105   ! std::is_reference< T >::value 105   ! std::is_reference< T >::value
106   @endcode 106   @endcode
107   107  
108   @par Exception Safety 108   @par Exception Safety
109   Strong guarantee. 109   Strong guarantee.
110   110  
111   @tparam T The type to convert to. 111   @tparam T The type to convert to.
112   112  
113   @tparam Context The type of context passed to the conversion function. 113   @tparam Context The type of context passed to the conversion function.
114   114  
115   @returns `jv` converted to `T`. 115   @returns `jv` converted to `T`.
116   116  
117   @param jv The @ref value to convert. 117   @param jv The @ref value to convert.
118   118  
119   @param ctx Context passed to the conversion function. 119   @param ctx Context passed to the conversion function.
120   120  
121   @see @ref try_value_to, @ref value_from, 121   @see @ref try_value_to, @ref value_from,
122   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf"> 122   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
123   tag_invoke: A general pattern for supporting customisable functions</a> 123   tag_invoke: A general pattern for supporting customisable functions</a>
124   124  
125   @{ 125   @{
126   */ 126   */
127   template< class T, class Context > 127   template< class T, class Context >
128   T 128   T
HITCBC 129   413 value_to( value const& jv, Context const& ctx ) 129   413 value_to( value const& jv, Context const& ctx )
130   { 130   {
131   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value ); 131   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
132   using bare_T = detail::remove_cvref<T>; 132   using bare_T = detail::remove_cvref<T>;
133   using cat = detail::value_to_category<Context, bare_T>; 133   using cat = detail::value_to_category<Context, bare_T>;
HITCBC 134   413 return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx ); 134   413 return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx );
135   } 135   }
136   136  
137   /// Overload 137   /// Overload
138   template<class T> 138   template<class T>
139   T 139   T
HITCBC 140   134 value_to(const value& jv) 140   134 value_to(const value& jv)
141   { 141   {
HITCBC 142   198 return value_to<T>( jv, detail::no_context() ); 142   198 return value_to<T>( jv, detail::no_context() );
143   } 143   }
144   144  
145   /// Overload 145   /// Overload
146   template<class T, class U 146   template<class T, class U
147   #ifndef BOOST_JSON_DOCS 147   #ifndef BOOST_JSON_DOCS
148   , class = typename std::enable_if<!std::is_same<U, value>::value>::type 148   , class = typename std::enable_if<!std::is_same<U, value>::value>::type
149   #endif 149   #endif
150   > 150   >
151   T 151   T
152   value_to(U const& jv) = delete; 152   value_to(U const& jv) = delete;
153   /// @} 153   /// @}
154   154  
155   /** Convert a @ref value to a @ref boost::system::result. 155   /** Convert a @ref value to a @ref boost::system::result.
156   156  
157   This function attempts to convert a @ref value to `result<T>` using 157   This function attempts to convert a @ref value to `result<T>` using
158   158  
159   - one of @ref value's accessors, or 159   - one of @ref value's accessors, or
160   - a library-provided generic conversion, or 160   - a library-provided generic conversion, or
161   - a user-provided overload of `tag_invoke`. 161   - a user-provided overload of `tag_invoke`.
162   162  
163   In order to perform the conversion the function selects an appropriate 163   In order to perform the conversion the function selects an appropriate
164   implementation based on the types `T` and `Context` (if provided). 164   implementation based on the types `T` and `Context` (if provided).
165   165  
166   1. If `Context` is available and is not `std::tuple<C...>` 166   1. If `Context` is available and is not `std::tuple<C...>`
167   167  
168   a. check if `use_category<T, Context>::value` is not 168   a. check if `use_category<T, Context>::value` is not
169   @ref conversion_category::unknown; otherwise 169   @ref conversion_category::unknown; otherwise
170   170  
171   b. check if a `tag_invoke` overload from the list below that takes a 171   b. check if a `tag_invoke` overload from the list below that takes a
172   `Context const&` exists. 172   `Context const&` exists.
173   173  
174   2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat 174   2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat
175   steps **1** and **2** recursively for every `C` until either 175   steps **1** and **2** recursively for every `C` until either
176   step **1.a** or **1.b** succeeds for some `C`. 176   step **1.a** or **1.b** succeeds for some `C`.
177   177  
178   3. Failing that, 178   3. Failing that,
179   179  
180   a. check if `use_category<T>::value` is not 180   a. check if `use_category<T>::value` is not
181   @ref conversion_category::unknown; otherwise 181   @ref conversion_category::unknown; otherwise
182   182  
183   b. check if a `tag_invoke` overload from the list below that takes only 183   b. check if a `tag_invoke` overload from the list below that takes only
184   2 parameters exists; otherwise 184   2 parameters exists; otherwise
185   185  
186   c. check if `T` is one of @ref value, @ref array, @ref object, 186   c. check if `T` is one of @ref value, @ref array, @ref object,
187   or @ref string; otherwise 187   or @ref string; otherwise
188   188  
189   d. check if `T` matches one of the categories of types described in the 189   d. check if `T` matches one of the categories of types described in the
190   table "Conversion categories" in \<\<Value Conversion>> section. 190   table "Conversion categories" in \<\<Value Conversion>> section.
191   191  
192   These steps determine both the appropriate category of conversion for `T`, 192   These steps determine both the appropriate category of conversion for `T`,
193   and, if necessary, the effective context `C` that will be used for 193   and, if necessary, the effective context `C` that will be used for
194   conversion. If the category is selected on steps **1.a**, **3.a**, **3.c**, 194   conversion. If the category is selected on steps **1.a**, **3.a**, **3.c**,
195   or **3.d**, the library provides a suitable conversion implementation. 195   or **3.d**, the library provides a suitable conversion implementation.
196   If the category is selected on steps **2.b** or **3.b**, then a 196   If the category is selected on steps **2.b** or **3.b**, then a
197   user-provided `tag_invoke` overload is used. 197   user-provided `tag_invoke` overload is used.
198   198  
199   The overloads of `tag_invoke` that will be considered by this function 199   The overloads of `tag_invoke` that will be considered by this function
200   are in the following list. Overloads that appear higher in the list have 200   are in the following list. Overloads that appear higher in the list have
201   higher priority. 201   higher priority.
202   202  
203   @code 203   @code
204   template< class FullContext > 204   template< class FullContext >
205   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context&, const FullContext& ); 205   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context&, const FullContext& );
206   206  
207   template< class FullContext > 207   template< class FullContext >
208   T tag_invoke( value_to_tag<T>, const value&, const Context&, const FullContext& ); 208   T tag_invoke( value_to_tag<T>, const value&, const Context&, const FullContext& );
209   209  
210   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& ); 210   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& );
211   211  
212   T tag_invoke( value_to_tag<T>, const value&, const Context& ); 212   T tag_invoke( value_to_tag<T>, const value&, const Context& );
213   213  
214   result<T> tag_invoke( try_value_to_tag<T>, const value& ); 214   result<T> tag_invoke( try_value_to_tag<T>, const value& );
215   215  
216   T tag_invoke( value_to_tag<T>, const value& ); 216   T tag_invoke( value_to_tag<T>, const value& );
217   @endcode 217   @endcode
218   218  
219   For `tag_invoke` overloads that take a parameter of type 219   For `tag_invoke` overloads that take a parameter of type
220   `try_value_to_tag<T>` the object returned by a call to that overload is 220   `try_value_to_tag<T>` the object returned by a call to that overload is
221   returned by the function as the result of the conversion. For overloads 221   returned by the function as the result of the conversion. For overloads
222   that take a parameter of type `value_to_tag<T>` the returned object is 222   that take a parameter of type `value_to_tag<T>` the returned object is
223   wrapped with a `result<T>`. 223   wrapped with a `result<T>`.
224   224  
225   If an error occurs during conversion, the result will store the error code 225   If an error occurs during conversion, the result will store the error code
226   associated with the error. If an exception is thrown, the function will 226   associated with the error. If an exception is thrown, the function will
227   attempt to retrieve the associated error code and return it, otherwise it 227   attempt to retrieve the associated error code and return it, otherwise it
228   will return @ref error::exception, unless the exception type is 228   will return @ref error::exception, unless the exception type is
229   @ref std::bad_alloc, which will be allowed to propagate. 229   @ref std::bad_alloc, which will be allowed to propagate.
230   230  
231   The `ctx` argument can be used either as a tag type to provide conversions 231   The `ctx` argument can be used either as a tag type to provide conversions
232   for third-party types, or to pass extra data to the conversion function. 232   for third-party types, or to pass extra data to the conversion function.
233   233  
234   @par Constraints 234   @par Constraints
235   @code 235   @code
236   ! std::is_reference< T >::value 236   ! std::is_reference< T >::value
237   @endcode 237   @endcode
238   238  
239   @par Exception Safety 239   @par Exception Safety
240   Strong guarantee. 240   Strong guarantee.
241   241  
242   @tparam T The type to convert to. 242   @tparam T The type to convert to.
243   @tparam Context The type of context passed to the conversion function. 243   @tparam Context The type of context passed to the conversion function.
244   244  
245   @param jv The @ref value to convert. 245   @param jv The @ref value to convert.
246   @param ctx Context passed to the conversion function. 246   @param ctx Context passed to the conversion function.
247   247  
248   @returns `jv` converted to `result<T>`. 248   @returns `jv` converted to `result<T>`.
249   249  
250   @see @ref value_to_tag, @ref value_to, @ref value_from, 250   @see @ref value_to_tag, @ref value_to, @ref value_from,
251   [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf). 251   [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
252   252  
253   @{ 253   @{
254   */ 254   */
255   template< class T, class Context > 255   template< class T, class Context >
256   typename result_for<T, value>::type 256   typename result_for<T, value>::type
HITCBC 257   3786 try_value_to( value const& jv, Context const& ctx ) 257   3786 try_value_to( value const& jv, Context const& ctx )
258   { 258   {
259   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value ); 259   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
260   using bare_T = detail::remove_cvref<T>; 260   using bare_T = detail::remove_cvref<T>;
261   using cat = detail::value_to_category<Context, bare_T>; 261   using cat = detail::value_to_category<Context, bare_T>;
HITCBC 262   3584 return detail::value_to_impl( 262   3584 return detail::value_to_impl(
HITCBC 263   3780 cat(), try_value_to_tag<bare_T>(), jv, ctx ); 263   3780 cat(), try_value_to_tag<bare_T>(), jv, ctx );
264   } 264   }
265   265  
266   /// Overload 266   /// Overload
267   template<class T> 267   template<class T>
268   typename result_for<T, value>::type 268   typename result_for<T, value>::type
HITCBC 269   136 try_value_to(const value& jv) 269   136 try_value_to(const value& jv)
270   { 270   {
HITCBC 271   173 return try_value_to<T>( jv, detail::no_context() ); 271   173 return try_value_to<T>( jv, detail::no_context() );
272   } 272   }
273   /// @} 273   /// @}
274   274  
275   /** Determine if a @ref value can be converted to `T`. 275   /** Determine if a @ref value can be converted to `T`.
276   276  
277   If @ref value can be converted to `T` via a 277   If @ref value can be converted to `T` via a
278   call to @ref value_to, the static data member `value` 278   call to @ref value_to, the static data member `value`
279   is defined as `true`. Otherwise, `value` is 279   is defined as `true`. Otherwise, `value` is
280   defined as `false`. 280   defined as `false`.
281   281  
282   @see @ref value_to 282   @see @ref value_to
283   */ 283   */
284   #ifdef BOOST_JSON_DOCS 284   #ifdef BOOST_JSON_DOCS
285   template<class T> 285   template<class T>
286   using has_value_to = __see_below__; 286   using has_value_to = __see_below__;
287   #else 287   #else
288   template<class T> 288   template<class T>
289   using has_value_to = detail::can_convert< 289   using has_value_to = detail::can_convert<
290   detail::remove_cvref<T>, detail::value_to_conversion>; 290   detail::remove_cvref<T>, detail::value_to_conversion>;
291   #endif 291   #endif
292   292  
293   } // namespace json 293   } // namespace json
294   } // namespace boost 294   } // namespace boost
295   295  
296   #endif 296   #endif