mirror of
https://github.com/nlohmann/json.git
synced 2026-09-30 22:15:19 +00:00
Merge branch 'json-view/10-view-document' into json-view/11-view-access
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -418,6 +418,14 @@ class builder
|
||||
return w;
|
||||
}
|
||||
|
||||
/// a compile-time option as a runtime condition: testing the template
|
||||
/// argument directly makes a condition like `TrailingCommas && c == ']'`
|
||||
/// constant when the option is off, which MSVC reports as C4127
|
||||
static NLOHMANN_VIEW_ALWAYS_INLINE bool enabled(bool option) noexcept
|
||||
{
|
||||
return option;
|
||||
}
|
||||
|
||||
/// The parse state and the parser proper. The cursor is a local object of
|
||||
/// run() whose address never escapes (everything it calls out of line is a
|
||||
/// member of the builder and gets the positions it needs), so that the
|
||||
@@ -547,7 +555,7 @@ arr_next:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TrailingCommas && cur() == ']')
|
||||
if (enabled(TrailingCommas) && cur() == ']')
|
||||
{
|
||||
++p;
|
||||
goto close_container;
|
||||
@@ -614,7 +622,7 @@ obj_next:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TrailingCommas && cur() == '}')
|
||||
if (enabled(TrailingCommas) && cur() == '}')
|
||||
{
|
||||
++p;
|
||||
goto close_container;
|
||||
@@ -756,7 +764,7 @@ indent_done:
|
||||
{
|
||||
++p;
|
||||
}
|
||||
if (Comments && cur() == '/')
|
||||
if (enabled(Comments) && cur() == '/')
|
||||
{
|
||||
const unsigned char* const q = cold.comment(p);
|
||||
if (q == nullptr)
|
||||
|
||||
@@ -956,6 +956,14 @@ class builder
|
||||
return w;
|
||||
}
|
||||
|
||||
/// a compile-time option as a runtime condition: testing the template
|
||||
/// argument directly makes a condition like `TrailingCommas && c == ']'`
|
||||
/// constant when the option is off, which MSVC reports as C4127
|
||||
static NLOHMANN_VIEW_ALWAYS_INLINE bool enabled(bool option) noexcept
|
||||
{
|
||||
return option;
|
||||
}
|
||||
|
||||
/// The parse state and the parser proper. The cursor is a local object of
|
||||
/// run() whose address never escapes (everything it calls out of line is a
|
||||
/// member of the builder and gets the positions it needs), so that the
|
||||
@@ -1085,7 +1093,7 @@ arr_next:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TrailingCommas && cur() == ']')
|
||||
if (enabled(TrailingCommas) && cur() == ']')
|
||||
{
|
||||
++p;
|
||||
goto close_container;
|
||||
@@ -1152,7 +1160,7 @@ obj_next:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TrailingCommas && cur() == '}')
|
||||
if (enabled(TrailingCommas) && cur() == '}')
|
||||
{
|
||||
++p;
|
||||
goto close_container;
|
||||
@@ -1294,7 +1302,7 @@ indent_done:
|
||||
{
|
||||
++p;
|
||||
}
|
||||
if (Comments && cur() == '/')
|
||||
if (enabled(Comments) && cur() == '/')
|
||||
{
|
||||
const unsigned char* const q = cold.comment(p);
|
||||
if (q == nullptr)
|
||||
|
||||
@@ -1465,7 +1465,8 @@ TEST_CASE("Eisel-Lemire float conversion")
|
||||
// than the distance to the rounding boundary, so it must not change
|
||||
std::string longer = token;
|
||||
const std::size_t e = longer.find('e');
|
||||
const std::string extra = longer.find('.') == std::string::npos ? ".000000000000000000001" : "000000000000000000001";
|
||||
const std::size_t dot = longer.find('.');
|
||||
const std::string extra = dot == std::string::npos ? ".000000000000000000001" : "000000000000000000001";
|
||||
longer.insert(e == std::string::npos ? longer.size() : e, extra);
|
||||
CAPTURE(longer);
|
||||
if (eisel_lemire(longer, out))
|
||||
@@ -1488,7 +1489,8 @@ TEST_CASE("Eisel-Lemire float conversion")
|
||||
CHECK(bits_of(json::parse("-65.613616999999977").get<double>()) == bits_of(-65.613616999999977));
|
||||
CHECK(bits_of(json::parse("2.2250738585072011e-308").get<double>()) == 0x000FFFFFFFFFFFFFu);
|
||||
CHECK(bits_of(json::parse("4.9406564584124654e-324").get<double>()) == 1u);
|
||||
CHECK_THROWS_WITH_AS(json::parse("1.7976931348623159e308"),
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::parse("1.7976931348623159e308"),
|
||||
"[json.exception.out_of_range.406] number overflow parsing '1.7976931348623159e308'", json::out_of_range&);
|
||||
}
|
||||
}
|
||||
@@ -1555,16 +1557,23 @@ TEST_CASE("string scanning kernels")
|
||||
state ^= state << 17u;
|
||||
return state;
|
||||
};
|
||||
// the upper half as a 32-bit value: converts to std::size_t implicitly on
|
||||
// every platform (a cast of std::uint64_t is useless where both are the
|
||||
// same type, and required where std::size_t is 32 bits wide)
|
||||
const auto next_small = [&next]()
|
||||
{
|
||||
return static_cast<std::uint32_t>(next() >> 32u);
|
||||
};
|
||||
for (int round = 0; round < 100000; ++round)
|
||||
{
|
||||
// mostly ordinary text, so that runs span several words
|
||||
std::string text(static_cast<std::size_t>(next() % 8), '.');
|
||||
const auto count = static_cast<std::size_t>(next() % 12);
|
||||
std::string text(next_small() % 8u, '.');
|
||||
const std::size_t count = next_small() % 12u;
|
||||
for (std::size_t k = 0; k < count; ++k)
|
||||
{
|
||||
const std::size_t p = (next() % 4 == 0) ? static_cast<std::size_t>(next() % pieces.size()) : 0;
|
||||
const std::size_t p = (next() % 4 == 0) ? next_small() % pieces.size() : 0;
|
||||
text += pieces[p];
|
||||
text += std::string(static_cast<std::size_t>(next() % 10), 'x');
|
||||
text += std::string(next_small() % 10u, 'x');
|
||||
}
|
||||
const auto* data = reinterpret_cast<const unsigned char*>(text.data()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
for (std::size_t offset = 0; offset < 3 && offset <= text.size(); ++offset)
|
||||
|
||||
@@ -32,6 +32,7 @@ using nlohmann::ordered_json_view;
|
||||
|
||||
namespace
|
||||
{
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
// the exception parse() throws for a text, or "" if it accepts it
|
||||
std::string parse_exception(const std::string& text, bool comments = false, bool trailing_commas = false)
|
||||
{
|
||||
@@ -60,6 +61,7 @@ std::string view_exception(const std::string& text, bool comments = false, bool
|
||||
}
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
// a small deterministic generator of documents
|
||||
struct generator
|
||||
@@ -149,7 +151,7 @@ TEST_CASE("json_view")
|
||||
CHECK(v.materialize() == j);
|
||||
}
|
||||
|
||||
const json_view invalid;
|
||||
const json_view invalid{};
|
||||
CHECK(invalid.is_discarded());
|
||||
CHECK(!static_cast<bool>(invalid));
|
||||
CHECK(invalid.type() == json::value_t::discarded);
|
||||
@@ -194,9 +196,11 @@ TEST_CASE("json_view")
|
||||
})
|
||||
{
|
||||
CAPTURE(text);
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
const std::string expected = parse_exception(text);
|
||||
REQUIRE(!expected.empty());
|
||||
CHECK(view_exception(text) == expected);
|
||||
#endif
|
||||
CHECK(!json_document::accept(text));
|
||||
const json_document d = json_document::parse(text, false);
|
||||
CHECK(d.is_discarded());
|
||||
@@ -204,8 +208,9 @@ TEST_CASE("json_view")
|
||||
CHECK(d.node_count() == 0);
|
||||
}
|
||||
// the exception types
|
||||
CHECK_THROWS_AS(json_document::parse("[1,"), json::parse_error&);
|
||||
CHECK_THROWS_AS(json_document::parse("1e400"), json::out_of_range&);
|
||||
json_document _;
|
||||
CHECK_THROWS_AS(_ = json_document::parse("[1,"), json::parse_error&);
|
||||
CHECK_THROWS_AS(_ = json_document::parse("1e400"), json::out_of_range&);
|
||||
}
|
||||
|
||||
SECTION("parse options")
|
||||
@@ -220,7 +225,9 @@ TEST_CASE("json_view")
|
||||
const bool comments = (options & 1) != 0;
|
||||
const bool trailing_commas = (options & 2) != 0;
|
||||
CHECK(json_document::accept(text, comments, trailing_commas) == json::accept(text, comments, trailing_commas));
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
CHECK(view_exception(text, comments, trailing_commas) == parse_exception(text, comments, trailing_commas));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,7 +239,9 @@ TEST_CASE("json_view")
|
||||
const std::string nul_in_comment("[1, // c\0\n2]", 12);
|
||||
CHECK(json_document::accept(nul_in_comment, true) == json::accept(nul_in_comment, true));
|
||||
CHECK(json_document::parse("\xEF\xBB\xBF[1]").root().materialize() == json::parse("\xEF\xBB\xBF[1]"));
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
CHECK(view_exception("\xEF\xBB") == parse_exception("\xEF\xBB"));
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("inputs")
|
||||
|
||||
@@ -9,8 +9,12 @@
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <nlohmann/detail/view/builder.hpp>
|
||||
#include <nlohmann/detail/view/string_ref.hpp>
|
||||
#if JSON_TEST_USING_MULTIPLE_HEADERS
|
||||
#include <nlohmann/detail/view/builder.hpp>
|
||||
#include <nlohmann/detail/view/string_ref.hpp>
|
||||
#else
|
||||
#include <nlohmann/json_view.hpp> // the single header contains the internal headers
|
||||
#endif
|
||||
using nlohmann::json;
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
Reference in New Issue
Block a user