GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/value_from.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 48 48 100.0%
Functions: 608 617 98.5%
Branches: 22 23 95.7%

Line Branch Exec Source
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 618 operator()(mp11::mp_size_t<I>) const
40 {
41 using std::get;
42
2/2
✓ Branch 2 taken 303 times.
✓ Branch 5 taken 299 times.
1236 arr.emplace_back(value_from(
43
1/1
✓ Branch 4 taken 4 times.
1256 get<I>(std::forward<T>(t)), ctx, arr.storage() ));
44 618 }
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 14392 to_representation( T&& t )
57 {
58 using R = to_representation_result< T, Ctx >;
59 14392 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 65 value_from_impl( user_conversion_tag, value& jv, T&& from, Ctx const& )
68 {
69
1/1
✓ Branch 1 taken 24 times.
65 tag_invoke( value_from_tag(), jv, static_cast<T&&>(from) );
70 65 }
71
72 template< class T, class Ctx >
73 void
74 51 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
1/1
✓ Branch 2 taken 1 times.
51 tag_invoke( value_from_tag(), jv, static_cast<T&&>(from), Sup::get(ctx) );
78 51 }
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 13116 value_from_impl( native_conversion_tag, value& jv, T&& from, Ctx const& )
96 {
97 13116 jv = std::forward<T>(from);
98 13116 }
99
100 // null-like types
101 template< class T, class Ctx >
102 void
103 22 value_from_impl( null_like_conversion_tag, value& jv, T&&, Ctx const& )
104 {
105 // do nothing
106
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
22 BOOST_ASSERT(jv.is_null());
107 (void)jv;
108 22 }
109
110 // string-like types
111 template< class T, class Ctx >
112 void
113 270 value_from_impl( string_like_conversion_tag, value& jv, T&& from, Ctx const& )
114 {
115 270 auto sv = static_cast<string_view>(from);
116
1/1
✓ Branch 2 taken 135 times.
270 jv.emplace_string().assign(sv);
117 270 }
118
119 // map-like types
120 template< class T, class Ctx >
121 void
122 112 value_from_impl( map_like_conversion_tag, value& jv, T&& from, Ctx const& ctx )
123 {
124 using std::get;
125 112 object& obj = jv.emplace_object();
126 112 obj.reserve(detail::try_size(from, size_implementation<T>()));
127
2/2
✓ Branch 4 taken 123 times.
✓ Branch 5 taken 56 times.
358 for (auto&& elem : from)
128 {
129
3/3
✓ Branch 3 taken 123 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 67 times.
762 obj.emplace(
130 270 to_representation<Ctx>( get<0>(elem) ),
131 246 value_from( get<1>(elem), ctx, obj.storage() ));
132 }
133 112 }
134
135 // ranges
136 template< class T, class Ctx >
137 void
138 208 value_from_impl( sequence_conversion_tag, value& jv, T&& from, Ctx const& ctx )
139 {
140 208 array& result = jv.emplace_array();
141 208 result.reserve(detail::try_size(from, size_implementation<T>()));
142 using ForwardedValue = forwarded_value<T&&>;
143
6/6
✓ Branch 0 taken 6024 times.
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 232 times.
✓ Branch 5 taken 82 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 4 times.
12752 for (auto&& elem : from)
144
2/2
✓ Branch 3 taken 6272 times.
✓ Branch 6 taken 6182 times.
12976 result.emplace_back(
145 value_from(
146 // not a static_cast in order to appease clang < 4.0
147
1/1
✓ Branch 1 taken 84 times.
432 ForwardedValue(elem),
148 ctx,
149 result.storage() ));
150 208 }
151
152 // tuple-like types
153 template< class T, class Ctx >
154 void
155 292 value_from_impl( tuple_conversion_tag, value& jv, T&& from, Ctx const& ctx )
156 {
157 292 constexpr std::size_t n =
158 std::tuple_size<remove_cvref<T>>::value;
159 292 array& arr = jv.emplace_array();
160 292 arr.reserve(n);
161
1/1
✓ Branch 1 taken 146 times.
292 mp11::mp_for_each<mp11::mp_iota_c<n>>(
162 292 append_tuple_element< Ctx, T >{ arr, ctx, std::forward<T>(from) });
163 292 }
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
300