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 % 46 46
Test Date: 2026-04-28 15:33:47 Functions: 98.1 % 315 309 6

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

Generated by: LCOV version 2.3