LCOV - code coverage report
Current view: top level - json/detail - value_from.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 46 46
Test Date: 2025-12-23 17:21:58 Functions: 97.7 % 309 302

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

Generated by: LCOV version 2.1