File indexing completed on 2025-07-09 08:14:09
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 = described_members< remove_cvref<T> >;
0159
0160 object& obj;
0161 Ctx const& ctx;
0162 T&& from;
0163
0164 template< class I >
0165 void
0166 operator()(I) const
0167 {
0168 using D = mp11::mp_at<Ds, I>;
0169 obj.emplace(
0170 D::name,
0171 value_from(
0172 static_cast<T&&>(from).* D::pointer,
0173 ctx,
0174 obj.storage()));
0175 }
0176 };
0177
0178
0179 template< class T, class Ctx >
0180 void
0181 value_from_impl(
0182 described_class_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0183 {
0184 object& obj = jv.emplace_object();
0185 from_described_member<Ctx, T> member_converter{
0186 obj, ctx, static_cast<T&&>(from)};
0187
0188 using Ds = typename decltype(member_converter)::Ds;
0189 constexpr std::size_t N = mp11::mp_size<Ds>::value;
0190 obj.reserve(N);
0191 mp11::mp_for_each< mp11::mp_iota_c<N> >(member_converter);
0192 }
0193
0194
0195 template< class T, class Ctx >
0196 void
0197 value_from_impl(
0198 described_enum_conversion_tag, value& jv, T from, Ctx const& )
0199 {
0200 (void)jv;
0201 (void)from;
0202 #ifdef BOOST_DESCRIBE_CXX14
0203 char const* const name = describe::enum_to_string(from, nullptr);
0204 if( name )
0205 {
0206 string& str = jv.emplace_string();
0207 str.assign(name);
0208 }
0209 else
0210 {
0211 using Integer = typename std::underlying_type< remove_cvref<T> >::type;
0212 jv = static_cast<Integer>(from);
0213 }
0214 #endif
0215 }
0216
0217
0218 template< class T, class Ctx >
0219 void
0220 value_from_impl(
0221 optional_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0222 {
0223 if( from )
0224 value_from( *from, ctx, jv );
0225 else
0226 jv = nullptr;
0227 }
0228
0229
0230 template< class Ctx >
0231 struct value_from_visitor
0232 {
0233 value& jv;
0234 Ctx const& ctx;
0235
0236 template<class T>
0237 void
0238 operator()(T&& t)
0239 {
0240 value_from( static_cast<T&&>(t), ctx, jv );
0241 }
0242 };
0243
0244 template< class Ctx, class T >
0245 void
0246 value_from_impl( variant_conversion_tag, value& jv, T&& from, Ctx const& ctx )
0247 {
0248 visit( value_from_visitor<Ctx>{ jv, ctx }, static_cast<T&&>(from) );
0249 }
0250
0251 template< class Ctx, class T >
0252 void
0253 value_from_impl( path_conversion_tag, value& jv, T&& from, Ctx const& )
0254 {
0255 std::string s = from.generic_string();
0256 string_view sv = s;
0257 jv.emplace_string().assign(sv);
0258 }
0259
0260
0261
0262
0263 template< class Ctx, class T >
0264 using value_from_category = conversion_category<
0265 Ctx, T, value_from_conversion >;
0266
0267 }
0268
0269 #ifndef BOOST_NO_CXX17_HDR_OPTIONAL
0270 inline
0271 void
0272 tag_invoke(
0273 value_from_tag,
0274 value& jv,
0275 std::nullopt_t)
0276 {
0277
0278 BOOST_ASSERT(jv.is_null());
0279 (void)jv;
0280 }
0281 #endif
0282
0283 }
0284 }
0285
0286 #endif