* Speed up container destruction, iterator access and diff() Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Destroy the first levels of a value by recursion The pointer-reversing walk in destroy_container() avoids the call stack but moves a value around for every container it visits. Recurse for the first recursion_depth_limit() levels instead - no allocation, no thread-local, a bounded frame - and hand anything deeper to the walk. Destroy twitter 0.49 -> 0.36 ms, citm 0.80 -> 0.74 ms (3.12.0: 0.47 / 1.00). Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
1738 lines
53 KiB
C++
1738 lines
53 KiB
C++
// __ _____ _____ _____
|
|
// __| | __| | | | JSON for Modern C++ (supporting code)
|
|
// | | |__ | | | | | | version 3.12.0
|
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|
//
|
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include "doctest_compatibility.h"
|
|
|
|
#define JSON_TESTS_PRIVATE
|
|
#include <nlohmann/json.hpp>
|
|
#include <string>
|
|
#include <vector>
|
|
using nlohmann::json;
|
|
|
|
TEST_CASE("iterators 1")
|
|
{
|
|
SECTION("basic behavior")
|
|
{
|
|
SECTION("uninitialized")
|
|
{
|
|
json::iterator it; // NOLINT(misc-const-correctness)
|
|
CHECK(it.m_object == nullptr);
|
|
|
|
json::const_iterator cit; // NOLINT(misc-const-correctness)
|
|
CHECK(cit.m_object == nullptr);
|
|
}
|
|
|
|
SECTION("boolean")
|
|
{
|
|
json j = true;
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
it--;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
--it;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it = j_const.begin();
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
it--;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
--it;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
it--;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
--it;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j_const.cbegin();
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it = j.rbegin();
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
it--;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
--it;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j.crbegin();
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
it--;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
--it;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j_const.crbegin();
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("additional tests")
|
|
{
|
|
SECTION("!(begin != begin)")
|
|
{
|
|
CHECK(!(j.begin() != j.begin()));
|
|
}
|
|
|
|
SECTION("!(end != end)")
|
|
{
|
|
CHECK(!(j.end() != j.end()));
|
|
}
|
|
|
|
SECTION("begin < end")
|
|
{
|
|
CHECK(j.begin() < j.end());
|
|
}
|
|
|
|
SECTION("begin <= end")
|
|
{
|
|
CHECK(j.begin() <= j.end());
|
|
}
|
|
|
|
SECTION("end > begin")
|
|
{
|
|
CHECK(j.end() > j.begin());
|
|
}
|
|
|
|
SECTION("end >= begin")
|
|
{
|
|
CHECK(j.end() >= j.begin());
|
|
}
|
|
|
|
SECTION("end == end")
|
|
{
|
|
CHECK(j.end() == j.end());
|
|
}
|
|
|
|
SECTION("end <= end")
|
|
{
|
|
CHECK(j.end() <= j.end());
|
|
}
|
|
|
|
SECTION("begin == begin")
|
|
{
|
|
CHECK(j.begin() == j.begin());
|
|
}
|
|
|
|
SECTION("begin <= begin")
|
|
{
|
|
CHECK(j.begin() <= j.begin());
|
|
}
|
|
|
|
SECTION("begin >= begin")
|
|
{
|
|
CHECK(j.begin() >= j.begin());
|
|
}
|
|
|
|
SECTION("!(begin == end)")
|
|
{
|
|
CHECK(!(j.begin() == j.end()));
|
|
}
|
|
|
|
SECTION("begin != end")
|
|
{
|
|
CHECK(j.begin() != j.end());
|
|
}
|
|
|
|
SECTION("begin+1 == end")
|
|
{
|
|
CHECK(j.begin() + 1 == j.end());
|
|
}
|
|
|
|
SECTION("begin == end-1")
|
|
{
|
|
CHECK(j.begin() == j.end() - 1);
|
|
}
|
|
|
|
SECTION("begin != end+1")
|
|
{
|
|
CHECK(j.begin() != j.end() + 1);
|
|
}
|
|
|
|
SECTION("end != end+1")
|
|
{
|
|
CHECK(j.end() != j.end() + 1);
|
|
}
|
|
|
|
SECTION("begin+1 != begin+2")
|
|
{
|
|
CHECK(j.begin() + 1 != j.begin() + 2);
|
|
}
|
|
|
|
SECTION("begin+1 < begin+2")
|
|
{
|
|
CHECK(j.begin() + 1 < j.begin() + 2);
|
|
}
|
|
|
|
SECTION("begin+1 <= begin+2")
|
|
{
|
|
CHECK(j.begin() + 1 <= j.begin() + 2);
|
|
}
|
|
|
|
SECTION("end+1 != end+2")
|
|
{
|
|
CHECK(j.end() + 1 != j.end() + 2);
|
|
}
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(it.value() == json(true));
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(cit.value() == json(true));
|
|
|
|
auto rit = j.rend();
|
|
auto crit = j.crend();
|
|
CHECK_THROWS_WITH_AS(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(rit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
}
|
|
}
|
|
|
|
SECTION("string")
|
|
{
|
|
json j = "hello world";
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
it--;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
--it;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it = j_const.begin();
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
it--;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
--it;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
it--;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
--it;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j_const.cbegin();
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it = j.rbegin();
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
it--;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
--it;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j.crbegin();
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
it--;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
--it;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j_const.crbegin();
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(it.value() == json("hello world"));
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(cit.value() == json("hello world"));
|
|
|
|
auto rit = j.rend();
|
|
auto crit = j.crend();
|
|
CHECK_THROWS_WITH_AS(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(rit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
}
|
|
}
|
|
|
|
SECTION("array")
|
|
{
|
|
json j = {1, 2, 3};
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it_begin = j.begin();
|
|
json::iterator it_end = j.end();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[0]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[2]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it_begin = j_const.begin();
|
|
json::const_iterator it_end = j_const.end();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const[0]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const[2]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it_begin = j.cbegin();
|
|
json::const_iterator it_end = j.cend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[0]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[2]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it_begin = j_const.cbegin();
|
|
json::const_iterator it_end = j_const.cend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[0]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[2]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it_begin = j.rbegin();
|
|
json::reverse_iterator it_end = j.rend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[2]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[0]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it_begin = j.crbegin();
|
|
json::const_reverse_iterator it_end = j.crend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[2]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[0]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it_begin = j_const.crbegin();
|
|
json::const_reverse_iterator it_end = j_const.crend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[2]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[1]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j[0]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(it.value() == json(1));
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(cit.value() == json(1));
|
|
}
|
|
}
|
|
|
|
SECTION("object")
|
|
{
|
|
json j = {{"A", 1}, {"B", 2}, {"C", 3}};
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it_begin = j.begin();
|
|
json::iterator it_end = j.end();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["A"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["C"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it_begin = j_const.begin();
|
|
json::const_iterator it_end = j_const.end();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const["A"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const["C"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it_begin = j.cbegin();
|
|
json::const_iterator it_end = j.cend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["A"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["C"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it_begin = j_const.cbegin();
|
|
json::const_iterator it_end = j_const.cend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const["A"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j_const["C"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it_begin = j.rbegin();
|
|
json::reverse_iterator it_end = j.rend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["C"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["A"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it_begin = j.crbegin();
|
|
json::const_reverse_iterator it_end = j.crend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["C"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["A"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it_begin = j_const.crbegin();
|
|
json::const_reverse_iterator it_end = j_const.crend();
|
|
|
|
auto it = it_begin;
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["C"]);
|
|
|
|
it++;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["B"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it != it_end);
|
|
CHECK(*it == j["A"]);
|
|
|
|
++it;
|
|
CHECK(it != it_begin);
|
|
CHECK(it == it_end);
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK(it.key() == "A");
|
|
CHECK(it.value() == json(1));
|
|
CHECK(cit.key() == "A");
|
|
CHECK(cit.value() == json(1));
|
|
}
|
|
}
|
|
|
|
SECTION("number (integer)")
|
|
{
|
|
json j = 23;
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
it--;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
--it;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it = j_const.begin();
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
it--;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
--it;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
it--;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
--it;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j_const.cbegin();
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it = j.rbegin();
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
it--;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
--it;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j.crbegin();
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
it--;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
--it;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j_const.crbegin();
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(it.value() == json(23));
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(cit.value() == json(23));
|
|
|
|
auto rit = j.rend();
|
|
auto crit = j.crend();
|
|
CHECK_THROWS_WITH_AS(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(rit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
}
|
|
}
|
|
|
|
SECTION("number (unsigned)")
|
|
{
|
|
json j = 23u;
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
it--;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
--it;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it = j_const.begin();
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
it--;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
--it;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
it--;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
--it;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j_const.cbegin();
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it = j.rbegin();
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
it--;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
--it;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j.crbegin();
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
it--;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
--it;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j_const.crbegin();
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(it.value() == json(23));
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(cit.value() == json(23));
|
|
|
|
auto rit = j.rend();
|
|
auto crit = j.crend();
|
|
CHECK_THROWS_WITH_AS(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(rit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
}
|
|
}
|
|
|
|
SECTION("number (float)")
|
|
{
|
|
json j = 23.42;
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
it--;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.begin());
|
|
CHECK(it == j.end());
|
|
|
|
--it;
|
|
CHECK(it == j.begin());
|
|
CHECK(it != j.end());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
json::const_iterator it = j_const.begin();
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
it--;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.begin());
|
|
CHECK(it == j_const.end());
|
|
|
|
--it;
|
|
CHECK(it == j_const.begin());
|
|
CHECK(it != j_const.end());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
it--;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.cbegin());
|
|
CHECK(it == j.cend());
|
|
|
|
--it;
|
|
CHECK(it == j.cbegin());
|
|
CHECK(it != j.cend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
json::const_iterator it = j_const.cbegin();
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.cbegin());
|
|
CHECK(it == j_const.cend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.cbegin());
|
|
CHECK(it != j_const.cend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
json::reverse_iterator it = j.rbegin();
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
it--;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.rbegin());
|
|
CHECK(it == j.rend());
|
|
|
|
--it;
|
|
CHECK(it == j.rbegin());
|
|
CHECK(it != j.rend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j.crbegin();
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
it++;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
it--;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
|
|
++it;
|
|
CHECK(it != j.crbegin());
|
|
CHECK(it == j.crend());
|
|
|
|
--it;
|
|
CHECK(it == j.crbegin());
|
|
CHECK(it != j.crend());
|
|
CHECK(*it == j);
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
json::const_reverse_iterator it = j_const.crbegin();
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
it++;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
it--;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
|
|
++it;
|
|
CHECK(it != j_const.crbegin());
|
|
CHECK(it == j_const.crend());
|
|
|
|
--it;
|
|
CHECK(it == j_const.crbegin());
|
|
CHECK(it != j_const.crend());
|
|
CHECK(*it == j_const);
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(it.value() == json(23.42));
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK(cit.value() == json(23.42));
|
|
|
|
auto rit = j.rend();
|
|
auto crit = j.crend();
|
|
CHECK_THROWS_WITH_AS(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(rit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
}
|
|
}
|
|
|
|
SECTION("null")
|
|
{
|
|
json j = nullptr;
|
|
json j_const(j);
|
|
|
|
SECTION("json + begin/end")
|
|
{
|
|
const json::iterator it = j.begin();
|
|
CHECK(it == j.end());
|
|
}
|
|
|
|
SECTION("const json + begin/end")
|
|
{
|
|
const json::const_iterator it_begin = j_const.begin();
|
|
json::const_iterator it_end = j_const.end();
|
|
CHECK(it_begin == it_end);
|
|
}
|
|
|
|
SECTION("json + cbegin/cend")
|
|
{
|
|
const json::const_iterator it_begin = j.cbegin();
|
|
json::const_iterator it_end = j.cend();
|
|
CHECK(it_begin == it_end);
|
|
}
|
|
|
|
SECTION("const json + cbegin/cend")
|
|
{
|
|
const json::const_iterator it_begin = j_const.cbegin();
|
|
json::const_iterator it_end = j_const.cend();
|
|
CHECK(it_begin == it_end);
|
|
}
|
|
|
|
SECTION("json + rbegin/rend")
|
|
{
|
|
const json::reverse_iterator it = j.rbegin();
|
|
CHECK(it == j.rend());
|
|
}
|
|
|
|
SECTION("json + crbegin/crend")
|
|
{
|
|
const json::const_reverse_iterator it = j.crbegin();
|
|
CHECK(it == j.crend());
|
|
}
|
|
|
|
SECTION("const json + crbegin/crend")
|
|
{
|
|
const json::const_reverse_iterator it = j_const.crbegin();
|
|
CHECK(it == j_const.crend());
|
|
}
|
|
|
|
SECTION("key/value")
|
|
{
|
|
auto it = j.begin();
|
|
auto cit = j_const.cbegin();
|
|
CHECK_THROWS_WITH_AS(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(it.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(cit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
|
|
auto rit = j.rend();
|
|
auto crit = j.crend();
|
|
CHECK_THROWS_WITH_AS(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(rit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators", json::invalid_iterator&);
|
|
CHECK_THROWS_WITH_AS(crit.value(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("conversion from iterator to const iterator")
|
|
{
|
|
SECTION("boolean")
|
|
{
|
|
json j = true;
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("string")
|
|
{
|
|
json j = "hello world";
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("array")
|
|
{
|
|
json j = {1, 2, 3};
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("object")
|
|
{
|
|
json j = {{"A", 1}, {"B", 2}, {"C", 3}};
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("number (integer)")
|
|
{
|
|
json j = 23;
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("number (unsigned)")
|
|
{
|
|
json j = 23u;
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("number (float)")
|
|
{
|
|
json j = 23.42;
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
SECTION("null")
|
|
{
|
|
json j = nullptr;
|
|
json::const_iterator it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
it = j.begin();
|
|
CHECK(it == j.cbegin());
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE_TEMPLATE("reverse iteration and member access", Json, nlohmann::json, nlohmann::ordered_json)
|
|
{
|
|
SECTION("array: -- and rbegin/rend")
|
|
{
|
|
Json j = {1, 2, 3, 4};
|
|
|
|
auto it = j.end();
|
|
std::vector<int> seen;
|
|
while (it != j.begin())
|
|
{
|
|
--it;
|
|
seen.push_back(it->template get<int>());
|
|
}
|
|
CHECK(seen == std::vector<int> {4, 3, 2, 1});
|
|
|
|
auto it2 = j.end();
|
|
auto old = it2--;
|
|
CHECK(old == j.end());
|
|
CHECK(*it2 == 4);
|
|
|
|
seen.clear();
|
|
for (auto r = j.rbegin(); r != j.rend(); ++r)
|
|
{
|
|
seen.push_back(r->template get<int>());
|
|
}
|
|
CHECK(seen == std::vector<int> {4, 3, 2, 1});
|
|
|
|
seen.clear();
|
|
for (auto r = j.crbegin(); r != j.crend(); ++r)
|
|
{
|
|
seen.push_back(*r);
|
|
}
|
|
CHECK(seen == std::vector<int> {4, 3, 2, 1});
|
|
}
|
|
|
|
SECTION("object: -- and rbegin/rend")
|
|
{
|
|
Json j = {{"a", 1}, {"b", 2}, {"c", 3}};
|
|
// order of keys depends on the object type; use the forward order as reference
|
|
std::vector<std::string> fwd;
|
|
for (auto it = j.begin(); it != j.end(); ++it)
|
|
{
|
|
fwd.push_back(it.key());
|
|
}
|
|
std::vector<std::string> rev(fwd.rbegin(), fwd.rend());
|
|
|
|
std::vector<std::string> seen;
|
|
auto it = j.end();
|
|
while (it != j.begin())
|
|
{
|
|
--it;
|
|
seen.push_back(it.key());
|
|
}
|
|
CHECK(seen == rev);
|
|
|
|
auto it2 = j.end();
|
|
auto old = it2--;
|
|
CHECK(old == j.end());
|
|
CHECK(it2.key() == rev.front());
|
|
|
|
seen.clear();
|
|
for (auto r = j.rbegin(); r != j.rend(); ++r)
|
|
{
|
|
seen.push_back(r.key());
|
|
}
|
|
CHECK(seen == rev);
|
|
}
|
|
|
|
SECTION("object: operator-> reads and writes the mapped value")
|
|
{
|
|
Json j = {{"a", 1}, {"s", "str"}};
|
|
auto it = j.find("s");
|
|
REQUIRE(it != j.end());
|
|
CHECK(it->is_string());
|
|
CHECK(it->size() == 1);
|
|
*it = Json::array({1, 2});
|
|
CHECK(it->is_array());
|
|
it->push_back(3);
|
|
CHECK(j["s"].size() == 3);
|
|
|
|
const Json& cj = j;
|
|
auto cit = cj.find("a");
|
|
REQUIRE(cit != cj.end());
|
|
CHECK(cit->is_number_integer());
|
|
CHECK(cit->template get<int>() == 1);
|
|
}
|
|
|
|
SECTION("primitives: -- and ->")
|
|
{
|
|
Json j = 42;
|
|
auto it = j.end();
|
|
--it;
|
|
CHECK(it == j.begin());
|
|
CHECK(it->template get<int>() == 42);
|
|
}
|
|
|
|
SECTION("comparing iterators of different containers throws")
|
|
{
|
|
Json a = {1, 2};
|
|
Json b = {1, 2};
|
|
CHECK_THROWS_WITH_AS(a.begin() == b.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", nlohmann::json::invalid_iterator);
|
|
CHECK_THROWS_WITH_AS(a.begin() < b.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", nlohmann::json::invalid_iterator);
|
|
}
|
|
}
|