diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index 5c2689771..4b56f10c5 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -968,6 +968,9 @@ bool integral_conversion(const std::string &input, T &output) noexcept { nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end()); return integral_conversion(nstring, output); } + if(std::isspace(static_cast(input.back()))) { + return integral_conversion(trim_copy(input), output); + } if(input.compare(0, 2, "0o") == 0 || input.compare(0, 2, "0O") == 0) { val = nullptr; errno = 0; @@ -1016,13 +1019,16 @@ bool integral_conversion(const std::string &input, T &output) noexcept { output = static_cast(1); return true; } - // remove separators + // remove separators and trailing spaces if(input.find_first_of("_'") != std::string::npos) { std::string nstring = input; nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end()); nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end()); return integral_conversion(nstring, output); } + if(std::isspace(static_cast(input.back()))) { + return integral_conversion(trim_copy(input), output); + } if(input.compare(0, 2, "0o") == 0 || input.compare(0, 2, "0O") == 0) { val = nullptr; errno = 0; @@ -1147,6 +1153,13 @@ bool lexical_cast(const std::string &input, T &output) { if(val == (input.c_str() + input.size())) { return true; } + while(std::isspace(static_cast(*val))) { + ++val; + if(val == (input.c_str() + input.size())) { + return true; + } + } + // remove separators if(input.find_first_of("_'") != std::string::npos) { std::string nstring = input; diff --git a/tests/OptionTypeTest.cpp b/tests/OptionTypeTest.cpp index c30127559..212626496 100644 --- a/tests/OptionTypeTest.cpp +++ b/tests/OptionTypeTest.cpp @@ -227,9 +227,13 @@ TEST_CASE_METHOD(TApp, "atomic_int_option", "[optiontype]") { static const std::map testValuesDouble{ {"3.14159", 3.14159}, {"-3.14159", -3.14159}, + {"-3.14159\t", -3.14159}, + {"-3.14159 ", -3.14159}, {"+1.0", 1.0}, {"-0.01", -0.01}, {"5e22", 5e22}, + {" 5e22", 5e22}, + {" 5e22 ", 5e22}, {"-2E-2", -2e-2}, {"5e+22", 5e22}, {"1e06", 1e6}, @@ -268,6 +272,7 @@ static const std::map testValuesInt{ {"+99", 99}, {"99", 99}, {"-99", -99}, + {"-99 ", -99}, {"0xDEADBEEF", 0xDEADBEEF}, {"0xdeadbeef", 0xDEADBEEF}, {"0XDEADBEEF", 0xDEADBEEF}, @@ -280,6 +285,7 @@ static const std::map testValuesInt{ {"995862_262", 995862262}, {"995862262", 995862262}, {"-995862275", -995862275}, + {"\t-995862275\t", -995862275}, {"-995'862'275", -995862275}, {"0b11010110", 0xD6}, {"0b1101'0110", 0xD6}, @@ -323,6 +329,7 @@ TEST_CASE_METHOD(TApp, "intConversionsErange", "[optiontype]") { static const std::map testValuesUInt{ {"+99", 99}, {"99", 99}, + {" 99 ", 99}, {"0xDEADBEEF", 0xDEADBEEF}, {"0xdeadbeef", 0xDEADBEEF}, {"0XDEADBEEF", 0xDEADBEEF}, @@ -331,13 +338,16 @@ static const std::map testValuesUInt{ {"0xdead'beef", 0xDEADBEEF}, {"0o01234567", 001234567}, {"0o755", 0755}, + {"0o755\t", 0755}, {"0755", 0755}, {"995862_262", 995862262}, {"995862262", 995862262}, {"+995862275", +995862275}, + {"+995862275 \n\t", +995862275}, {"995'862'275", 995862275}, {"0b11010110", 0xD6}, {"0b1101'0110", 0xD6}, + {"0b1101'0110 ", 0xD6}, {"0B11010110", 0xD6}, {"0B1101'0110", 0xD6}, {"1_2_3_4_5", 12345},