diff --git a/tests/NewParseTest.cpp b/tests/NewParseTest.cpp index f6e5f73..5776018 100644 --- a/tests/NewParseTest.cpp +++ b/tests/NewParseTest.cpp @@ -341,6 +341,101 @@ TEST_F(TApp, custom_string_converterFail) { EXPECT_THROW(run(), CLI::ConversionError); } +<<<<<<< HEAD +======= +// an example of custom complex number converter that can be used to add new parsing options +#if defined(__has_include) +#if __has_include() +// an example of custom converter that can be used to add new parsing options +#define HAS_REGEX_INCLUDE +#endif +#endif + +#ifdef HAS_REGEX_INCLUDE +// Gcc 4.8 and older and the corresponding standard libraries have a broken so this would +// fail. And if a clang compiler is using libstd++ then this will generate an error as well so this is just a check to +// simplify compilation and prevent a much more complicated #if expression +#include // NOLINT(build/c++11) +namespace CLI { +namespace detail { + +// On MSVC and possibly some other new compilers this can be a free standing function without the template +// specialization but this is compiler dependent +template <> bool lexical_cast>(const std::string &input, std::complex &output) { + // regular expression to handle complex numbers of various formats + static const std::regex creg( + R"(([+-]?(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?)\s*([+-]\s*(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?)[ji]*)"); + + std::smatch m; + double x{0.0}, y{0.0}; + bool worked; + std::regex_search(input, m, creg); + if(m.size() == 9) { + worked = CLI::detail::lexical_cast(m[1], x) && CLI::detail::lexical_cast(m[6], y); + if(worked) { + if(*m[5].first == '-') { + y = -y; + } + } + } else { + if((input.back() == 'j') || (input.back() == 'i')) { + auto strval = input.substr(0, input.size() - 1); + CLI::detail::trim(strval); + worked = CLI::detail::lexical_cast(strval, y); + } else { + std::string ival = input; + CLI::detail::trim(ival); + worked = CLI::detail::lexical_cast(ival, x); + } + } + if(worked) { + output = cx{x, y}; + } + return worked; +} +} // namespace detail +} // namespace CLI + +TEST_F(TApp, AddingComplexParserDetail) { + + bool skip_tests = false; + try { // check if the library actually supports regex, it is possible to link against a non working regex in the + // standard library + std::smatch m; + std::string input = "1.5+2.5j"; + static const std::regex creg( + R"(([+-]?(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?)\s*([+-]\s*(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?)[ji]*)"); + + auto rsearch = std::regex_search(input, m, creg); + if(!rsearch) { + skip_tests = true; + } else { + EXPECT_EQ(m.size(), 9u); + } + + } catch(...) { + skip_tests = true; + } + if(!skip_tests) { + cx comp{0, 0}; + app.add_option("-c,--complex", comp, "add a complex number option"); + args = {"-c", "1.5+2.5j"}; + + run(); + + EXPECT_DOUBLE_EQ(1.5, comp.real()); + EXPECT_DOUBLE_EQ(2.5, comp.imag()); + args = {"-c", "1.5-2.5j"}; + + run(); + + EXPECT_DOUBLE_EQ(1.5, comp.real()); + EXPECT_DOUBLE_EQ(-2.5, comp.imag()); + } +} +#endif + +>>>>>>> Do not lint chrono, thread, and regex /// simple class to wrap another with a very specific type constructor and assignment operators to test out some of the /// option assignments template class objWrapper { diff --git a/tests/TimerTest.cpp b/tests/TimerTest.cpp index 51d8bb0..51dbfc4 100644 --- a/tests/TimerTest.cpp +++ b/tests/TimerTest.cpp @@ -7,10 +7,10 @@ #include "CLI/Timer.hpp" #include "gmock/gmock.h" #include "gtest/gtest.h" -#include +#include // NOLINT(build/c++11) #include #include -#include +#include // NOLINT(build/c++11) using ::testing::HasSubstr;