Skip to content

basic implementation of context-based path traction #1075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions include/boost/json/conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <boost/json/detail/config.hpp>
#include <boost/json/fwd.hpp>
#include <boost/json/string_view.hpp>

#include <type_traits>

Expand Down Expand Up @@ -437,6 +438,27 @@ struct is_variant_like;
template<class T>
struct is_optional_like;

struct context_key_push_tag{};
struct context_key_pop_tag{};
struct context_index_push_tag{};
struct context_index_pop_tag{};

template< class Ctx >
void
context_key_push( Ctx const& ctx, string_view sv );

template< class Ctx >
void
context_key_pop( Ctx const& ctx );

template< class Ctx >
void
context_index_push( Ctx const& ctx, std::size_t n );

template< class Ctx >
void
context_index_pop( Ctx const& ctx );

} // namespace json
} // namespace boost

Expand Down
20 changes: 17 additions & 3 deletions include/boost/json/detail/value_to.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,14 @@ value_to_impl(
auto ins = detail::inserter(res, inserter_implementation<T>());
for( key_value_pair const& kv: *obj )
{
json::context_key_push( ctx, kv.key() );
auto elem_res = try_value_to<mapped_type<T>>( kv.value(), ctx );
if( elem_res.has_error() )
return {boost::system::in_place_error, elem_res.error()};
*ins++ = value_type<T>{
key_type<T>(kv.key()),
std::move(*elem_res)};
json::context_key_pop(ctx);
}
return res;
}
Expand Down Expand Up @@ -272,24 +274,30 @@ value_to_impl(
auto ins = detail::inserter(result, inserter_implementation<T>());
for( value const& val: *arr )
{
json::context_index_push( ctx, &val - arr->begin() );
auto elem_res = try_value_to<value_type<T>>( val, ctx );
if( elem_res.has_error() )
return {boost::system::in_place_error, elem_res.error()};
*ins++ = std::move(*elem_res);
json::context_index_pop(ctx);
}
return result;
}

// tuple-like types
template< class T, class Ctx >
system::result<T>
try_make_tuple_elem(value const& jv, Ctx const& ctx, system::error_code& ec)
try_make_tuple_elem(
value const* b, std::size_t n, Ctx const& ctx, system::error_code& ec)
{
if( ec.failed() )
return {boost::system::in_place_error, ec};

auto result = try_value_to<T>( jv, ctx );
json::context_index_push(ctx, n);
auto result = try_value_to<T>( b[n], ctx );
ec = result.error();
if( !ec.failed() )
json::context_index_pop(ctx);
return result;
}

Expand All @@ -302,7 +310,7 @@ try_make_tuple_like(
auto items = std::make_tuple(
try_make_tuple_elem<
typename std::decay<tuple_element_t<Is, T>>::type >(
arr[Is], ctx, ec)
arr.data(), Is, ctx, ec)
...);
#if defined(BOOST_GCC)
# pragma GCC diagnostic push
Expand Down Expand Up @@ -377,6 +385,7 @@ struct to_described_member
return;
}

json::context_key_push(ctx, D::name);
#if defined(__GNUC__) && BOOST_GCC_VERSION >= 80000 && BOOST_GCC_VERSION < 11000
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused"
Expand All @@ -387,9 +396,14 @@ struct to_described_member
# pragma GCC diagnostic pop
#endif
if( member_res )
{
(*res).* D::pointer = std::move(*member_res);
json::context_key_pop(ctx);
}
else
{
res = {boost::system::in_place_error, member_res.error()};
}
}
};

Expand Down
52 changes: 52 additions & 0 deletions include/boost/json/impl/conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,58 @@ struct is_optional_like
mp11::mp_valid<detail::can_reset, T>>
{ };

inline
void
tag_invoke(context_key_push_tag, string_view, ...)
{
}

inline
void
tag_invoke(context_key_pop_tag, ...)
{
}

inline
void
tag_invoke(context_index_push_tag, std::size_t, ...)
{
}

inline
void
tag_invoke(context_index_pop_tag, ...)
{
}

template< class Ctx >
void
context_key_push(Ctx const& ctx, string_view sv)
{
tag_invoke(context_key_push_tag(), sv, ctx);
}

template< class Ctx >
void
context_key_pop(Ctx const& ctx)
{
tag_invoke(context_key_pop_tag(), ctx);
}

template< class Ctx >
void
context_index_push(Ctx const& ctx, std::size_t n)
{
tag_invoke(context_index_push_tag(), n, ctx);
}

template< class Ctx >
void
context_index_pop(Ctx const& ctx)
{
tag_invoke(context_index_pop_tag(), ctx);
}

} // namespace json
} // namespace boost

Expand Down
50 changes: 50 additions & 0 deletions test/value_to.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,45 @@ tag_invoke(
return T11( jv.to_number<int>() );
}

struct logging_context
{
std::vector<std::string>& path;
};

void
tag_invoke(
boost::json::context_key_push_tag,
boost::json::string_view sv,
logging_context const& ctx)
{
ctx.path.push_back(sv);
}

void
tag_invoke(
boost::json::context_key_pop_tag,
logging_context const& ctx)
{
ctx.path.pop_back();
}

void
tag_invoke(
boost::json::context_index_push_tag,
std::size_t n,
logging_context const& ctx)
{
ctx.path.push_back( std::to_string(n) );
}

void
tag_invoke(
boost::json::context_index_pop_tag,
logging_context const& ctx)
{
ctx.path.pop_back();
}

} // namespace value_to_test_ns

namespace std
Expand Down Expand Up @@ -814,6 +853,17 @@ class value_to_test

testContext();
testContainerHelpers();

value jv = {
{{"n", 1}, {"d", 2}},
{{"n", 3}, {"d", "4"}}
};
std::vector<std::string> error_path;
value_to_test_ns::logging_context ctx{error_path};
auto result = try_value_to< std::vector<value_to_test_ns::T6> >(
jv, ctx);
BOOST_TEST( result.error().failed() );
BOOST_TEST(( std::vector<std::string>{"1", "d"} == error_path ));
}
};

Expand Down
Loading