From 7795b6a47b7af268ed64ce901fa1f2d9f1bee6d3 Mon Sep 17 00:00:00 2001 From: Nigel Stewart Date: Tue, 14 Jan 2025 16:56:41 +1000 Subject: [PATCH] C++17 std::filesystem::path support added (#447) --- include/cxxopts.hpp | 15 +++++++++ test/options.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index 2819f50..63d140d 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -73,6 +73,12 @@ THE SOFTWARE. # define CXXOPTS_HAS_OPTIONAL # endif # endif +# if __has_include() +# include +# ifdef __cpp_lib_filesystem +# define CXXOPTS_HAS_FILESYSTEM +# endif +# endif #endif #define CXXOPTS_FALLTHROUGH @@ -1074,6 +1080,15 @@ parse_value(const std::string& text, std::optional& value) } #endif +#ifdef CXXOPTS_HAS_FILESYSTEM +inline +void +parse_value(const std::string& text, std::filesystem::path& value) +{ + value.assign(text); +} +#endif + inline void parse_value(const std::string& text, char& c) { diff --git a/test/options.cpp b/test/options.cpp index 8b99a5b..843f4ae 100644 --- a/test/options.cpp +++ b/test/options.cpp @@ -732,6 +732,27 @@ TEST_CASE("std::optional", "[optional]") { } #endif +#ifdef CXXOPTS_HAS_FILESYSTEM +TEST_CASE("std::filesystem::path", "[path]") { + std::filesystem::path path; + cxxopts::Options options("path", " - tests path"); + options.add_options() + ("path", "a path", cxxopts::value(path)); + + Argv av({"path", "--path", "Hello World.txt"}); + + auto** argv = av.argv(); + auto argc = av.argc(); + + REQUIRE(path.empty()); + + options.parse(argc, argv); + + REQUIRE(!path.empty()); + CHECK(path == "Hello World.txt"); +} +#endif + TEST_CASE("Unrecognised options", "[options]") { cxxopts::Options options("unknown_options", " - test unknown options"); @@ -877,6 +898,60 @@ TEST_CASE("Optional value", "[optional]") } #endif +#ifdef CXXOPTS_HAS_OPTIONAL +TEST_CASE("std::filesystem::path value", "[path]") +{ + cxxopts::Options options("options", "query as std::fileystem::path"); + options.add_options() + ("a", "Path", cxxopts::value()) + ("b", "Path", cxxopts::value()) + ("c", "Path", cxxopts::value()) + ("d", "Path", cxxopts::value()) + ("e", "Path", cxxopts::value()) + ; + + SECTION("Available") { + Argv av({ + "available", + "-a", "hello.txt", + "-b", "C:\\Users\\JoeCitizen\\hello world.txt", + "-c", "/home/joecitzen/hello world.txt", + "-d", "../world.txt" + }); + + auto** argv = av.argv(); + auto argc = av.argc(); + + auto result = options.parse(argc, argv); + + CHECK(result.as_optional("a")); + CHECK(result.as_optional("b")); + CHECK(result.as_optional("c")); + CHECK(result.as_optional("d")); + CHECK(!result.as_optional("e")); + + CHECK(result.as_optional("a") == "hello.txt"); + CHECK(result.as_optional("b") == "C:\\Users\\JoeCitizen\\hello world.txt"); + CHECK(result.as_optional("c") == "/home/joecitzen/hello world.txt"); + CHECK(result.as_optional("d") == "../world.txt"); + } + + SECTION("Unavailable") { + Argv av({ + "unavailable" + }); + + auto** argv = av.argv(); + auto argc = av.argc(); + + auto result = options.parse(argc, argv); + + CHECK(!result.as_optional("a")); + } + +} +#endif + TEST_CASE("Initializer list with group", "[options]") { cxxopts::Options options("Initializer list group", " - test initializer list with group");