From 131802310380515d6e2a5e27fbeadbc462b532d7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 29 Sep 2026 00:45:50 +0200 Subject: [PATCH] Address the clang-tidy findings of dump() The output buffer initializes its members in the initializer list, and the escaping has no nested conditional operators; the test marks a fixed seed. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/view/serializer.hpp | 39 ++++++++++++++------- single_include/nlohmann/json_view.hpp | 39 ++++++++++++++------- tests/src/unit-json_view.cpp | 4 +-- 3 files changed, 56 insertions(+), 26 deletions(-) diff --git a/include/nlohmann/detail/view/serializer.hpp b/include/nlohmann/detail/view/serializer.hpp index ce9bb8e8f..38377e9c0 100644 --- a/include/nlohmann/detail/view/serializer.hpp +++ b/include/nlohmann/detail/view/serializer.hpp @@ -37,12 +37,10 @@ class output_buffer { public: output_buffer(StringType& out, std::size_t estimate) - : m_out(out) - { - m_out.resize((std::max)(estimate, static_cast(64))); - m_pos = &m_out[0]; - m_end = m_pos + m_out.size(); - } + : m_out(sized(out, estimate)) + , m_pos(&m_out[0]) + , m_end(m_pos + m_out.size()) + {} void finish() { @@ -78,17 +76,23 @@ class output_buffer } private: + static StringType& sized(StringType& out, std::size_t estimate) + { + out.resize((std::max)(estimate, static_cast(64))); + return out; + } + NLOHMANN_VIEW_NOINLINE void grow(std::size_t n) { - const std::size_t used = static_cast(m_pos - m_out.data()); + const auto used = static_cast(m_pos - m_out.data()); m_out.resize((std::max)(m_out.size() * 2, used + n + 256)); m_pos = &m_out[0] + used; m_end = &m_out[0] + m_out.size(); } StringType& m_out; - char* m_pos = nullptr; - char* m_end = nullptr; + char* m_pos; + char* m_end; }; /// how the view's dump() writes a value @@ -318,8 +322,15 @@ class view_serializer std::size_t i = 0; while (i < n) { - const std::size_t run = EnsureAscii ? (is_ascii_copyable(s[i]) ? find_ascii_copyable_run(s + i, n - i) : 0) - : string_bulk_run(s + i, n - i); + std::size_t run = 0; + if (!EnsureAscii) + { + run = string_bulk_run(s + i, n - i); + } + else if (is_ascii_copyable(s[i])) + { + run = find_ascii_copyable_run(s + i, n - i); + } if (run != 0) { m_out.put(reinterpret_cast(s + i), run); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) @@ -330,7 +341,11 @@ class view_serializer std::size_t len = 1; if (codepoint >= 0xC0) { - len = codepoint >= 0xF0 ? 4 : (codepoint >= 0xE0 ? 3 : 2); + len = 2; + if (codepoint >= 0xE0) + { + len = codepoint >= 0xF0 ? 4 : 3; + } codepoint &= 0xFFu >> (len + 1); for (std::size_t k = 1; k < len; ++k) { diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index 8a27f8810..f7b68df76 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -2603,12 +2603,10 @@ class output_buffer { public: output_buffer(StringType& out, std::size_t estimate) - : m_out(out) - { - m_out.resize((std::max)(estimate, static_cast(64))); - m_pos = &m_out[0]; - m_end = m_pos + m_out.size(); - } + : m_out(sized(out, estimate)) + , m_pos(&m_out[0]) + , m_end(m_pos + m_out.size()) + {} void finish() { @@ -2644,17 +2642,23 @@ class output_buffer } private: + static StringType& sized(StringType& out, std::size_t estimate) + { + out.resize((std::max)(estimate, static_cast(64))); + return out; + } + NLOHMANN_VIEW_NOINLINE void grow(std::size_t n) { - const std::size_t used = static_cast(m_pos - m_out.data()); + const auto used = static_cast(m_pos - m_out.data()); m_out.resize((std::max)(m_out.size() * 2, used + n + 256)); m_pos = &m_out[0] + used; m_end = &m_out[0] + m_out.size(); } StringType& m_out; - char* m_pos = nullptr; - char* m_end = nullptr; + char* m_pos; + char* m_end; }; /// how the view's dump() writes a value @@ -2884,8 +2888,15 @@ class view_serializer std::size_t i = 0; while (i < n) { - const std::size_t run = EnsureAscii ? (is_ascii_copyable(s[i]) ? find_ascii_copyable_run(s + i, n - i) : 0) - : string_bulk_run(s + i, n - i); + std::size_t run = 0; + if (!EnsureAscii) + { + run = string_bulk_run(s + i, n - i); + } + else if (is_ascii_copyable(s[i])) + { + run = find_ascii_copyable_run(s + i, n - i); + } if (run != 0) { m_out.put(reinterpret_cast(s + i), run); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) @@ -2896,7 +2907,11 @@ class view_serializer std::size_t len = 1; if (codepoint >= 0xC0) { - len = codepoint >= 0xF0 ? 4 : (codepoint >= 0xE0 ? 3 : 2); + len = 2; + if (codepoint >= 0xE0) + { + len = codepoint >= 0xF0 ? 4 : 3; + } codepoint &= 0xFFu >> (len + 1); for (std::size_t k = 1; k < len; ++k) { diff --git a/tests/src/unit-json_view.cpp b/tests/src/unit-json_view.cpp index d49279f08..c6defd558 100644 --- a/tests/src/unit-json_view.cpp +++ b/tests/src/unit-json_view.cpp @@ -1086,7 +1086,7 @@ TEST_CASE("json_view dump") CHECK(d.root().dump(-1, ' ', false, json_view::number_format::source) == "[1.50,1E2,-0,-0.0,123456789012345678901234567890,18446744073709551615,-9223372036854775808,0.1,1e-7,5e-324]"); // random doubles, written as parse() and dump() would - std::mt19937_64 rng(1170); + std::mt19937_64 rng(1170); // NOLINT(cert-msc32-c,cert-msc51-cpp,bugprone-random-generator-seed) std::string many = "["; for (int i = 0; i < 5000; ++i) { @@ -1098,7 +1098,7 @@ TEST_CASE("json_view dump") many += (many.size() > 1 ? "," : "") + json(x).dump(); } } - many += "]"; + many += ']'; CHECK(json_document::parse(many).root().dump() == json::parse(many).dump()); using json_float = nlohmann::basic_json;