From 44166ff4d6c96ea461d9cd74d4b93672a8ed6506 Mon Sep 17 00:00:00 2001 From: Timothy Prepscius Date: Tue, 23 Oct 2018 16:41:49 -0400 Subject: [PATCH] enables erase by json_pointer --- include/nlohmann/detail/json_pointer.hpp | 74 ++++++++++++++++++++++++ include/nlohmann/json.hpp | 39 +++++++++++++ 2 files changed, 113 insertions(+) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index b2bc47277..e449f3549 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -347,6 +347,80 @@ class json_pointer return *ptr; } + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + void erase_checked(BasicJsonType* ptr) const + { + BasicJsonType* previous = nullptr; + + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + previous = ptr; + + switch (ptr->m_type) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + // if we get here, it means that no exception was thrown, so therefore the value specified to + // erase exists + + // if previous exists, it means that the specified json value was not a root, so, we use the previous + // object and erase from it + if (previous) + { + previous->erase(reference_tokens.back()); + } + else + { + // what to do + } + } + /*! @brief return a const reference to the pointed to value diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 619fd9e63..7bcb97287 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -7085,6 +7085,45 @@ class basic_json { return ptr.get_checked(this); } + + + /*! + @brief remove element from a JSON tree given a pointer + + Removes elements from a JSON tree with the pointer value @ptr + + @param[in] pointer value of the elements to remove + + @post References and iterators to the erased elements are invalidated. + Other references and iterators are not affected. + + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. + + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. + + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.403 if the JSON pointer describes a key of an object + which cannot be found. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @complexity + + @since version + */ + void erase(const json_pointer& ptr) + { + ptr.erase_checked(this); + } /*! @brief return flattened JSON value