From 0244d5958a549aad491d9ddf4f41513876e60e28 Mon Sep 17 00:00:00 2001 From: Roy Bellingan Date: Sat, 15 Feb 2025 01:50:33 +0000 Subject: [PATCH 1/7] 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. From 21582608d293ee2ecd4b9b6ea6437580873f168c Mon Sep 17 00:00:00 2001 From: Roy Date: Sat, 15 Feb 2025 13:50:15 +0000 Subject: [PATCH 2/7] forget the falltrought --- include/boost/json/impl/pointer.ipp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index 57da07c78..c97a8c97a 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -500,6 +500,7 @@ value::delete_at_pointer( obj.erase(kv); return {true, err_position}; } + return {false,err_position}; } case kind::array: { auto const index = detail::parse_number_token(previous_segment, ec); @@ -508,6 +509,7 @@ value::delete_at_pointer( arr.erase(arr.begin() + index); return {true, err_position}; } + return {false,err_position}; } default: { BOOST_JSON_FAIL(ec, error::value_is_scalar); From 231143c0a19fe851fabb3d6d4ecd6dae21a591b4 Mon Sep 17 00:00:00 2001 From: Roy Date: Sat, 15 Feb 2025 15:09:36 +0000 Subject: [PATCH 3/7] build was failing on old gcc4 and 5, https://drone.cpp.al/boostorg/json/1791/15/2 ./boost/json/impl/pointer.ipp:457:18: error: 'kind' is not a class, namespace, or enumeration --- include/boost/json/impl/pointer.ipp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index c97a8c97a..aa17947f0 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -454,7 +454,7 @@ value::delete_at_pointer( switch (result->kind()) { - case kind::object: { + case boost::json::kind::object: { auto& obj = result->get_object(); detail::pointer_token const token(segment); @@ -468,7 +468,7 @@ value::delete_at_pointer( } break; } - case kind::array: { + case boost::json::kind::array: { auto const index = detail::parse_number_token(segment, ec); segment = detail::next_segment(sv, ec); @@ -492,7 +492,7 @@ value::delete_at_pointer( switch (previous_result->kind()) { - case kind::object: { + 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; @@ -502,7 +502,7 @@ value::delete_at_pointer( } return {false,err_position}; } - case kind::array: { + 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)){ From c829369210d768d139fa37bfb015f65d5dc62262 Mon Sep 17 00:00:00 2001 From: Roy Bellingan Date: Sat, 15 Feb 2025 22:17:33 +0000 Subject: [PATCH 4/7] Update pointer.ipp Unreachable code removed. --- include/boost/json/impl/pointer.ipp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index aa17947f0..65d6e340a 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -516,7 +516,6 @@ value::delete_at_pointer( return {false, err_position}; } } - return {false, err_position}; } value* From 220ea7325af4d9c546199b046baa4303837a236d Mon Sep 17 00:00:00 2001 From: Roy Bellingan Date: Tue, 18 Feb 2025 01:03:41 +0000 Subject: [PATCH 5/7] initial test for intrusive debug --- include/boost/json/detail/value_to.hpp | 33 +++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/include/boost/json/detail/value_to.hpp b/include/boost/json/detail/value_to.hpp index 29ae444f9..3c012b564 100644 --- a/include/boost/json/detail/value_to.hpp +++ b/include/boost/json/detail/value_to.hpp @@ -12,6 +12,23 @@ #ifndef BOOST_JSON_DETAIL_VALUE_TO_HPP #define BOOST_JSON_DETAIL_VALUE_TO_HPP +#ifndef BOOST_JSON_INTRUSIVE_INDEX_INC +#define BOOST_JSON_INTRUSIVE_INDEX_INC ((void)0); +#endif + +#ifndef BOOST_JSON_INTRUSIVE_PATH_PUSH +#define BOOST_JSON_INTRUSIVE_PATH_PUSH(x) ((void)0); +#endif + +#ifndef BOOST_JSON_INTRUSIVE_PATH_POP +#define BOOST_JSON_INTRUSIVE_PATH_POP ((void)0); +#endif + +#ifndef BOOST_JSON_INTRUSIVE_MESSAGE +#define BOOST_JSON_INTRUSIVE_MESSAGE(x) ((void)0); +#endif + + #include #include #include @@ -270,13 +287,21 @@ value_to_impl( } auto ins = detail::inserter(result, inserter_implementation()); + + BOOST_JSON_INTRUSIVE_PATH_PUSH(-1) + for( value const& val: *arr ) { + BOOST_JSON_INTRUSIVE_INDEX_INC + auto elem_res = try_value_to>( val, ctx ); if( elem_res.has_error() ) return {boost::system::in_place_error, elem_res.error()}; *ins++ = std::move(*elem_res); } + + BOOST_JSON_INTRUSIVE_PATH_POP + return result; } @@ -373,10 +398,14 @@ struct to_described_member system::error_code ec; BOOST_JSON_FAIL(ec, error::size_mismatch); res = {boost::system::in_place_error, ec}; + + BOOST_JSON_INTRUSIVE_MESSAGE(std::format("the key >> {} << is non optional and missing in path {}", D::name, BOOST_JSON_INTRUSIVE::composePath())); } return; } + BOOST_JSON_INTRUSIVE_PATH_PUSH(D::name) + #if defined(__GNUC__) && BOOST_GCC_VERSION >= 80000 && BOOST_GCC_VERSION < 11000 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused" @@ -386,8 +415,10 @@ struct to_described_member #if defined(__GNUC__) && BOOST_GCC_VERSION >= 80000 && BOOST_GCC_VERSION < 11000 # pragma GCC diagnostic pop #endif - if( member_res ) + if( member_res ){ (*res).* D::pointer = std::move(*member_res); + BOOST_JSON_INTRUSIVE_PATH_POP + } else res = {boost::system::in_place_error, member_res.error()}; } From 808fea0b4da55e2f8ed33207c6914abcf15231f3 Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 6 Jan 2026 01:34:49 +0000 Subject: [PATCH 6/7] function renamed as erase_at_pointer --- include/boost/json/impl/pointer.ipp | 2 +- include/boost/json/value.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index 65d6e340a..6f70ce2ef 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -416,7 +416,7 @@ value::find_pointer(string_view ptr, std::error_code& ec) noexcept } std::pair -value::delete_at_pointer( +value::erase_at_pointer( string_view sv, system::error_code& ec) { diff --git a/include/boost/json/value.hpp b/include/boost/json/value.hpp index 8512b51bd..de255f213 100644 --- a/include/boost/json/value.hpp +++ b/include/boost/json/value.hpp @@ -3036,7 +3036,7 @@ class value */ BOOST_JSON_DECL std::pair - delete_at_pointer( + erase_at_pointer( string_view sv, system::error_code& ec); //------------------------------------------------------ From 4e07b677e8f654155a559f1cfce0c4b76eb49ef2 Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 6 Jan 2026 03:25:35 +0000 Subject: [PATCH 7/7] some suggestion --- include/boost/json/impl/pointer.ipp | 36 +++++++++++++---------------- include/boost/json/value.hpp | 3 +-- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index 6f70ce2ef..a3eb12ffd 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -415,19 +415,20 @@ value::find_pointer(string_view ptr, std::error_code& ec) noexcept return const_cast(self.find_pointer(ptr, ec)); } -std::pair +bool value::erase_at_pointer( string_view sv, system::error_code& ec) { ec.clear(); - + if(sv.empty()){ + BOOST_JSON_FAIL(ec, error::syntax); + return false; + } 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; @@ -435,20 +436,17 @@ value::erase_at_pointer( while (true) { if (ec.failed()) - return {false, err_position}; + return false; if (!result) { BOOST_JSON_FAIL(ec, error::not_found); - return {false, err_position}; + return false; } if( segment.empty() ) break; - shift += segment.size(); - err_position = sv_copy.substr(0, shift); - previous_segment = segment; previous_result = result; @@ -464,7 +462,7 @@ value::erase_at_pointer( if( !result ) { BOOST_JSON_FAIL(ec, error::not_found); - return {false, err_position}; + return false; } break; } @@ -477,19 +475,17 @@ value::erase_at_pointer( if( !result ) { BOOST_JSON_FAIL(ec, error::past_the_end); - return {false, err_position}; + return false; } break; } default: { BOOST_JSON_FAIL(ec, error::value_is_scalar); - return {false, err_position}; + return false; } } } - err_position = {}; - switch (previous_result->kind()) { case boost::json::kind::object: { @@ -498,22 +494,22 @@ value::erase_at_pointer( key_value_pair* kv = detail::find_in_object(obj, token).first; if (kv) { obj.erase(kv); - return {true, err_position}; + return true; } - return {false,err_position}; + 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, err_position}; + return true; } - return {false,err_position}; + return false; } default: { BOOST_JSON_FAIL(ec, error::value_is_scalar); - return {false, err_position}; + return false; } } } diff --git a/include/boost/json/value.hpp b/include/boost/json/value.hpp index de255f213..59e4ebc92 100644 --- a/include/boost/json/value.hpp +++ b/include/boost/json/value.hpp @@ -3035,8 +3035,7 @@ class value /** Remove an element via JSON Pointer. */ BOOST_JSON_DECL - std::pair - erase_at_pointer( + bool erase_at_pointer( string_view sv, system::error_code& ec); //------------------------------------------------------