File indexing completed on 2025-01-18 09:39:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_JSON_DETAIL_VALUE_FROM_HPP
0013 #define BOOST_JSON_DETAIL_VALUE_FROM_HPP
0014
0015 #include <boost/json/conversion.hpp>
0016 #include <boost/describe/enum_to_string.hpp>
0017 #include <boost/mp11/algorithm.hpp>
0018
0019 #ifndef BOOST_NO_CXX17_HDR_OPTIONAL
0020 # include <optional>
0021 #endif
0022
0023 namespace boost {
0024 namespace json {
0025
0026 namespace detail {
0027
0028 template< class Ctx, class T >
0029 struct append_tuple_element {
0030 array& arr;
0031 Ctx const& ctx;
0032 T&& t;
0033
0034 template<std::size_t I>
0035 void
0036 operator()(mp11::mp_size_t<I>) const
0037 {
0038 using std::get;
0039 arr.emplace_back(value_from(
0040 get<I>(std::forward<T>(t)), ctx, arr.storage() ));
0041 }
0042 };
0043
0044
0045
0046
0047 template< class T, class Ctx >
0048 void
0049 value_from_impl( user_conversion_tag, value& jv, T&& from, Ctx const& )
0050 {
0051 tag_invoke( value_from_tag(), jv, static_cast<T&&>(from) );
0052 }
0053
0054 template< class T, class Ctx >
0055 void
0056 value_from_impl( context_conversion_tag, value& jv, T&& from, Ctx const& ctx)
0057 {
0058 using Sup = supported_context<Ctx, T, value_from_conversion>;
0059 tag_invoke( value_from_tag(), jv, static_cast<T&&>(from), Sup::get(ctx) );
0060 }
0061
0062 template< class T, class Ctx >
0063 void
0064 value_from_impl(
0065 full_context_conversion_tag, value& jv, T&& from, Ctx const& ctx)
0066 {
0067 using Sup = supported_context<Ctx, T, value_from_conversion>;
0068 tag_invoke(
0069 value_from_tag(), jv, static_cast<T&&>(from), Sup::get(ctx), ctx );
0070 }
0071
0072
0073
0074
0075 template< class T, class Ctx >
0076 void
0077 value_from_impl( native_conversion_tag, value& jv, T&& from, Ctx const& )
0078 {
0079 jv = std::forward<T>(from);
0080 }
0081
0082
0083 template< class T, class Ctx >
0084 void
0085 value_from_impl( null_like_conversion_tag, value& jv, T&&, Ctx const& )
0086 {
0087
0088 BOOST_ASSERT(jv.is_null());
0089 (void)jv;
0090 }
0091
0092
0093 template< class T, class Ctx >
0094 void
0095 value_from_impl( string_like_conversion_tag, value& jv, T&& from, Ctx const& )
0096 {
0097 auto sv = static_cast<string_view>(from);
0098 jv.emplace_string().assign(sv);
0099 }
0100
0101
0102 template< class T, class Ctx >
0103 void
0104 value_from_impl( map_like_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0105 {
0106 using std::get;
0107 object& obj = jv.emplace_object();
0108 obj.reserve(detail::try_size(from, size_implementation<T>()));
0109 for (auto&& elem : from)
0110 obj.emplace(
0111 get<0>(elem),
0112 value_from( get<1>(elem), ctx, obj.storage() ));
0113 }
0114
0115
0116 template< class T, class Ctx >
0117 void
0118 value_from_impl( sequence_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0119 {
0120 array& result = jv.emplace_array();
0121 result.reserve(detail::try_size(from, size_implementation<T>()));
0122 using ForwardedValue = forwarded_value<T&&>;
0123 for (auto&& elem : from)
0124 result.emplace_back(
0125 value_from(
0126
0127 ForwardedValue(elem),
0128 ctx,
0129 result.storage() ));
0130 }
0131
0132
0133 template< class T, class Ctx >
0134 void
0135 value_from_impl( tuple_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0136 {
0137 constexpr std::size_t n =
0138 std::tuple_size<remove_cvref<T>>::value;
0139 array& arr = jv.emplace_array();
0140 arr.reserve(n);
0141 mp11::mp_for_each<mp11::mp_iota_c<n>>(
0142 append_tuple_element< Ctx, T >{ arr, ctx, std::forward<T>(from) });
0143 }
0144
0145
0146 template< class T, class Ctx >
0147 void
0148 value_from_impl( no_conversion_tag, value&, T&&, Ctx const& )
0149 {
0150 static_assert(
0151 !std::is_same<T, T>::value,
0152 "No suitable tag_invoke overload found for the type");
0153 }
0154
0155 template< class Ctx, class T >
0156 struct from_described_member
0157 {
0158 using Ds = describe::describe_members<
0159 remove_cvref<T>, describe::mod_public | describe::mod_inherited>;
0160
0161 object& obj;
0162 Ctx const& ctx;
0163 T&& from;
0164
0165 template< class I >
0166 void
0167 operator()(I) const
0168 {
0169 using D = mp11::mp_at<Ds, I>;
0170 obj.emplace(
0171 D::name,
0172 value_from(
0173 static_cast<T&&>(from).* D::pointer,
0174 ctx,
0175 obj.storage()));
0176 }
0177 };
0178
0179
0180 template< class T, class Ctx >
0181 void
0182 value_from_impl(
0183 described_class_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0184 {
0185 object& obj = jv.emplace_object();
0186 from_described_member<Ctx, T> member_converter{
0187 obj, ctx, static_cast<T&&>(from)};
0188
0189 using Ds = typename decltype(member_converter)::Ds;
0190 constexpr std::size_t N = mp11::mp_size<Ds>::value;
0191 obj.reserve(N);
0192 mp11::mp_for_each< mp11::mp_iota_c<N> >(member_converter);
0193 }
0194
0195
0196 template< class T, class Ctx >
0197 void
0198 value_from_impl(
0199 described_enum_conversion_tag, value& jv, T from, Ctx const& )
0200 {
0201 (void)jv;
0202 (void)from;
0203 #ifdef BOOST_DESCRIBE_CXX14
0204 char const* const name = describe::enum_to_string(from, nullptr);
0205 if( name )
0206 {
0207 string& str = jv.emplace_string();
0208 str.assign(name);
0209 }
0210 else
0211 {
0212 using Integer = typename std::underlying_type< remove_cvref<T> >::type;
0213 jv = static_cast<Integer>(from);
0214 }
0215 #endif
0216 }
0217
0218
0219 template< class T, class Ctx >
0220 void
0221 value_from_impl(
0222 optional_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0223 {
0224 if( from )
0225 value_from( *from, ctx, jv );
0226 else
0227 jv = nullptr;
0228 }
0229
0230
0231 template< class Ctx >
0232 struct value_from_visitor
0233 {
0234 value& jv;
0235 Ctx const& ctx;
0236
0237 template<class T>
0238 void
0239 operator()(T&& t)
0240 {
0241 value_from( static_cast<T&&>(t), ctx, jv );
0242 }
0243 };
0244
0245 template< class Ctx, class T >
0246 void
0247 value_from_impl( variant_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0248 {
0249 visit( value_from_visitor<Ctx>{ jv, ctx }, static_cast<T&&>(from) );
0250 }
0251
0252
0253
0254
0255 template< class Ctx, class T >
0256 using value_from_category = conversion_category<
0257 Ctx, T, value_from_conversion >;
0258
0259 }
0260
0261 #ifndef BOOST_NO_CXX17_HDR_OPTIONAL
0262 inline
0263 void
0264 tag_invoke(
0265 value_from_tag,
0266 value& jv,
0267 std::nullopt_t)
0268 {
0269
0270 BOOST_ASSERT(jv.is_null());
0271 (void)jv;
0272 }
0273 #endif
0274
0275 }
0276 }
0277
0278 #endif