// __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ (supporting code) // | | |__ | | | | | | version 3.12.0 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once #include // size_t #include // uint8_t (via json::binary_t) #include // numeric_limits #include // string, to_string #include // vector #include // the loggers are defined in this header only, so their vtables are emitted in // every test that includes it #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-vtables" #endif namespace utils { /// a SAX event consumer that records every event it receives as a /// human-readable string, used by the deserialization tests to check the /// exact sequence of SAX events a parse run produces struct SaxEventLogger : public nlohmann::json_sax { using json = nlohmann::json; bool null() override { events.emplace_back("null()"); return true; } bool boolean(bool val) override { events.emplace_back(val ? "boolean(true)" : "boolean(false)"); return true; } bool number_integer(json::number_integer_t val) override { events.push_back("number_integer(" + std::to_string(val) + ")"); return true; } bool number_unsigned(json::number_unsigned_t val) override { events.push_back("number_unsigned(" + std::to_string(val) + ")"); return true; } bool number_float(json::number_float_t /*val*/, const std::string& s) override { events.push_back("number_float(" + s + ")"); return true; } bool string(std::string& val) override { events.push_back("string(" + val + ")"); return true; } bool binary(json::binary_t& val) override { std::string binary_contents = "binary("; std::string comma_space; for (const auto b : val) { binary_contents.append(comma_space); binary_contents.append(std::to_string(static_cast(b))); comma_space = ", "; } binary_contents.append(")"); events.push_back(binary_contents); return true; } bool start_object(std::size_t elements) override { if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_object()"); } else { events.push_back("start_object(" + std::to_string(elements) + ")"); } return true; } bool key(std::string& val) override { events.push_back("key(" + val + ")"); return true; } bool end_object() override { events.emplace_back("end_object()"); return true; } bool start_array(std::size_t elements) override { if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_array()"); } else { events.push_back("start_array(" + std::to_string(elements) + ")"); } return true; } bool end_array() override { events.emplace_back("end_array()"); return true; } bool parse_error(std::size_t position, const std::string& /*last_token*/, const json::exception& /*ex*/) override { errored = true; events.push_back("parse_error(" + std::to_string(position) + ")"); return false; } std::vector events {}; // NOLINT(readability-redundant-member-init) bool errored = false; }; struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger { bool start_object(std::size_t elements) override { if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_object()"); } else { events.push_back("start_object(" + std::to_string(elements) + ")"); } return false; } }; struct SaxEventLoggerExitAfterKey : public SaxEventLogger { bool key(std::string& val) override { events.push_back("key(" + val + ")"); return false; } }; struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger { bool start_array(std::size_t elements) override { if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_array()"); } else { events.push_back("start_array(" + std::to_string(elements) + ")"); } return false; } }; } // namespace utils #if defined(__clang__) #pragma clang diagnostic pop #endif