From eabdcef5259f73d438e019ccb87909d8b92b5cdd Mon Sep 17 00:00:00 2001 From: Mathieu Westphal Date: Thu, 2 Jan 2025 21:05:32 +0100 Subject: [PATCH 1/4] format for meak --- library/public/options.h.in | 8 ++++++++ library/src/options.cxx | 10 +++++++++- library/testing/TestSDKOptionsIO.cxx | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/library/public/options.h.in b/library/public/options.h.in index d59d3a6fad..9d36a7fb9d 100644 --- a/library/public/options.h.in +++ b/library/public/options.h.in @@ -152,6 +152,14 @@ public: template [[nodiscard]] static T parse(const std::string& str); + /** + * Templated parsing method used internally to format var into strings. + * Implemented for the different supported types, + * see PARSING.md for more info. + */ + template + [[nodiscard]] static std::string format(const T& var); + /** * An exception that can be thrown by the options * when parsing of a string into an option value fails diff --git a/library/src/options.cxx b/library/src/options.cxx index 2253f779eb..b4798dfb86 100644 --- a/library/src/options.cxx +++ b/library/src/options.cxx @@ -173,9 +173,17 @@ T options::parse(const std::string& str) return options_tools::parse(str); } +//---------------------------------------------------------------------------- +template +std::string options::format(const T& var) +{ + return options_tools::format(var); +} + //---------------------------------------------------------------------------- #define F3D_DECL_TYPE_INTERNAL(TYPE) \ - template F3D_EXPORT TYPE options::parse(const std::string& str) + template F3D_EXPORT TYPE options::parse(const std::string& str); \ + template F3D_EXPORT std::string options::format(const TYPE& val) #define F3D_DECL_TYPE(TYPE) \ F3D_DECL_TYPE_INTERNAL(TYPE); \ F3D_DECL_TYPE_INTERNAL(std::vector) diff --git a/library/testing/TestSDKOptionsIO.cxx b/library/testing/TestSDKOptionsIO.cxx index 0ad80e9460..defc34e526 100644 --- a/library/testing/TestSDKOptionsIO.cxx +++ b/library/testing/TestSDKOptionsIO.cxx @@ -26,6 +26,18 @@ class ParsingTest : public PseudoUnitTest PseudoUnitTest::expect( label + " `" + input + "`", [&]() { std::ignore = f3d::options::parse(input); }); } + + template + void format(const std::string& label, const T& input, const std::string& expected) + { + PseudoUnitTest::operator()(label + " `" + std::to_string(input) + "`", [&]() { + const std::string actual = f3d::options::format(input); + if (actual != expected) + { + throw this->comparisonMessage(actual, expected, "!="); + } + }); + } }; int TestSDKOptionsIO(int argc, char* argv[]) @@ -42,6 +54,9 @@ int TestSDKOptionsIO(int argc, char* argv[]) test.parse("bool", "0", false); test.parse_expect("invalid bool", "foo"); + test.format("bool", true, "true"); + test.format("bool", false, "false"); + test.parse("int", "123", 123); test.parse("int", "-123", -123); test.parse("int", "+123", +123); From 3f65d55cece5d760ae6f8ca1e21281390f7a9824 Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Thu, 2 Jan 2025 21:31:09 +0100 Subject: [PATCH 2/4] fix --- library/private/options_tools.h.in | 37 ++++++++++++------------------ library/src/options.cxx | 2 +- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/library/private/options_tools.h.in b/library/private/options_tools.h.in index 30ae3ac09d..ab457d8b9a 100644 --- a/library/private/options_tools.h.in +++ b/library/private/options_tools.h.in @@ -194,26 +194,23 @@ std::string parse(const std::string& str) // TODO Improve string generation //---------------------------------------------------------------------------- /** - * Generic templated string generation from provided value - * rely on std::to_string + * Format provided var into a string from provided boolean + * using boolalpha formatting, eg: "true" or "false" */ -template -std::string format(const T& var) +std::string format(bool var) { - return std::to_string(var); + std::stringstream stream; + stream << std::boolalpha << var; + return stream.str(); } //---------------------------------------------------------------------------- /** - * Format provided var into a string from provided boolean - * using boolalpha formatting, eg: "true" or "false" + * Format provided var into a string from provided int */ -template<> -std::string format(const bool& var) +std::string format(int var) { - std::stringstream stream; - stream << std::boolalpha << var; - return stream.str(); + return std::to_string(var); } //---------------------------------------------------------------------------- @@ -221,8 +218,7 @@ std::string format(const bool& var) * Format provided var into a string from provided double * using ostringstream with std::noshowpoint */ -template<> -std::string format(const double& var) +std::string format(double var) { std::ostringstream stream; stream << std::noshowpoint << var; @@ -234,19 +230,16 @@ std::string format(const double& var) * Format provided var into a string from provided ratio_t * rely on format(double&) */ -template<> -std::string format(const ratio_t& var) +std::string format(ratio_t var) { // TODO generate a proper ratio string - double val = var; - return options_tools::format(val); + return options_tools::format(static_cast(var)); } //---------------------------------------------------------------------------- /** * Generate (returns) a string from provided string */ -template<> std::string format(const std::string& var) { return var; @@ -257,12 +250,12 @@ std::string format(const std::string& var) * Format provided var into a string from provided double vector * rely on format(double&) and add `, ` between the double values */ -template<> -std::string format(const std::vector& var) +template +std::string format(const std::vector& var) { std::ostringstream stream; unsigned int i = 0; - for (auto& elem : var) + for (const T& elem : var) { stream << ((i > 0) ? "," : "") << options_tools::format(elem); i++; diff --git a/library/src/options.cxx b/library/src/options.cxx index b4798dfb86..517147eff6 100644 --- a/library/src/options.cxx +++ b/library/src/options.cxx @@ -177,7 +177,7 @@ T options::parse(const std::string& str) template std::string options::format(const T& var) { - return options_tools::format(var); + return options_tools::format(var); } //---------------------------------------------------------------------------- From d48e6bfd5a92f420f739aa252d831d230180245c Mon Sep 17 00:00:00 2001 From: Mathieu Westphal Date: Thu, 2 Jan 2025 22:51:00 +0100 Subject: [PATCH 3/4] adding testing --- library/testing/TestSDKOptionsIO.cxx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/library/testing/TestSDKOptionsIO.cxx b/library/testing/TestSDKOptionsIO.cxx index defc34e526..6cd672f30f 100644 --- a/library/testing/TestSDKOptionsIO.cxx +++ b/library/testing/TestSDKOptionsIO.cxx @@ -11,7 +11,7 @@ class ParsingTest : public PseudoUnitTest template void parse(const std::string& label, const std::string& input, const T& expected) { - PseudoUnitTest::operator()(label + " `" + input + "`", [&]() { + PseudoUnitTest::operator()("parse: " + label + " `" + input + "`", [&]() { const T actual = f3d::options::parse(input); if (actual != expected) { @@ -24,13 +24,13 @@ class ParsingTest : public PseudoUnitTest void parse_expect(const std::string& label, const std::string& input) { PseudoUnitTest::expect( - label + " `" + input + "`", [&]() { std::ignore = f3d::options::parse(input); }); + "parse exception: " + label + " `" + input + "`", [&]() { std::ignore = f3d::options::parse(input); }); } template void format(const std::string& label, const T& input, const std::string& expected) { - PseudoUnitTest::operator()(label + " `" + std::to_string(input) + "`", [&]() { + PseudoUnitTest::operator()("format: " + label + " `" + expected + "`", [&]() { const std::string actual = f3d::options::format(input); if (actual != expected) { @@ -64,15 +64,21 @@ int TestSDKOptionsIO(int argc, char* argv[]) test.parse_expect("invalid int", "abc"); test.parse_expect("invalid int", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + test.format("int", 123, "123"); + test.format("int", -123, "-123"); test.parse("double", "123", 123.0); test.parse("double", "-123.45", -123.45); test.parse("double", "+1e-3", 0.001); test.parse_expect("invalid double", "1.2.3"); test.parse_expect("invalid double", "abc"); + test.format("double", 0.001, "0.001"); + test.format("double", -123.45, "-123.45"); test.parse("std::string", "foobar", "foobar"); test.parse("std::string", " foobar ", "foobar"); + test.format("std::string", "foobar", "foobar"); + test.format("std::string", " foobar ", " foobar "); test.parse("ratio_t", "0.1234", 0.1234); test.parse("ratio_t", "12.34%", 0.1234); @@ -81,13 +87,21 @@ int TestSDKOptionsIO(int argc, char* argv[]) test.parse_expect("invalid ratio_t", "12.34&"); test.parse("ratio_t", "-2/-3.5", 2.0 / 3.5); test.parse_expect("invalid ratio_t", "1/2/3"); + test.format("ratio_t", .1234, "0.1234"); test.parse>("std::vector", "1, 2, 3", { 1, 2, 3 }); + test.parse>("std::vector", "1,2,3", { 1, 2, 3 }); + test.format>("std::vector", { 1, 2, 3 }, "1,2,3"); + test.parse>("std::vector", "0.1,0.2,0.3", { 0.1, 0.2, 0.3 }); test.parse>("std::vector", " 0.1, 0.2 , 0.3 ", { 0.1, 0.2, 0.3 }); + test.format>("std::vector", { 0.1, 0.2, 0.3 }, "0.1,0.2,0.3"); + test.parse>( + "std::vector", "foo,bar,baz", { "foo", "bar", "baz" }); test.parse>( "std::vector", " foo, bar , baz ", { "foo", "bar", "baz" }); + test.format>("std::vector", { "foo", "bar", "baz" }, "foo,bar,baz"); return test.result(); } From 963ae84cde074fd8bb76104616bf29dcecd15325 Mon Sep 17 00:00:00 2001 From: Mathieu Westphal Date: Thu, 2 Jan 2025 22:55:20 +0100 Subject: [PATCH 4/4] fixup --- library/testing/TestSDKOptionsIO.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/testing/TestSDKOptionsIO.cxx b/library/testing/TestSDKOptionsIO.cxx index 6cd672f30f..7077255ccf 100644 --- a/library/testing/TestSDKOptionsIO.cxx +++ b/library/testing/TestSDKOptionsIO.cxx @@ -23,8 +23,8 @@ class ParsingTest : public PseudoUnitTest template void parse_expect(const std::string& label, const std::string& input) { - PseudoUnitTest::expect( - "parse exception: " + label + " `" + input + "`", [&]() { std::ignore = f3d::options::parse(input); }); + PseudoUnitTest::expect("parse exception: " + label + " `" + input + "`", + [&]() { std::ignore = f3d::options::parse(input); }); } template @@ -101,7 +101,8 @@ int TestSDKOptionsIO(int argc, char* argv[]) "std::vector", "foo,bar,baz", { "foo", "bar", "baz" }); test.parse>( "std::vector", " foo, bar , baz ", { "foo", "bar", "baz" }); - test.format>("std::vector", { "foo", "bar", "baz" }, "foo,bar,baz"); + test.format>( + "std::vector", { "foo", "bar", "baz" }, "foo,bar,baz"); return test.result(); }