diff --git a/include/nlohmann/detail/view/builder.hpp b/include/nlohmann/detail/view/builder.hpp index 45f547072..2e0151b31 100644 --- a/include/nlohmann/detail/view/builder.hpp +++ b/include/nlohmann/detail/view/builder.hpp @@ -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) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8c81b9123..71cfe2322 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -279,6 +279,10 @@ if(json_32bit_test_only) elseif(NOT json_32bit_test) list(FILTER files EXCLUDE REGEX src/unit-32bit.cpp) endif() +if(NOT JSON_MultipleHeaders) + # the internal headers of json_view are not part of a single header yet + list(FILTER files EXCLUDE REGEX src/unit-json_view_builder.cpp) +endif() foreach(file ${files}) json_test_add_test_for(${file} MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}) diff --git a/tests/src/unit-class_lexer.cpp b/tests/src/unit-class_lexer.cpp index e16bf0bf1..e476c08c3 100644 --- a/tests/src/unit-class_lexer.cpp +++ b/tests/src/unit-class_lexer.cpp @@ -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()) == bits_of(-65.613616999999977)); CHECK(bits_of(json::parse("2.2250738585072011e-308").get()) == 0x000FFFFFFFFFFFFFu); CHECK(bits_of(json::parse("4.9406564584124654e-324").get()) == 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(next() >> 32u); + }; for (int round = 0; round < 100000; ++round) { // mostly ordinary text, so that runs span several words - std::string text(static_cast(next() % 8), '.'); - const auto count = static_cast(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(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(next() % 10), 'x'); + text += std::string(next_small() % 10u, 'x'); } const auto* data = reinterpret_cast(text.data()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) for (std::size_t offset = 0; offset < 3 && offset <= text.size(); ++offset)