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
24   to `T` using 24   to `T` using
25   25  
26   @li one of @ref value's accessors, or 26   @li one of @ref value's accessors, or
27   @li a library-provided generic conversion, or 27   @li a library-provided generic conversion, or
28   @li a user-provided overload of `tag_invoke`. 28   @li a user-provided overload of `tag_invoke`.
29   29  
30   Out of the box the function supports default constructible types satisfying 30   Out of the box the function supports default constructible types satisfying
31   {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`, 31   {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
32   `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs 32   `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
33   and enums described using Boost.Describe. 33   and enums described using Boost.Describe.
34   34  
35   Conversion of other types is done by calling an overload of `tag_invoke` 35   Conversion of other types is done by calling an overload of `tag_invoke`
36   found by argument-dependent lookup. Its signature should be similar to: 36   found by argument-dependent lookup. Its signature should be similar to:
37   37  
38   @code 38   @code
39   template< class FullContext > 39   template< class FullContext >
40   T tag_invoke( value_to_tag<T>, const value&, const Context& , const FullContext& ); 40   T tag_invoke( value_to_tag<T>, const value&, const Context& , const FullContext& );
41   @endcode 41   @endcode
42   42  
43   or 43   or
44   44  
45   @code 45   @code
46   T tag_invoke( value_to_tag<T>, const value&, const Context& ); 46   T tag_invoke( value_to_tag<T>, const value&, const Context& );
47   @endcode 47   @endcode
48   48  
49   or 49   or
50   50  
51   @code 51   @code
52   result<T> tag_invoke( value_to_tag<T>, const value& ); 52   result<T> tag_invoke( value_to_tag<T>, const value& );
53   @endcode 53   @endcode
54   54  
55   The overloads are checked for existence in that order and the first that 55   The overloads are checked for existence in that order and the first that
56   matches will be selected. 56   matches will be selected.
57   57  
58   The object returned by the function call is returned by @ref value_to as 58   The object returned by the function call is returned by @ref value_to as
59   the result of the conversion. 59   the result of the conversion.
60   60  
61   The `ctx` argument can be used either as a tag type to provide conversions 61   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. 62   for third-party types, or to pass extra data to the conversion function.
63   63  
64   Overload **(3)** is **deleted** and participates in overload resolution 64   Overload **(3)** is **deleted** and participates in overload resolution
65   only when `U` is not @ref value. The overload exists to prevent unintented 65   only when `U` is not @ref value. The overload exists to prevent unintented
66   creation of temporary @ref value instances, e.g. 66   creation of temporary @ref value instances, e.g.
67   67  
68   @code 68   @code
69   auto flag = value_to<bool>(true); 69   auto flag = value_to<bool>(true);
70   @endcode 70   @endcode
71   71  
72   @par Constraints 72   @par Constraints
73   @code 73   @code
74   ! std::is_reference< T >::value 74   ! std::is_reference< T >::value
75   @endcode 75   @endcode
76   76  
77   @par Exception Safety 77   @par Exception Safety
78   Strong guarantee. 78   Strong guarantee.
79   79  
80   @tparam T The type to convert to. 80   @tparam T The type to convert to.
81   81  
82   @tparam Context The type of context passed to the conversion function. 82   @tparam Context The type of context passed to the conversion function.
83   83  
84   @returns `jv` converted to `result<T>`. 84   @returns `jv` converted to `result<T>`.
85   85  
86   @param jv The @ref value to convert. 86   @param jv The @ref value to convert.
87   87  
88   @param ctx Context passed to the conversion function. 88   @param ctx Context passed to the conversion function.
89   89  
90   @see @ref value_to_tag, @ref value_from, 90   @see @ref value_to_tag, @ref value_from,
91   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf"> 91   <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> 92   tag_invoke: A general pattern for supporting customisable functions</a>
93   93  
94   @{ 94   @{
95   */ 95   */
96   template< class T, class Context > 96   template< class T, class Context >
97   T 97   T
HITCBC 98   410 value_to( value const& jv, Context const& ctx ) 98   410 value_to( value const& jv, Context const& ctx )
99   { 99   {
100   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value ); 100   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
101   using bare_T = detail::remove_cvref<T>; 101   using bare_T = detail::remove_cvref<T>;
102   BOOST_CORE_STATIC_ASSERT(( 102   BOOST_CORE_STATIC_ASSERT((
103   detail::conversion_round_trips< 103   detail::conversion_round_trips<
104   Context, bare_T, detail::value_to_conversion>::value)); 104   Context, bare_T, detail::value_to_conversion>::value));
105   using cat = detail::value_to_category<Context, bare_T>; 105   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 ); 106   410 return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx );
107   } 107   }
108   108  
109   /// Overload 109   /// Overload
110   template<class T> 110   template<class T>
111   T 111   T
HITCBC 112   131 value_to(const value& jv) 112   131 value_to(const value& jv)
113   { 113   {
HITCBC 114   192 return value_to<T>( jv, detail::no_context() ); 114   192 return value_to<T>( jv, detail::no_context() );
115   } 115   }
116   116  
117   /// Overload 117   /// Overload
118   template<class T, class U 118   template<class T, class U
119   #ifndef BOOST_JSON_DOCS 119   #ifndef BOOST_JSON_DOCS
120   , class = typename std::enable_if<!std::is_same<U, value>::value>::type 120   , class = typename std::enable_if<!std::is_same<U, value>::value>::type
121   #endif 121   #endif
122   > 122   >
123   T 123   T
124   value_to(U const& jv) = delete; 124   value_to(U const& jv) = delete;
125   /// @} 125   /// @}
126   126  
127   /** Convert a @ref value to a @ref boost::system::result. 127   /** Convert a @ref value to a @ref boost::system::result.
128   128  
129   This function attempts to convert a @ref value to `result<T>` using 129   This function attempts to convert a @ref value to `result<T>` using
130   130  
131   @li one of @ref value's accessors, or 131   @li one of @ref value's accessors, or
132   @li a library-provided generic conversion, or 132   @li a library-provided generic conversion, or
133   @li a user-provided overload of `tag_invoke`. 133   @li a user-provided overload of `tag_invoke`.
134   134  
135   Out of the box the function supports default constructible types satisfying 135   Out of the box the function supports default constructible types satisfying
136   {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`, 136   {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
137   `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs 137   `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
138   and enums described using Boost.Describe. 138   and enums described using Boost.Describe.
139   139  
140   Conversion of other types is done by calling an overload of `tag_invoke` 140   Conversion of other types is done by calling an overload of `tag_invoke`
141   found by argument-dependent lookup. Its signature should be similar to: 141   found by argument-dependent lookup. Its signature should be similar to:
142   142  
143   @code 143   @code
144   template< class FullContext > 144   template< class FullContext >
145   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& , const FullContext& ); 145   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& , const FullContext& );
146   @endcode 146   @endcode
147   147  
148   or 148   or
149   149  
150   @code 150   @code
151   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& ); 151   result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& );
152   @endcode 152   @endcode
153   153  
154   or 154   or
155   155  
156   @code 156   @code
157   result<T> tag_invoke( try_value_to_tag<T>, const value& ); 157   result<T> tag_invoke( try_value_to_tag<T>, const value& );
158   @endcode 158   @endcode
159   159  
160   The overloads are checked for existence in that order and the first that 160   The overloads are checked for existence in that order and the first that
161   matches will be selected. 161   matches will be selected.
162   162  
163   If an error occurs during conversion, the result will store the error code 163   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 164   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 165   attempt to retrieve the associated error code and return it, otherwise it
166   will return `error::exception`, unless the exception type is 166   will return `error::exception`, unless the exception type is
167   @ref std::bad_alloc, which will be allowed to propagate. 167   @ref std::bad_alloc, which will be allowed to propagate.
168   168  
169   The `ctx` argument can be used either as a tag type to provide conversions 169   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. 170   for third-party types, or to pass extra data to the conversion function.
171   171  
172   @par Constraints 172   @par Constraints
173   @code 173   @code
174   ! std::is_reference< T >::value 174   ! std::is_reference< T >::value
175   @endcode 175   @endcode
176   176  
177   @par Exception Safety 177   @par Exception Safety
178   Strong guarantee. 178   Strong guarantee.
179   179  
180   @tparam T The type to convert to. 180   @tparam T The type to convert to.
181   @tparam Context The type of context passed to the conversion function. 181   @tparam Context The type of context passed to the conversion function.
182   182  
183   @param jv The @ref value to convert. 183   @param jv The @ref value to convert.
184   @param ctx Context passed to the conversion function. 184   @param ctx Context passed to the conversion function.
185   185  
186   @returns `jv` converted to `result<T>`. 186   @returns `jv` converted to `result<T>`.
187   187  
188   @see @ref value_to_tag, @ref value_to, @ref value_from, 188   @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). 189   [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
190   190  
191   @{ 191   @{
192   */ 192   */
193   template< class T, class Context > 193   template< class T, class Context >
194   typename result_for<T, value>::type 194   typename result_for<T, value>::type
HITCBC 195   3763 try_value_to( value const& jv, Context const& ctx ) 195   3763 try_value_to( value const& jv, Context const& ctx )
196   { 196   {
197   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value ); 197   BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
198   using bare_T = detail::remove_cvref<T>; 198   using bare_T = detail::remove_cvref<T>;
199   BOOST_CORE_STATIC_ASSERT(( 199   BOOST_CORE_STATIC_ASSERT((
200   detail::conversion_round_trips< 200   detail::conversion_round_trips<
201   Context, bare_T, detail::value_to_conversion>::value)); 201   Context, bare_T, detail::value_to_conversion>::value));
202   using cat = detail::value_to_category<Context, bare_T>; 202   using cat = detail::value_to_category<Context, bare_T>;
HITCBC 203   3573 return detail::value_to_impl( 203   3573 return detail::value_to_impl(
HITCBC 204   3757 cat(), try_value_to_tag<bare_T>(), jv, ctx ); 204   3757 cat(), try_value_to_tag<bare_T>(), jv, ctx );
205   } 205   }
206   206  
207   /// Overload 207   /// Overload
208   template<class T> 208   template<class T>
209   typename result_for<T, value>::type 209   typename result_for<T, value>::type
HITCBC 210   130 try_value_to(const value& jv) 210   130 try_value_to(const value& jv)
211   { 211   {
HITCBC 212   163 return try_value_to<T>( jv, detail::no_context() ); 212   163 return try_value_to<T>( jv, detail::no_context() );
213   } 213   }
214   /// @} 214   /// @}
215   215  
216   /** Determine if a @ref value can be converted to `T`. 216   /** Determine if a @ref value can be converted to `T`.
217   217  
218   If @ref value can be converted to `T` via a 218   If @ref value can be converted to `T` via a
219   call to @ref value_to, the static data member `value` 219   call to @ref value_to, the static data member `value`
220   is defined as `true`. Otherwise, `value` is 220   is defined as `true`. Otherwise, `value` is
221   defined as `false`. 221   defined as `false`.
222   222  
223   @see @ref value_to 223   @see @ref value_to
224   */ 224   */
225   #ifdef BOOST_JSON_DOCS 225   #ifdef BOOST_JSON_DOCS
226   template<class T> 226   template<class T>
227   using has_value_to = __see_below__; 227   using has_value_to = __see_below__;
228   #else 228   #else
229   template<class T> 229   template<class T>
230   using has_value_to = detail::can_convert< 230   using has_value_to = detail::can_convert<
231   detail::remove_cvref<T>, detail::value_to_conversion>; 231   detail::remove_cvref<T>, detail::value_to_conversion>;
232   #endif 232   #endif
233   233  
234   } // namespace json 234   } // namespace json
235   } // namespace boost 235   } // namespace boost
236   236  
237   #endif 237   #endif