diff --git a/src/json.hpp b/src/json.hpp index 3c338eb8da..1016ab18fc 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -44,7 +44,7 @@ SOFTWARE. #include // initializer_list #include // hex #include // istream, ostream -#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator +#include // advance, begin, back_inserter, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include // numeric_limits #include // locale #include // map @@ -281,8 +281,6 @@ json.exception.invalid_iterator.204 | iterators out of range | When an iterator json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. @@ -3555,7 +3553,7 @@ class iter_impl : public std::iterator::type; /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; + using iterator_category = std::random_access_iterator_tag; /// default constructor iter_impl() = default; @@ -3949,7 +3947,8 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + std::advance(m_it.object_iterator, i); + break; case value_t::array: { @@ -4020,7 +4019,11 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + { + difference_type result = 0; + for (auto it = other; it != *this; ++it, ++result); + return result; + } case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; @@ -4041,7 +4044,11 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); + { + auto it = *this; + std::advance(it.m_it.object_iterator, n); + return *it; + } case value_t::array: return *std::next(m_it.array_iterator, n); @@ -13187,7 +13194,7 @@ class basic_json */ template::value, int> = 0> - static basic_json from_cbor(A1&& a1, A2&& a2, const bool strict = true) + static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true) { return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_cbor(strict); } @@ -13274,7 +13281,7 @@ class basic_json */ template::value, int> = 0> - static basic_json from_msgpack(A1&& a1, A2&& a2, const bool strict = true) + static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true) { return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_msgpack(strict); } diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 5a106b6ac8..e67ea40457 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -240,9 +240,8 @@ TEST_CASE("algorithms") SECTION("sorting an object") { json j({{"one", 1}, {"two", 2}}); - CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator&); - CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), - "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + std::sort(j.begin(), j.end()); + CHECK(j == json({{"one", 1}, {"two", 2}})); } } diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index be4e27702c..6391b54b21 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -240,7 +240,7 @@ TEST_CASE("iterators 2") SECTION("iterator arithmetic") { - json j_object = {{"one", 1}, {"two", 2}, {"three", 3}}; + json j_object = {{"one", 1}, {"two", 2}, {"three", 3}, {"four", 4}}; json j_array = {1, 2, 3, 4, 5, 6}; json j_null = nullptr; json j_value = 42; @@ -251,63 +251,25 @@ TEST_CASE("iterators 2") { { auto it = j_object.begin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.cbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.begin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.cbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.begin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); - CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.cbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); - CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.begin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.cbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.begin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.begin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); - CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + it += 3; + CHECK((j_object.begin() + 3) == it); + CHECK((3 + j_object.begin()) == it); + CHECK((it - 3) == j_object.begin()); + CHECK((it - j_object.begin()) == 3); + CHECK(*it == json(2)); + it -= 2; + CHECK(*it == json(1)); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); - CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + it += 3; + CHECK((j_object.cbegin() + 3) == it); + CHECK((3 + j_object.cbegin()) == it); + CHECK((it - 3) == j_object.cbegin()); + CHECK((it - j_object.cbegin()) == 3); + CHECK(*it == json(2)); + it -= 2; + CHECK(*it == json(1)); } } @@ -396,17 +358,17 @@ TEST_CASE("iterators 2") { { auto it = j_object.begin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); - CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); - CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); + CHECK(it[0] == json(4)); + CHECK(it[1] == json(1)); + CHECK(it[2] == json(3)); + CHECK(it[3] == json(2)); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); - CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); - CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); + CHECK(it[0] == json(4)); + CHECK(it[1] == json(1)); + CHECK(it[2] == json(3)); + CHECK(it[3] == json(2)); } } @@ -675,7 +637,7 @@ TEST_CASE("iterators 2") SECTION("reverse iterator arithmetic") { - json j_object = {{"one", 1}, {"two", 2}, {"three", 3}}; + json j_object = {{"one", 1}, {"two", 2}, {"three", 3}, {"four", 4}}; json j_array = {1, 2, 3, 4, 5, 6}; json j_null = nullptr; json j_value = 42; @@ -686,63 +648,25 @@ TEST_CASE("iterators 2") { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.crbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.rbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.crbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.rbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); - CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.crbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); - CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.rbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.crbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); - CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - } - { - auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); - CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + it += 3; + CHECK((j_object.rbegin() + 3) == it); + CHECK(json::reverse_iterator(3 + j_object.rbegin()) == it); + CHECK((it - 3) == j_object.rbegin()); + CHECK((it - j_object.rbegin()) == 3); + CHECK(*it == json(4)); + it -= 2; + CHECK(*it == json(3)); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); - CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + it += 3; + CHECK((j_object.crbegin() + 3) == it); + CHECK(json::const_reverse_iterator(3 + j_object.crbegin()) == it); + CHECK((it - 3) == j_object.crbegin()); + CHECK((it - j_object.crbegin()) == 3); + CHECK(*it == json(4)); + it -= 2; + CHECK(*it == json(3)); } } @@ -831,17 +755,17 @@ TEST_CASE("iterators 2") { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); - CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + CHECK(it[0] == json(2)); + CHECK(it[1] == json(3)); + CHECK(it[2] == json(1)); + CHECK(it[3] == json(4)); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); - CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); - CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); + CHECK(it[0] == json(2)); + CHECK(it[1] == json(3)); + CHECK(it[2] == json(1)); + CHECK(it[3] == json(4)); } }