Skip to content
Open
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
104 changes: 104 additions & 0 deletions include/boost/json/impl/pointer.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,110 @@ value::set_at_pointer(
return try_set_at_pointer(sv, ref, opts).value();
}

bool
value::erase_at_pointer(
string_view sv,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, reformat here and elsewhere. The project doesn't do such token alignment.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😓

system::error_code& ec)
{
ec.clear();
if(sv.empty()){
BOOST_JSON_FAIL(ec, error::syntax);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error::syntax is for JSON syntax errors. Arguably, error::missing_slash is fitting (you require at least one pointer token, and a pointer token starts with a /. But there's an interesting question if we want to allow zero tokens, and what to do in that case. For example, we can set the root object to null.

return false;
}

string_view previous_segment;

string_view segment = detail::next_segment(sv, ec);

auto result = this;
auto previous_result = this;

while (true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this loop, this is pretty much walk_pointer used with find_pointer lambdas, followed by element erasure, if the search was successful. The only difference is that you need to store the parent of the discovered element, which can be achieved with lambdas with captures.

So, why not do that instead of duplicating walk_pointer?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check that part of the code, thank you

{
if (ec.failed())
return false;

if (!result)
{
BOOST_JSON_FAIL(ec, error::not_found);
return false;
}

if( segment.empty() )
break;

previous_segment = segment;
previous_result = result;

switch (result->kind())
{
case boost::json::kind::object: {
auto& obj = result->get_object();

detail::pointer_token const token(segment);
segment = detail::next_segment(sv, ec);
if (ec.failed())
return false;

result = detail::if_contains_token(obj, token);
if( !result )
{
BOOST_JSON_FAIL(ec, error::not_found);
return false;
}
break;
}
case boost::json::kind::array: {
auto const index = detail::parse_number_token(segment, ec);
segment = detail::next_segment(sv, ec);
if (ec.failed())
return false;

auto& arr = result->get_array();
result = arr.if_contains(index);
if( !result )
{
BOOST_JSON_FAIL(ec, error::past_the_end);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error::past_the_end is for when the current token is the past-the-end token (-). This is just error::not_found.

return false;
}
break;
}
default: {
BOOST_JSON_FAIL(ec, error::value_is_scalar);
return false;
}
}
}

switch (previous_result->kind())
{
case boost::json::kind::object: {
auto& obj = previous_result->get_object();
detail::pointer_token const token(previous_segment);
key_value_pair* kv = detail::find_in_object(obj, token).first;
if (kv) {
obj.erase(kv);
return true;
}
return false;
}
case boost::json::kind::array: {
auto const index = detail::parse_number_token(previous_segment, ec);
auto& arr = previous_result->get_array();
if (arr.if_contains(index)){
arr.erase(arr.begin() + index);
return true;
}
return false;
}
default: {
BOOST_JSON_FAIL(ec, error::value_is_scalar);
return false;
}
}
}


} // namespace json
} // namespace boost

Expand Down
13 changes: 13 additions & 0 deletions include/boost/json/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3035,6 +3035,19 @@ class value

//------------------------------------------------------

/** Remove an element via JSON Pointer.

@{
*/
BOOST_JSON_DECL
bool
erase_at_pointer(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should also be a non-throwing overload.

string_view sv,
system::error_code& ec);

/// @}
//------------------------------------------------------

/** Check if two values are equal.

Two values are equal when they are the same kind and their referenced
Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local SOURCES =
doc_uses_allocator.cpp
doc_using_numbers.cpp
double.cpp
erase_at_pointer.cpp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this feature warrants a separate test file. Just use pointer.cpp.

error.cpp
fwd.cpp
json.cpp
Expand Down
Loading
Loading