From a18d3f4ee6cfafed938e81e95e7289773f4baa5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C4=81rlis=20Se=C5=86ko?= Date: Mon, 4 Aug 2025 21:59:51 +0300 Subject: [PATCH] Use locale independent double parser for units.xml --- src/util/units.cpp | 16 ++++---- testfiles/src/test-utils.h | 63 +++++++++++++++++++++++++++++++ testfiles/src/util-units-test.cpp | 23 ++++++++++- 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/util/units.cpp b/src/util/units.cpp index fea10ab37b..ebb7f384db 100644 --- a/src/util/units.cpp +++ b/src/util/units.cpp @@ -7,21 +7,22 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -#include +#include "util/units.h" + #include +#include #include #include -#include #include +#include #include -#include #include #include - +#include +#include #include <2geom/coord.h> #include "io/resource.h" -#include "util/units.h" #include "path-prefix.h" #include "streq.h" #include "util-string/ustring-format.h" @@ -508,12 +509,11 @@ void UnitParser::on_text(Ctx &ctx, Glib::ustring const &text) } else if (element == "abbr") { unit.abbr = text; } else if (element == "factor") { - // TODO make sure we use the right conversion - unit.factor = std::stod(text.raw()); + unit.factor = Glib::Ascii::strtod(text); } else if (element == "description") { unit.description = text; } else if (element == "tic" && metric) { - auto tic = std::stod(text.raw()); + auto tic = Glib::Ascii::strtod(text); metric->ruler_scale.push_back(tic); if (is_div) { metric->subdivide.push_back(tic); diff --git a/testfiles/src/test-utils.h b/testfiles/src/test-utils.h index 874266b65e..5f5d608971 100644 --- a/testfiles/src/test-utils.h +++ b/testfiles/src/test-utils.h @@ -84,6 +84,69 @@ inline static std::vector random_values(unsigned ccount) return values; } +/** Locale testing fixture. + * + * This fixture only creates a locale, it is test responsibility to use it. + * \code{.cpp} + * class FooTestFixture : public LocaleTestFixture {}; + * TEST_P(FooTestFixture, Test1) + * { + * std::sstream stream("1.32"); + * stream.imbue(locale); + * float v; + * stream >> v; + * } + * TEST_P(FooTestFixture, Test2) { .. } + * INSTANTIATE_TEST_SUITE_P(TestSuite, + * FooTestFixture, + * testing::Values("C", "de_DE.UTF8")); + * \endcode + */ +class LocaleTestFixture : public ::testing::TestWithParam +{ +protected: + std::locale locale; + + void SetUp() override { locale = std::locale(GetParam()); } +}; + +/** Global locale testing fixture. + * + * Parametrized test fixtures which automatically sets up and restores global locale. + * \code{.cpp} + * class FooTestFixture : public GlobalLocaleTestFixture {}; + * TEST_P(FooTestFixture, Test1) + * { + * test_logic + * } + * TEST_P(FooTestFixture, Test2) { .. } + * INSTANTIATE_TEST_SUITE_P(TestSuite, + * FooTestFixture, + * testing::Values("C", "de_DE.UTF8")); + * \endcode + */ +class GlobalLocaleTestFixture : public LocaleTestFixture +{ + std::locale backup; + +protected: + void SetUp() override + { + try { + LocaleTestFixture::SetUp(); + } catch (std::exception const &e) { + GTEST_SKIP() << "Skipping locale '" << GetParam() << "' not available\n"; + } + backup = std::locale::global(locale); + } + + void TearDown() override + { + LocaleTestFixture::TearDown(); + std::locale::global(backup); + } +}; + } // namespace /* diff --git a/testfiles/src/util-units-test.cpp b/testfiles/src/util-units-test.cpp index ecf40aa80e..b6855be719 100644 --- a/testfiles/src/util-units-test.cpp +++ b/testfiles/src/util-units-test.cpp @@ -7,10 +7,10 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -#include - #include +#include +#include "test-utils.h" #include "util/units.h" namespace { @@ -86,6 +86,25 @@ TEST(UtilUnitsTest, UnitMetricGet) } } +class UnitLocale : public GlobalLocaleTestFixture +{ +}; + +TEST_P(UnitLocale, UnitScale) +{ + UnitTable units; + auto mm = units.getUnit("mm"); + auto inch = units.getUnit("in"); + EXPECT_NE(mm, nullptr); + EXPECT_NE(inch, nullptr); + ASSERT_DOUBLE_EQ(25.4, inch->convert(1, mm)); + + auto cm = units.getUnit("cm"); + EXPECT_NE(cm, nullptr); + ASSERT_DOUBLE_EQ(10, cm->convert(1, mm)); +} + +INSTANTIATE_TEST_SUITE_P(UtilUnitsTest, UnitLocale, testing::Values("C", "de_DE.UTF8")); } // namespace -- GitLab