diff --git a/lib/thirdparty/CLI11.hpp b/lib/thirdparty/CLI11.hpp index 739fd8bd..3913fa9c 100644 --- a/lib/thirdparty/CLI11.hpp +++ b/lib/thirdparty/CLI11.hpp @@ -1,11 +1,11 @@ -// CLI11: Version 2.3.1 +// CLI11: Version 2.3.2 // Originally designed by Henry Schreiner // https://github.com/CLIUtils/CLI11 // // This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts -// from: v2.3.1 +// from: v2.3.2 // -// CLI11 2.3.1 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry +// CLI11 2.3.2 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry // Schreiner under NSF AWARD 1414736. All rights reserved. // // Redistribution and use in source and binary forms of CLI11, with or without @@ -34,34 +34,34 @@ #pragma once // Standard combined includes: -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include -#include +#include +#include +#include #include +#include +#include #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include #define CLI11_VERSION_MAJOR 2 #define CLI11_VERSION_MINOR 3 -#define CLI11_VERSION_PATCH 1 -#define CLI11_VERSION "2.3.1" +#define CLI11_VERSION_PATCH 2 +#define CLI11_VERSION "2.3.2" @@ -972,7 +972,9 @@ constexpr enabler dummy = {}; template using enable_if_t = typename std::enable_if::type; /// A copy of std::void_t from C++17 (helper for C++11 and C++14) -template struct make_void { using type = void; }; +template struct make_void { + using type = void; +}; /// A copy of std::void_t from C++17 - same reasoning as enable_if_t, it does not hurt to redefine template using void_t = typename make_void::type; @@ -1001,10 +1003,14 @@ template struct is_copyable_ptr { }; /// This can be specialized to override the type deduction for IsMember. -template struct IsMemberType { using type = T; }; +template struct IsMemberType { + using type = T; +}; /// The main custom type needed here is const char * should be a string. -template <> struct IsMemberType { using type = std::string; }; +template <> struct IsMemberType { + using type = std::string; +}; namespace detail { @@ -1014,7 +1020,9 @@ namespace detail { /// pointer_traits be valid. /// not a pointer -template struct element_type { using type = T; }; +template struct element_type { + using type = T; +}; template struct element_type::value>::type> { using type = typename std::pointer_traits::element_type; @@ -1022,7 +1030,9 @@ template struct element_type struct element_value_type { using type = typename element_type::type::value_type; }; +template struct element_value_type { + using type = typename element_type::type::value_type; +}; /// Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost nothing. template struct pair_adaptor : std::false_type { @@ -1283,7 +1293,9 @@ auto value_string(const T &value) -> decltype(to_string(value)) { } /// template to get the underlying value type if it exists or use a default -template struct wrapped_type { using type = def; }; +template struct wrapped_type { + using type = def; +}; /// Type size for regular object types that do not look like a tuple template struct wrapped_type::value>::type> { @@ -1291,7 +1303,9 @@ template struct wrapped_type struct type_count_base { static const int value{0}; }; +template struct type_count_base { + static const int value{0}; +}; /// Type size for regular object types that do not look like a tuple template @@ -1321,7 +1335,9 @@ template struct subtype_count; template struct subtype_count_min; /// This will only trigger for actual void type -template struct type_count { static const int value{0}; }; +template struct type_count { + static const int value{0}; +}; /// Type size for regular object types that do not look like a tuple template @@ -1372,7 +1388,9 @@ template struct subtype_count { }; /// This will only trigger for actual void type -template struct type_count_min { static const int value{0}; }; +template struct type_count_min { + static const int value{0}; +}; /// Type size for regular object types that do not look like a tuple template @@ -1421,7 +1439,9 @@ template struct subtype_count_min { }; /// This will only trigger for actual void type -template struct expected_count { static const int value{0}; }; +template struct expected_count { + static const int value{0}; +}; /// For most types the number of expected items is 1 template @@ -1725,11 +1745,15 @@ inline std::string type_name() { /// Convert to an unsigned integral template ::value, detail::enabler> = detail::dummy> bool integral_conversion(const std::string &input, T &output) noexcept { - if(input.empty()) { + if(input.empty() || input.front() == '-') { return false; } char *val = nullptr; + errno = 0; std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); + if(errno == ERANGE) { + return false; + } output = static_cast(output_ll); if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { return true; @@ -1750,7 +1774,11 @@ bool integral_conversion(const std::string &input, T &output) noexcept { return false; } char *val = nullptr; + errno = 0; std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); + if(errno == ERANGE) { + return false; + } output = static_cast(output_ll); if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { return true; @@ -1867,18 +1895,18 @@ bool lexical_cast(const std::string &input, T &output) { bool worked = false; auto nloc = str1.find_last_of("+-"); if(nloc != std::string::npos && nloc > 0) { - worked = detail::lexical_cast(str1.substr(0, nloc), x); + worked = lexical_cast(str1.substr(0, nloc), x); str1 = str1.substr(nloc); if(str1.back() == 'i' || str1.back() == 'j') str1.pop_back(); - worked = worked && detail::lexical_cast(str1, y); + worked = worked && lexical_cast(str1, y); } else { if(str1.back() == 'i' || str1.back() == 'j') { str1.pop_back(); - worked = detail::lexical_cast(str1, y); + worked = lexical_cast(str1, y); x = XC{0}; } else { - worked = detail::lexical_cast(str1, x); + worked = lexical_cast(str1, x); y = XC{0}; } } @@ -2099,7 +2127,7 @@ template = detail::dummy> bool lexical_assign(const std::string &input, AssignTo &output) { ConvertTo val{}; - bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; + bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; if(parse_result) { output = val; } @@ -2115,7 +2143,7 @@ template < detail::enabler> = detail::dummy> bool lexical_assign(const std::string &input, AssignTo &output) { ConvertTo val{}; - bool parse_result = input.empty() ? true : lexical_cast(input, val); + bool parse_result = input.empty() ? true : lexical_cast(input, val); if(parse_result) { output = AssignTo(val); // use () form of constructor to allow some implicit conversions } @@ -2193,7 +2221,7 @@ bool lexical_conversion(const std::vector &strings, AssignTo &outpu if(str1.back() == 'i' || str1.back() == 'j') { str1.pop_back(); } - auto worked = detail::lexical_cast(strings[0], x) && detail::lexical_cast(str1, y); + auto worked = lexical_cast(strings[0], x) && lexical_cast(str1, y); if(worked) { output = ConvertTo{x, y}; } @@ -2457,7 +2485,7 @@ inline std::string sum_string_vector(const std::vector &values) { std::string output; for(const auto &arg : values) { double tv{0.0}; - auto comp = detail::lexical_cast(arg, tv); + auto comp = lexical_cast(arg, tv); if(!comp) { try { tv = static_cast(detail::to_flag_value(arg)); @@ -2475,8 +2503,7 @@ inline std::string sum_string_vector(const std::vector &values) { } else { if(val <= static_cast((std::numeric_limits::min)()) || val >= static_cast((std::numeric_limits::max)()) || - // NOLINTNEXTLINE(clang-diagnostic-float-equal,bugprone-narrowing-conversions) - val == static_cast(val)) { + std::ceil(val) == std::floor(val)) { output = detail::value_string(static_cast(val)); } else { output = detail::value_string(val); @@ -2998,8 +3025,9 @@ template class TypeValidator : public Validator { public: explicit TypeValidator(const std::string &validator_name) : Validator(validator_name, [](std::string &input_string) { + using CLI::detail::lexical_cast; auto val = DesiredType(); - if(!detail::lexical_cast(input_string, val)) { + if(!lexical_cast(input_string, val)) { return std::string("Failed parsing ") + input_string + " as a " + detail::type_name(); } return std::string(); @@ -3033,8 +3061,9 @@ class Range : public Validator { } func_ = [min_val, max_val](std::string &input) { + using CLI::detail::lexical_cast; T val; - bool converted = detail::lexical_cast(input, val); + bool converted = lexical_cast(input, val); if((!converted) || (val < min_val || val > max_val)) { std::stringstream out; out << "Value " << input << " not in range ["; @@ -3070,8 +3099,9 @@ class Bound : public Validator { description(out.str()); func_ = [min_val, max_val](std::string &input) { + using CLI::detail::lexical_cast; T val; - bool converted = detail::lexical_cast(input, val); + bool converted = lexical_cast(input, val); if(!converted) { return std::string("Value ") + input + " could not be converted"; } @@ -3262,8 +3292,9 @@ class IsMember : public Validator { // This is the function that validates // It stores a copy of the set pointer-like, so shared_ptr will stay alive func_ = [set, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; local_item_t b; - if(!detail::lexical_cast(input, b)) { + if(!lexical_cast(input, b)) { throw ValidationError(input); // name is added later } if(filter_fn) { @@ -3330,8 +3361,9 @@ class Transformer : public Validator { desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); }; func_ = [mapping, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; local_item_t b; - if(!detail::lexical_cast(input, b)) { + if(!lexical_cast(input, b)) { return std::string(); // there is no possible way we can match anything in the mapping if we can't convert so just return } @@ -3399,8 +3431,9 @@ class CheckedTransformer : public Validator { desc_function_ = tfunc; func_ = [mapping, tfunc, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; local_item_t b; - bool converted = detail::lexical_cast(input, b); + bool converted = lexical_cast(input, b); if(converted) { if(filter_fn) { b = filter_fn(b); @@ -3502,7 +3535,8 @@ class AsNumberWithUnit : public Validator { unit = detail::to_lower(unit); } if(unit.empty()) { - if(!detail::lexical_cast(input, num)) { + using CLI::detail::lexical_cast; + if(!lexical_cast(input, num)) { throw ValidationError(std::string("Value ") + input + " could not be converted to " + detail::type_name()); } @@ -3520,7 +3554,8 @@ class AsNumberWithUnit : public Validator { } if(!input.empty()) { - bool converted = detail::lexical_cast(input, num); + using CLI::detail::lexical_cast; + bool converted = lexical_cast(input, num); if(!converted) { throw ValidationError(std::string("Value ") + input + " could not be converted to " + detail::type_name()); @@ -3829,7 +3864,8 @@ CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") { } int num = 0; for(const auto &var : result) { - bool retval = detail::lexical_cast(var, num); + using CLI::detail::lexical_cast; + bool retval = lexical_cast(var, num); if(!retval) { return std::string("Failed parsing number (") + var + ')'; } @@ -5548,8 +5584,11 @@ struct AppFriend; } // namespace detail namespace FailureMessage { -std::string simple(const App *app, const Error &e); -std::string help(const App *app, const Error &e); +/// Printout a clean, simple message on error (the default in CLI11 1.5+) +CLI11_INLINE std::string simple(const App *app, const Error &e); + +/// Printout the full help string on error (if this fn is set, the old default for CLI11) +CLI11_INLINE std::string help(const App *app, const Error &e); } // namespace FailureMessage /// enumeration of modes of how to deal with extras in config files @@ -6122,7 +6161,8 @@ class App { std::string flag_description = "") { CLI::callback_t fun = [&flag_result](const CLI::results_t &res) { - return CLI::detail::lexical_cast(res[0], flag_result); + using CLI::detail::lexical_cast; + return lexical_cast(res[0], flag_result); }; auto *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description)); return detail::default_flag_modifiers(opt); @@ -6138,8 +6178,9 @@ class App { CLI::callback_t fun = [&flag_results](const CLI::results_t &res) { bool retval = true; for(const auto &elem : res) { + using CLI::detail::lexical_cast; flag_results.emplace_back(); - retval &= detail::lexical_cast(elem, flag_results.back()); + retval &= lexical_cast(elem, flag_results.back()); } return retval; }; @@ -6851,16 +6892,6 @@ CLI11_INLINE void retire_option(App *app, const std::string &option_name); /// Helper function to mark an option as retired CLI11_INLINE void retire_option(App &app, const std::string &option_name); -namespace FailureMessage { - -/// Printout a clean, simple message on error (the default in CLI11 1.5+) -CLI11_INLINE std::string simple(const App *app, const Error &e); - -/// Printout the full help string on error (if this fn is set, the old default for CLI11) -CLI11_INLINE std::string help(const App *app, const Error &e); - -} // namespace FailureMessage - namespace detail { /// This class is simply to allow tests access to App's protected functions struct AppFriend { @@ -7143,8 +7174,9 @@ CLI11_INLINE Option *App::add_flag_callback(std::string flag_name, std::string flag_description) { CLI::callback_t fun = [function](const CLI::results_t &res) { + using CLI::detail::lexical_cast; bool trigger{false}; - auto result = CLI::detail::lexical_cast(res[0], trigger); + auto result = lexical_cast(res[0], trigger); if(result && trigger) { function(); } @@ -7159,8 +7191,9 @@ App::add_flag_function(std::string flag_name, std::string flag_description) { CLI::callback_t fun = [function](const CLI::results_t &res) { + using CLI::detail::lexical_cast; std::int64_t flag_count{0}; - CLI::detail::lexical_cast(res[0], flag_count); + lexical_cast(res[0], flag_count); function(flag_count); return true; }; @@ -7544,7 +7577,7 @@ CLI11_NODISCARD CLI11_INLINE std::string App::help(std::string prev, AppFormatMo // Delegate to subcommand if needed auto selected_subcommands = get_subcommands(); if(!selected_subcommands.empty()) { - return selected_subcommands.at(0)->help(prev, mode); + return selected_subcommands.back()->help(prev, mode); } return formatter_->make_help(this, prev, mode); } @@ -8274,7 +8307,22 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t if(item.inputs.size() <= 1) { // Flag parsing auto res = config_formatter_->to_flag(item); - res = op->get_flag_value(item.name, res); + bool converted{false}; + if(op->get_disable_flag_override()) { + + try { + auto val = detail::to_flag_value(res); + if(val == 1) { + res = op->get_flag_value(item.name, "{}"); + converted = true; + } + } catch(...) { + } + } + + if(!converted) { + res = op->get_flag_value(item.name, res); + } op->add_result(res); return true; @@ -8998,8 +9046,9 @@ CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char string } // floating point conversion can convert some hex codes, but don't try that here if(arg.compare(0, 2, "0x") != 0 && arg.compare(0, 2, "0X") != 0) { + using CLI::detail::lexical_cast; double val = 0.0; - if(detail::lexical_cast(arg, val)) { + if(lexical_cast(arg, val)) { return arg; } } @@ -9420,7 +9469,7 @@ CLI11_INLINE std::string Formatter::make_description(const App *app) const { if(min_options == 1) { desc += " \n[Exactly 1 of the following options is required]"; } else { - desc += " \n[Exactly " + std::to_string(min_options) + "options from the following list are required]"; + desc += " \n[Exactly " + std::to_string(min_options) + " options from the following list are required]"; } } else if(max_options > 0) { if(min_options > 0) {