From 97a25de93866fc92a32e44c1856217dd6327f212 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 7 Apr 2017 18:29:09 +0200 Subject: [PATCH] :sparkles: proposal for #428 This implementation forwards the iterators to std::map::insert. --- doc/examples/insert__range_object.cpp | 20 +++++++++++ doc/examples/insert__range_object.output | 3 ++ src/json.hpp | 46 ++++++++++++++++++++++++ src/json.hpp.re2c | 46 ++++++++++++++++++++++++ test/src/unit-modifiers.cpp | 36 ++++++++++++++++++- 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 doc/examples/insert__range_object.cpp create mode 100644 doc/examples/insert__range_object.output diff --git a/doc/examples/insert__range_object.cpp b/doc/examples/insert__range_object.cpp new file mode 100644 index 00000000..4cd58938 --- /dev/null +++ b/doc/examples/insert__range_object.cpp @@ -0,0 +1,20 @@ +#include + +using json = nlohmann::json; + +int main() +{ + // create two JSON objects + json j1 = {{"one", "eins"}, {"two", "zwei"}}; + json j2 = {{"eleven", "elf"}, {"seventeen", "siebzehn"}}; + + // output objects + std::cout << j1 << '\n'; + std::cout << j2 << '\n'; + + // insert range from j2 to j1 + j1.insert(j2.begin(), j2.end()); + + // output result of insert call + std::cout << j1 << '\n'; +} diff --git a/doc/examples/insert__range_object.output b/doc/examples/insert__range_object.output new file mode 100644 index 00000000..a5985158 --- /dev/null +++ b/doc/examples/insert__range_object.output @@ -0,0 +1,3 @@ +{"one":"eins","two":"zwei"} +{"eleven":"elf","seventeen":"siebzehn"} +{"eleven":"elf","one":"eins","seventeen":"siebzehn","two":"zwei"} diff --git a/src/json.hpp b/src/json.hpp index 98659054..182a634c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5978,6 +5978,52 @@ class basic_json return result; } + /*! + @brief inserts elements + + Inserts elements from range `[first, last)`. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than objects; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number + of elements to insert. + + @liveexample{The example shows how `insert()` is used.,insert__range_object} + + @since version 3.0.0 + */ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (not is_object()) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); + } + + // check if range iterators belong to the same JSON object + if (first.m_object != last.m_object) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (not first.m_object->is_object() or not first.m_object->is_object()) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + /*! @brief exchanges the values diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 5e90f611..02866b22 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -5978,6 +5978,52 @@ class basic_json return result; } + /*! + @brief inserts elements + + Inserts elements from range `[first, last)`. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than objects; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number + of elements to insert. + + @liveexample{The example shows how `insert()` is used.,insert__range_object} + + @since version 3.0.0 + */ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (not is_object()) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); + } + + // check if range iterators belong to the same JSON object + if (first.m_object != last.m_object) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (not first.m_object->is_object() or not first.m_object->is_object()) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + /*! @brief exchanges the values diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index 0c332111..b860beee 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -594,7 +594,7 @@ TEST_CASE("modifiers") } } - SECTION("range") + SECTION("range for array") { json j_other_array = {"first", "second"}; @@ -631,6 +631,40 @@ TEST_CASE("modifiers") } } + SECTION("range for object") + { + json j_object1 = {{"one", "eins"}, {"two", "zwei"}}; + json j_object2 = {{"eleven", "elf"}, {"seventeen", "siebzehn"}}; + + SECTION("proper usage") + { + j_object1.insert(j_object2.begin(), j_object2.end()); + CHECK(j_object1.size() == 4); + } + + SECTION("empty range") + { + j_object1.insert(j_object2.begin(), j_object2.begin()); + CHECK(j_object1.size() == 2); + } + + SECTION("invalid iterators") + { + json j_other_array2 = {"first", "second"}; + + CHECK_THROWS_AS(j_array.insert(j_object2.begin(), j_object2.end()), json::type_error); + CHECK_THROWS_AS(j_object1.insert(j_object1.begin(), j_object2.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_object1.insert(j_array.begin(), j_array.end()), json::invalid_iterator); + + CHECK_THROWS_WITH(j_array.insert(j_object2.begin(), j_object2.end()), + "[json.exception.type_error.309] cannot use insert() with array"); + CHECK_THROWS_WITH(j_object1.insert(j_object1.begin(), j_object2.end()), + "[json.exception.invalid_iterator.210] iterators do not fit"); + CHECK_THROWS_WITH(j_object1.insert(j_array.begin(), j_array.end()), + "[json.exception.invalid_iterator.202] iterators first and last must point to objects"); + } + } + SECTION("initializer list at position") { SECTION("insert before begin()")