From 0244d5958a549aad491d9ddf4f41513876e60e28 Mon Sep 17 00:00:00 2001 From: Roy Bellingan Date: Sat, 15 Feb 2025 01:50:33 +0000 Subject: [PATCH] delete_at_pointer --- include/boost/json/impl/pointer.ipp | 102 ++++++++++++++++++++++++++++ include/boost/json/value.hpp | 7 ++ 2 files changed, 109 insertions(+) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index d07c48082..57da07c78 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -415,6 +415,108 @@ value::find_pointer(string_view ptr, std::error_code& ec) noexcept return const_cast(self.find_pointer(ptr, ec)); } +std::pair +value::delete_at_pointer( + string_view sv, + system::error_code& ec) +{ + ec.clear(); + + + string_view previous_segment; + string_view sv_copy = sv; + string_view err_position; + string_view segment = detail::next_segment(sv, ec); + size_t shift = 0; + + auto result = this; + auto previous_result = this; + + while (true) + { + if (ec.failed()) + return {false, err_position}; + + if (!result) + { + BOOST_JSON_FAIL(ec, error::not_found); + return {false, err_position}; + } + + if( segment.empty() ) + break; + + shift += segment.size(); + err_position = sv_copy.substr(0, shift); + + previous_segment = segment; + previous_result = result; + + switch (result->kind()) + { + case kind::object: { + auto& obj = result->get_object(); + + detail::pointer_token const token(segment); + segment = detail::next_segment(sv, ec); + + result = detail::if_contains_token(obj, token); + if( !result ) + { + BOOST_JSON_FAIL(ec, error::not_found); + return {false, err_position}; + } + break; + } + case kind::array: { + auto const index = detail::parse_number_token(segment, ec); + segment = detail::next_segment(sv, ec); + + auto& arr = result->get_array(); + result = arr.if_contains(index); + if( !result ) + { + BOOST_JSON_FAIL(ec, error::past_the_end); + return {false, err_position}; + } + break; + } + default: { + BOOST_JSON_FAIL(ec, error::value_is_scalar); + return {false, err_position}; + } + } + } + + err_position = {}; + + switch (previous_result->kind()) + { + case 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, err_position}; + } + } + case 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, err_position}; + } + } + default: { + BOOST_JSON_FAIL(ec, error::value_is_scalar); + return {false, err_position}; + } + } + return {false, err_position}; +} + value* value::set_at_pointer( string_view sv, diff --git a/include/boost/json/value.hpp b/include/boost/json/value.hpp index 151b8e3e2..13b8650d5 100644 --- a/include/boost/json/value.hpp +++ b/include/boost/json/value.hpp @@ -3996,6 +3996,13 @@ class value set_pointer_options const& opts = {} ); /** @} */ + /** Remove an element via JSON Pointer. + */ + BOOST_JSON_DECL + std::pair + delete_at_pointer( + string_view sv, + system::error_code& ec); //------------------------------------------------------ /** Return `true` if two values are equal.