Make SAX output locale-independent (#4505)

* 🐛 make SAX output locale-independent #4084

*  add test

*  add test

*  add test

*  add test

*  add test

*  add test

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084

* 🐛 make SAX output locale-independent #4084
This commit is contained in:
Niels Lohmann
2024-11-24 21:14:00 +01:00
committed by GitHub
parent a97041a98f
commit ee32bfc1c2
4 changed files with 190 additions and 3 deletions

View File

@@ -0,0 +1,161 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.3
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <clocale>
struct ParserImpl final: public nlohmann::json_sax<json>
{
bool null() override
{
return true;
}
bool boolean(bool /*val*/) override
{
return true;
}
bool number_integer(json::number_integer_t /*val*/) override
{
return true;
}
bool number_unsigned(json::number_unsigned_t /*val*/) override
{
return true;
}
bool number_float(json::number_float_t /*val*/, const json::string_t& s) override
{
float_string_copy = s;
return true;
}
bool string(json::string_t& /*val*/) override
{
return true;
}
bool binary(json::binary_t& /*val*/) override
{
return true;
}
bool start_object(std::size_t /*val*/) override
{
return true;
}
bool key(json::string_t& /*val*/) override
{
return true;
}
bool end_object() override
{
return true;
}
bool start_array(std::size_t /*val*/) override
{
return true;
}
bool end_array() override
{
return true;
}
bool parse_error(std::size_t /*val*/, const std::string& /*val*/, const nlohmann::detail::exception& /*val*/) override
{
return false;
}
~ParserImpl() override;
ParserImpl()
: float_string_copy("not set")
{}
ParserImpl(const ParserImpl& other)
: float_string_copy(other.float_string_copy)
{}
ParserImpl(ParserImpl&& other) noexcept
: float_string_copy(std::move(other.float_string_copy))
{}
ParserImpl& operator=(const ParserImpl& other)
{
if (this != &other)
{
float_string_copy = other.float_string_copy;
}
return *this;
}
ParserImpl& operator=(ParserImpl&& other) noexcept
{
if (this != &other)
{
float_string_copy = std::move(other.float_string_copy);
}
return *this;
}
json::string_t float_string_copy;
};
ParserImpl::~ParserImpl() = default;
TEST_CASE("locale-dependent test (LC_NUMERIC=C)")
{
WARN_MESSAGE(std::setlocale(LC_NUMERIC, "C") != nullptr, "could not set locale");
SECTION("check if locale is properly set")
{
std::array<char, 6> buffer = {};
CHECK(std::snprintf(buffer.data(), buffer.size(), "%.2f", 12.34) == 5); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
CHECK(std::string(buffer.data()) == "12.34");
}
SECTION("parsing")
{
CHECK(json::parse("12.34").dump() == "12.34");
}
SECTION("SAX parsing")
{
ParserImpl sax {};
json::sax_parse( "12.34", &sax );
CHECK(sax.float_string_copy == "12.34");
}
}
TEST_CASE("locale-dependent test (LC_NUMERIC=de_DE)")
{
if (std::setlocale(LC_NUMERIC, "de_DE") != nullptr)
{
SECTION("check if locale is properly set")
{
std::array<char, 6> buffer = {};
CHECK(std::snprintf(buffer.data(), buffer.size(), "%.2f", 12.34) == 5); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
CHECK(std::string(buffer.data()) == "12,34");
}
SECTION("parsing")
{
CHECK(json::parse("12.34").dump() == "12.34");
}
SECTION("SAX parsing")
{
ParserImpl sax{};
json::sax_parse("12.34", &sax);
CHECK(sax.float_string_copy == "12.34");
}
}
else
{
MESSAGE("locale de_DE is not usable");
}
}