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 % 48 48
Test Date: 2025-12-23 17:20:51 Functions: 98.5 % 617 608

            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          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.1