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 23 + This function attempts to convert a @ref value to `T` using
24 - to `T` using  
25   24  
26 - @li one of @ref value's accessors, or 25 + - one of @ref value's accessors, or
27 - @li a library-provided generic conversion, or 26 + - a library-provided generic conversion, or
28 - @li a user-provided overload of `tag_invoke`. 27 + - a user-provided overload of `tag_invoke`.
29   28  
30 - Out of the box the function supports default constructible types satisfying 29 + In order to perform the conversion the function selects an appropriate
31 - {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`, 30 + implementation based on the types `T` and `Context` (if provided).
32 - `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs  
33 - and enums described using Boost.Describe.  
34   31  
35 - Conversion of other types is done by calling an overload of `tag_invoke` 32 + 1. If `Context` is available and is not `std::tuple<C...>`
36 - found by argument-dependent lookup. Its signature should be similar to: 33 +
  34 + a. check if `use_category<T, Context>::value` is not
  35 + @ref conversion_category::unknown; otherwise
  36 +
  37 + b. check if a `tag_invoke` overload from the list below that takes a
  38 + `Context const&` exists.
  39 +
  40 + 2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat
  41 + steps **1** and **2** recursively for every `C` until either
  42 + step **1.a** or **1.b** succeeds for some `C`.
  43 +
  44 + 3. Failing that,
  45 +
  46 + a. check if `use_category<T>::value` is not
  47 + @ref conversion_category::unknown; otherwise
  48 +
  49 + b. check if a `tag_invoke` overload from the list below that takes only
  50 + 2 parameters exists; otherwise
  51 +
  52 + c. check if `T` is one of @ref value, @ref array, @ref object,
  53 + or @ref string; otherwise
  54 +
  55 + d. check if `T` matches one of the categories of types described in the
  56 + table "Conversion categories" in \<\<Value Conversion>> section.
  57 +
  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
  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.
  62 + If the category is selected on steps **2.b** or **3.b**, then a
  63 + user-provided `tag_invoke` overload is used.
  64 +
  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
  67 + higher priority.
37   68  
38   @code 69   @code
39   template< class FullContext > 70   template< class FullContext >
40 - T tag_invoke( 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& );
41 - @endcode  
42   72  
43 - or 73 + template< class FullContext >
  74 + T tag_invoke( value_to_tag<T>, const value&, const Context&, const FullContext& );
  75 +
  76 + result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& );
44 - @code  
45   77  
46 - @endcode  
47   T tag_invoke( value_to_tag<T>, const value&, const Context& ); 78   T tag_invoke( value_to_tag<T>, const value&, const Context& );
48   79  
49 - or 80 + result<T> tag_invoke( try_value_to_tag<T>, const value& );
50   81  
51 - @code 82 + T tag_invoke( value_to_tag<T>, const value& );
52 - result<T> tag_invoke( value_to_tag<T>, const value& );  
53   @endcode 83   @endcode
54   84  
55 - The overloads are checked for existence in that order and the first that 85 + For `tag_invoke` overloads that take a parameter of type `value_to_tag<T>`
56 - matches will be selected. 86 + the object returned by a call to that overload is returned by the function
57 - 87 + as the result of the conversion. For overloads that take a parameter of
58 - The object returned by the function call is returned by @ref value_to as 88 + type `try_value_to_tag<T>` if the returned `result` contains a value, that
59 - the result of the conversion. 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.
60   91  
61   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
62   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.
63   94  
64   Overload **(3)** is **deleted** and participates in overload resolution 95   Overload **(3)** is **deleted** and participates in overload resolution
65   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
66   creation of temporary @ref value instances, e.g. 97   creation of temporary @ref value instances, e.g.
67   98  
68   @code 99   @code
69   auto flag = value_to<bool>(true); 100   auto flag = value_to<bool>(true);
70   @endcode 101   @endcode
71   102  
72   @par Constraints 103   @par Constraints
73   @code 104   @code
74   ! std::is_reference< T >::value 105   ! std::is_reference< T >::value
75   @endcode 106   @endcode
76   107  
77   @par Exception Safety 108   @par Exception Safety
78   Strong guarantee. 109   Strong guarantee.
79   110  
80   @tparam T The type to convert to. 111   @tparam T The type to convert to.
81   112  
82   @tparam Context The type of context passed to the conversion function. 113   @tparam Context The type of context passed to the conversion function.
83   114  
84 - @returns `jv` converted to `result<T>`. 115 + @returns `jv` converted to `T`.
85   116  
86   @param jv The @ref value to convert. 117   @param jv The @ref value to convert.
87   118  
88   @param ctx Context passed to the conversion function. 119   @param ctx Context passed to the conversion function.
89   120  
90 - @see @ref value_to_tag, @ref value_from, 121 + @see @ref try_value_to, @ref value_from,
91   <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">
92   tag_invoke: A general pattern for supporting customisable functions</a> 123   tag_invoke: A general pattern for supporting customisable functions</a>
93   124  
94   @{ 125   @{
95   */ 126   */
96   template< class T, class Context > 127   template< class T, class Context >
97   T 128   T
HITCBC 98   410 value_to( value const& jv, Context const& ctx ) 129   410 value_to( value const& jv, Context const& ctx )
99   { 130   {
100   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value ); 131   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
101 - BOOST_CORE_STATIC_ASSERT((  
102 - detail::conversion_round_trips<  
103 - Context, bare_T, detail::value_to_conversion>::value));  
104   using bare_T = detail::remove_cvref<T>; 132   using bare_T = detail::remove_cvref<T>;
105   using cat = detail::value_to_category<Context, bare_T>; 133   using cat = detail::value_to_category<Context, bare_T>;
HITCBC 106   410 return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx ); 134   410 return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx );
107   } 135   }
108   136  
109   /// Overload 137   /// Overload
110   template<class T> 138   template<class T>
111   T 139   T
HITCBC 112   131 value_to(const value& jv) 140   131 value_to(const value& jv)
113   { 141   {
HITCBC 114   192 return value_to<T>( jv, detail::no_context() ); 142   192 return value_to<T>( jv, detail::no_context() );
115   } 143   }
116   144  
117   /// Overload 145   /// Overload
118   template<class T, class U 146   template<class T, class U
119   #ifndef BOOST_JSON_DOCS 147   #ifndef BOOST_JSON_DOCS
120   , 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
121   #endif 149   #endif
122   > 150   >
123   T 151   T
124   value_to(U const& jv) = delete; 152   value_to(U const& jv) = delete;
125   /// @} 153   /// @}
126   154  
127   /** Convert a @ref value to a @ref boost::system::result. 155   /** Convert a @ref value to a @ref boost::system::result.
128   156  
129   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
130   158  
131 - @li one of @ref value's accessors, or 159 + - one of @ref value's accessors, or
132 - @li a library-provided generic conversion, or 160 + - a library-provided generic conversion, or
133 - @li a user-provided overload of `tag_invoke`. 161 + - a user-provided overload of `tag_invoke`.
134   162  
135 - Out of the box the function supports default constructible types satisfying 163 + In order to perform the conversion the function selects an appropriate
136 - {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`, 164 + implementation based on the types `T` and `Context` (if provided).
137 - `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs  
138 - and enums described using Boost.Describe.  
139   165  
140 - Conversion of other types is done by calling an overload of `tag_invoke` 166 + 1. If `Context` is available and is not `std::tuple<C...>`
141 - found by argument-dependent lookup. Its signature should be similar to: 167 +
  168 + a. check if `use_category<T, Context>::value` is not
  169 + @ref conversion_category::unknown; otherwise
  170 +
  171 + b. check if a `tag_invoke` overload from the list below that takes a
  172 + `Context const&` exists.
  173 +
  174 + 2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat
  175 + steps **1** and **2** recursively for every `C` until either
  176 + step **1.a** or **1.b** succeeds for some `C`.
  177 +
  178 + 3. Failing that,
  179 +
  180 + a. check if `use_category<T>::value` is not
  181 + @ref conversion_category::unknown; otherwise
  182 +
  183 + b. check if a `tag_invoke` overload from the list below that takes only
  184 + 2 parameters exists; otherwise
  185 +
  186 + c. check if `T` is one of @ref value, @ref array, @ref object,
  187 + or @ref string; otherwise
  188 +
  189 + d. check if `T` matches one of the categories of types described in the
  190 + table "Conversion categories" in \<\<Value Conversion>> section.
  191 +
  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
  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.
  196 + If the category is selected on steps **2.b** or **3.b**, then a
  197 + user-provided `tag_invoke` overload is used.
  198 +
  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
  201 + higher priority.
142   202  
143   @code 203   @code
144   template< class FullContext > 204   template< class FullContext >
145 - 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& );
146 - @endcode  
147   206  
148 - or 207 + template< class FullContext >
  208 + T tag_invoke( value_to_tag<T>, const value&, const Context&, const FullContext& );
149 - @code  
150   209  
151 - @endcode  
152   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& );
153   211  
154 - or 212 + T tag_invoke( value_to_tag<T>, const value&, const Context& );
155 - @code  
156   213  
157   result<T> tag_invoke( try_value_to_tag<T>, const value& ); 214   result<T> tag_invoke( try_value_to_tag<T>, const value& );
  215 +
  216 + T tag_invoke( value_to_tag<T>, const value& );
158   @endcode 217   @endcode
159   218  
160 - The overloads are checked for existence in that order and the first that 219 + For `tag_invoke` overloads that take a parameter of type
161 - matches will be selected. 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
  222 + that take a parameter of type `value_to_tag<T>` the returned object is
  223 + wrapped with a `result<T>`.
162   224  
163   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
164   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
165   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
166 - will return `error::exception`, unless the exception type is 228 + will return @ref error::exception, unless the exception type is
167   @ref std::bad_alloc, which will be allowed to propagate. 229   @ref std::bad_alloc, which will be allowed to propagate.
168   230  
169   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
170   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.
171   233  
172   @par Constraints 234   @par Constraints
173   @code 235   @code
174   ! std::is_reference< T >::value 236   ! std::is_reference< T >::value
175   @endcode 237   @endcode
176   238  
177   @par Exception Safety 239   @par Exception Safety
178   Strong guarantee. 240   Strong guarantee.
179   241  
180   @tparam T The type to convert to. 242   @tparam T The type to convert to.
181   @tparam Context The type of context passed to the conversion function. 243   @tparam Context The type of context passed to the conversion function.
182   244  
183   @param jv The @ref value to convert. 245   @param jv The @ref value to convert.
184   @param ctx Context passed to the conversion function. 246   @param ctx Context passed to the conversion function.
185   247  
186   @returns `jv` converted to `result<T>`. 248   @returns `jv` converted to `result<T>`.
187   249  
188   @see @ref value_to_tag, @ref value_to, @ref value_from, 250   @see @ref value_to_tag, @ref value_to, @ref value_from,
189   [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).
190   252  
191   @{ 253   @{
192   */ 254   */
193   template< class T, class Context > 255   template< class T, class Context >
194   typename result_for<T, value>::type 256   typename result_for<T, value>::type
HITCBC 195   3763 try_value_to( value const& jv, Context const& ctx ) 257   3763 try_value_to( value const& jv, Context const& ctx )
196   { 258   {
197   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value ); 259   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
198 - BOOST_CORE_STATIC_ASSERT((  
199 - detail::conversion_round_trips<  
200 - Context, bare_T, detail::value_to_conversion>::value));  
201   using bare_T = detail::remove_cvref<T>; 260   using bare_T = detail::remove_cvref<T>;
202   using cat = detail::value_to_category<Context, bare_T>; 261   using cat = detail::value_to_category<Context, bare_T>;
HITCBC 203   3573 return detail::value_to_impl( 262   3573 return detail::value_to_impl(
HITCBC 204   3757 cat(), try_value_to_tag<bare_T>(), jv, ctx ); 263   3757 cat(), try_value_to_tag<bare_T>(), jv, ctx );
205   } 264   }
206   265  
207   /// Overload 266   /// Overload
208   template<class T> 267   template<class T>
209   typename result_for<T, value>::type 268   typename result_for<T, value>::type
HITCBC 210   130 try_value_to(const value& jv) 269   130 try_value_to(const value& jv)
211   { 270   {
HITCBC 212   163 return try_value_to<T>( jv, detail::no_context() ); 271   163 return try_value_to<T>( jv, detail::no_context() );
213   } 272   }
214   /// @} 273   /// @}
215   274  
216   /** Determine if a @ref value can be converted to `T`. 275   /** Determine if a @ref value can be converted to `T`.
217   276  
218   If @ref value can be converted to `T` via a 277   If @ref value can be converted to `T` via a
219   call to @ref value_to, the static data member `value` 278   call to @ref value_to, the static data member `value`
220   is defined as `true`. Otherwise, `value` is 279   is defined as `true`. Otherwise, `value` is
221   defined as `false`. 280   defined as `false`.
222   281  
223   @see @ref value_to 282   @see @ref value_to
224   */ 283   */
225   #ifdef BOOST_JSON_DOCS 284   #ifdef BOOST_JSON_DOCS
226   template<class T> 285   template<class T>
227   using has_value_to = __see_below__; 286   using has_value_to = __see_below__;
228   #else 287   #else
229   template<class T> 288   template<class T>
230   using has_value_to = detail::can_convert< 289   using has_value_to = detail::can_convert<
231   detail::remove_cvref<T>, detail::value_to_conversion>; 290   detail::remove_cvref<T>, detail::value_to_conversion>;
232   #endif 291   #endif
233   292  
234   } // namespace json 293   } // namespace json
235   } // namespace boost 294   } // namespace boost
236   295  
237   #endif 296   #endif