Skip to content

Commit 675a94f

Browse files
author
Roy Bellingan
committed
Erase_at_pointer and related test, based on the suggestion in boostorg#1138
Resolve the parent JSON Pointer by splitting the full pointer into a parent prefix and last segment (via next_segment), then navigate to the parent with find_pointer instead of duplicating the walk_pointer logic.
1 parent f299282 commit 675a94f

3 files changed

Lines changed: 380 additions & 0 deletions

File tree

include/boost/json/impl/pointer.ipp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,84 @@ value::set_at_pointer(
520520
return try_set_at_pointer(sv, ref, opts).value();
521521
}
522522

523+
bool
524+
value::erase_at_pointer (
525+
string_view sv,
526+
system::error_code& ec) noexcept
527+
{
528+
ec.clear();
529+
if(sv.empty()){
530+
BOOST_JSON_FAIL(ec, error::missing_slash);
531+
return false;
532+
}
533+
534+
string_view walk = sv;
535+
string_view last_segment;
536+
while (true)
537+
{
538+
last_segment = detail::next_segment(walk, ec);
539+
if (ec.failed())
540+
return false;
541+
if (walk.empty())
542+
break;
543+
}
544+
545+
string_view const parent_sv(
546+
sv.data(),
547+
static_cast<std::size_t>(last_segment.data() - sv.data()));
548+
549+
value* parent = detail::walk_pointer(
550+
*this,
551+
parent_sv,
552+
ec,
553+
[]( object& obj, detail::pointer_token token )
554+
{
555+
return detail::if_contains_token(obj, token);
556+
},
557+
[]( array& arr, std::size_t index, system::error_code& ec ) -> value*
558+
{
559+
if( ec )
560+
return nullptr;
561+
562+
return arr.if_contains(index);
563+
},
564+
[]( value&, string_view)
565+
{
566+
return std::false_type();
567+
});
568+
569+
if (!parent)
570+
return false;
571+
572+
switch (parent->kind())
573+
{
574+
case boost::json::kind::object: {
575+
auto& obj = parent->get_object();
576+
detail::pointer_token const token(last_segment);
577+
key_value_pair* kv = detail::find_in_object(obj, token).first;
578+
if (kv) {
579+
obj.erase(kv);
580+
return true;
581+
}
582+
return false;
583+
}
584+
case boost::json::kind::array: {
585+
auto const index = detail::parse_number_token(last_segment, ec);
586+
auto& arr = parent->get_array();
587+
if (arr.if_contains(index)){
588+
arr.erase(arr.begin() + index);
589+
return true;
590+
}
591+
return false;
592+
}
593+
default: {
594+
BOOST_JSON_FAIL(ec, error::value_is_scalar);
595+
return false;
596+
}
597+
}
598+
}
599+
600+
523601
} // namespace json
524602
} // namespace boost
525603

include/boost/json/value.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,19 @@ class value
30353035

30363036
//------------------------------------------------------
30373037

3038+
/** Remove an element via JSON Pointer.
3039+
3040+
@{
3041+
*/
3042+
BOOST_JSON_DECL
3043+
bool
3044+
erase_at_pointer(
3045+
string_view sv,
3046+
system::error_code& ec) noexcept;
3047+
3048+
/// @}
3049+
//------------------------------------------------------
3050+
30383051
/** Check if two values are equal.
30393052
30403053
Two values are equal when they are the same kind and their referenced

0 commit comments

Comments
 (0)