LCOV - code coverage report
Current view: top level - json/detail - value_from.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 48 48
Test Date: 2026-03-05 09:04:27 Functions: 98.5 % 617 608 9

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
       4                 : // Copyright (c) 2022 Dmitry Arkhipov (grisumbras@gmail.com)
       5                 : //
       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)
       8                 : //
       9                 : // Official repository: https://github.com/boostorg/json
      10                 : //
      11                 : 
      12                 : #ifndef BOOST_JSON_DETAIL_VALUE_FROM_HPP
      13                 : #define BOOST_JSON_DETAIL_VALUE_FROM_HPP
      14                 : 
      15                 : #include <boost/json/conversion.hpp>
      16                 : #include <boost/describe/enum_to_string.hpp>
      17                 : #include <boost/mp11/algorithm.hpp>
      18                 : 
      19                 : #ifndef BOOST_NO_CXX17_HDR_OPTIONAL
      20                 : # include <optional>
      21                 : #endif
      22                 : 
      23                 : namespace boost {
      24                 : namespace json {
      25                 : namespace detail {
      26                 : 
      27                 : template< class Ctx, class T >
      28                 : using value_from_attrs = conversion_attrs<
      29                 :     Ctx, remove_cvref<T>, value_from_conversion>;
      30                 : 
      31                 : template< class Ctx, class T >
      32                 : struct append_tuple_element {
      33                 :     array& arr;
      34                 :     Ctx const& ctx;
      35                 :     T&& t;
      36                 : 
      37                 :     template<std::size_t I>
      38                 :     void
      39 HIT         309 :     operator()(mp11::mp_size_t<I>) const
      40                 :     {
      41                 :         using std::get;
      42             618 :         arr.emplace_back(value_from(
      43             628 :             get<I>(std::forward<T>(t)), ctx, arr.storage() ));
      44             309 :     }
      45                 : };
      46                 : 
      47                 : template< class T, class Ctx >
      48                 : using to_representation_result = mp11::mp_if<
      49                 :     std::is_same<
      50                 :         remove_cvref<T>, typename value_from_attrs<Ctx, T>::representation >,
      51                 :     T&&,
      52                 :     typename value_from_attrs<Ctx, T>::representation>;
      53                 : 
      54                 : template< class Ctx, class T >
      55                 : to_representation_result< T, Ctx >
      56            7196 : to_representation( T&& t )
      57                 : {
      58                 :     using R = to_representation_result< T, Ctx >;
      59            7196 :     return static_cast<R>( static_cast<T&&>(t) );
      60                 : }
      61                 : 
      62                 : //----------------------------------------------------------
      63                 : // User-provided conversion
      64                 : 
      65                 : template< class T, class Ctx >
      66                 : void
      67              35 : value_from_impl( user_conversion_tag, value& jv, T&& from, Ctx const& )
      68                 : {
      69              35 :     tag_invoke( value_from_tag(), jv, static_cast<T&&>(from) );
      70              35 : }
      71                 : 
      72                 : template< class T, class Ctx >
      73                 : void
      74              26 : value_from_impl( context_conversion_tag, value& jv, T&& from, Ctx const& ctx)
      75                 : {
      76                 :     using Sup = supported_context<Ctx, T, value_from_conversion>;
      77              26 :     tag_invoke( value_from_tag(), jv, static_cast<T&&>(from), Sup::get(ctx) );
      78              26 : }
      79                 : 
      80                 : template< class T, class Ctx >
      81                 : void
      82               2 : value_from_impl(
      83                 :     full_context_conversion_tag, value& jv, T&& from, Ctx const& ctx)
      84                 : {
      85                 :     using Sup = supported_context<Ctx, T, value_from_conversion>;
      86               2 :     tag_invoke(
      87               2 :         value_from_tag(), jv, static_cast<T&&>(from), Sup::get(ctx), ctx );
      88               2 : }
      89                 : 
      90                 : //----------------------------------------------------------
      91                 : // Native conversion
      92                 : 
      93                 : template< class T, class Ctx >
      94                 : void
      95            6558 : value_from_impl( native_conversion_tag, value& jv, T&& from, Ctx const& )
      96                 : {
      97            6558 :     jv = std::forward<T>(from);
      98            6558 : }
      99                 : 
     100                 : // null-like types
     101                 : template< class T, class Ctx >
     102                 : void
     103              11 : value_from_impl( null_like_conversion_tag, value& jv, T&&, Ctx const& )
     104                 : {
     105                 :     // do nothing
     106              11 :     BOOST_ASSERT(jv.is_null());
     107                 :     (void)jv;
     108              11 : }
     109                 : 
     110                 : // string-like types
     111                 : template< class T, class Ctx >
     112                 : void
     113             135 : value_from_impl( string_like_conversion_tag, value& jv, T&& from, Ctx const& )
     114                 : {
     115             135 :     auto sv = static_cast<string_view>(from);
     116             135 :     jv.emplace_string().assign(sv);
     117             135 : }
     118                 : 
     119                 : // map-like types
     120                 : template< class T, class Ctx >
     121                 : void
     122              56 : value_from_impl( map_like_conversion_tag, value& jv, T&& from, Ctx const& ctx )
     123                 : {
     124                 :     using std::get;
     125              56 :     object& obj = jv.emplace_object();
     126              56 :     obj.reserve(detail::try_size(from, size_implementation<T>()));
     127             179 :     for (auto&& elem : from)
     128                 :     {
     129             381 :         obj.emplace(
     130             135 :             to_representation<Ctx>( get<0>(elem) ),
     131             123 :             value_from( get<1>(elem), ctx, obj.storage() ));
     132                 :     }
     133              56 : }
     134                 : 
     135                 : // ranges
     136                 : template< class T, class Ctx >
     137                 : void
     138             104 : value_from_impl( sequence_conversion_tag, value& jv, T&& from, Ctx const& ctx )
     139                 : {
     140             104 :     array& result = jv.emplace_array();
     141             104 :     result.reserve(detail::try_size(from, size_implementation<T>()));
     142                 :     using ForwardedValue = forwarded_value<T&&>;
     143            6376 :     for (auto&& elem : from)
     144            6488 :         result.emplace_back(
     145                 :             value_from(
     146                 :                 // not a static_cast in order to appease clang < 4.0
     147             216 :                 ForwardedValue(elem),
     148                 :                 ctx,
     149                 :                 result.storage() ));
     150             104 : }
     151                 : 
     152                 : // tuple-like types
     153                 : template< class T, class Ctx >
     154                 : void
     155             146 : value_from_impl( tuple_conversion_tag, value& jv, T&& from, Ctx const& ctx )
     156                 : {
     157             146 :     constexpr std::size_t n =
     158                 :         std::tuple_size<remove_cvref<T>>::value;
     159             146 :     array& arr = jv.emplace_array();
     160             146 :     arr.reserve(n);
     161             146 :     mp11::mp_for_each<mp11::mp_iota_c<n>>(
     162             146 :         append_tuple_element< Ctx, T >{ arr, ctx, std::forward<T>(from) });
     163             146 : }
     164                 : 
     165                 : // no suitable conversion implementation
     166                 : template< class T, class Ctx >
     167                 : void
     168                 : value_from_impl( no_conversion_tag, value&, T&&, Ctx const& )
     169                 : {
     170                 :     static_assert(
     171                 :         !std::is_same<T, T>::value,
     172                 :         "No suitable tag_invoke overload found for the type");
     173                 : }
     174                 : 
     175                 : template< class Ctx, class T >
     176                 : struct from_described_member
     177                 : {
     178                 :     using Ds = described_members< remove_cvref<T> >;
     179                 : 
     180                 :     object& obj;
     181                 :     Ctx const& ctx;
     182                 :     T&& from;
     183                 : 
     184                 :     template< class I >
     185                 :     void
     186                 :     operator()(I) const
     187                 :     {
     188                 :         using D = mp11::mp_at<Ds, I>;
     189                 :         obj.emplace(
     190                 :             D::name,
     191                 :             value_from(
     192                 :                 static_cast<T&&>(from).* D::pointer,
     193                 :                 ctx,
     194                 :                 obj.storage()));
     195                 :     }
     196                 : };
     197                 : 
     198                 : // described classes
     199                 : template< class T, class Ctx >
     200                 : void
     201                 : value_from_impl(
     202                 :     described_class_conversion_tag, value& jv, T&& from, Ctx const& ctx )
     203                 : {
     204                 :     object& obj = jv.emplace_object();
     205                 :     from_described_member<Ctx, T> member_converter{
     206                 :         obj, ctx, static_cast<T&&>(from)};
     207                 : 
     208                 :     using Ds = typename decltype(member_converter)::Ds;
     209                 :     constexpr std::size_t N = mp11::mp_size<Ds>::value;
     210                 :     obj.reserve(N);
     211                 :     mp11::mp_for_each< mp11::mp_iota_c<N> >(member_converter);
     212                 : }
     213                 : 
     214                 : // described enums
     215                 : template< class T, class Ctx >
     216                 : void
     217                 : value_from_impl(
     218                 :     described_enum_conversion_tag, value& jv, T from, Ctx const& )
     219                 : {
     220                 :     (void)jv;
     221                 :     (void)from;
     222                 : #ifdef BOOST_DESCRIBE_CXX14
     223                 :     char const* const name = describe::enum_to_string(from, nullptr);
     224                 :     if( name )
     225                 :     {
     226                 :         string& str = jv.emplace_string();
     227                 :         str.assign(name);
     228                 :     }
     229                 :     else
     230                 :     {
     231                 :         using Integer = typename std::underlying_type< remove_cvref<T> >::type;
     232                 :         jv = static_cast<Integer>(from);
     233                 :     }
     234                 : #endif
     235                 : }
     236                 : 
     237                 : // optionals
     238                 : template< class T, class Ctx >
     239                 : void
     240                 : value_from_impl(
     241                 :     optional_conversion_tag, value& jv, T&& from, Ctx const& ctx )
     242                 : {
     243                 :     if( from )
     244                 :         value_from( *from, ctx, jv );
     245                 :     else
     246                 :         jv = nullptr;
     247                 : }
     248                 : 
     249                 : // variants
     250                 : template< class Ctx >
     251                 : struct value_from_visitor
     252                 : {
     253                 :     value& jv;
     254                 :     Ctx const& ctx;
     255                 : 
     256                 :     template<class T>
     257                 :     void
     258                 :     operator()(T&& t)
     259                 :     {
     260                 :         value_from( static_cast<T&&>(t), ctx, jv );
     261                 :     }
     262                 : };
     263                 : 
     264                 : template< class Ctx, class T >
     265                 : void
     266                 : value_from_impl( variant_conversion_tag, value& jv, T&& from, Ctx const& ctx )
     267                 : {
     268                 :     visit( value_from_visitor<Ctx>{ jv, ctx }, static_cast<T&&>(from) );
     269                 : }
     270                 : 
     271                 : template< class Ctx, class T >
     272                 : void
     273                 : value_from_impl( path_conversion_tag, value& jv, T&& from, Ctx const& )
     274                 : {
     275                 :     std::string s = from.generic_string();
     276                 :     string_view sv = s;
     277                 :     jv.emplace_string().assign(sv);
     278                 : }
     279                 : 
     280                 : } // detail
     281                 : 
     282                 : #ifndef BOOST_NO_CXX17_HDR_OPTIONAL
     283                 : inline
     284                 : void
     285                 : tag_invoke(
     286                 :     value_from_tag,
     287                 :     value& jv,
     288                 :     std::nullopt_t)
     289                 : {
     290                 :     // do nothing
     291                 :     BOOST_ASSERT(jv.is_null());
     292                 :     (void)jv;
     293                 : }
     294                 : #endif
     295                 : 
     296                 : } // namespace json
     297                 : } // namespace boost
     298                 : 
     299                 : #endif
        

Generated by: LCOV version 2.3