diff options
Diffstat (limited to '3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp')
-rw-r--r-- | 3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp | 279 |
1 files changed, 186 insertions, 93 deletions
diff --git a/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp index f5770f1..5314029 100644 --- a/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp @@ -7,6 +7,8 @@ #include <boost/program_options/config.hpp> #include <boost/program_options/value_semantic.hpp> #include <boost/program_options/detail/convert.hpp> +#include <boost/program_options/detail/cmdline.hpp> +#include <set> #include <cctype> @@ -14,6 +16,22 @@ namespace boost { namespace program_options { using namespace std; + +#ifndef BOOST_NO_STD_WSTRING + namespace + { + std::string convert_value(const std::wstring& s) + { + try { + return to_local_8_bit(s); + } + catch(const std::exception&) { + return "<unrepresentable unicode string>"; + } + } + } +#endif + void value_semantic_codecvt_helper<char>:: parse(boost::any& value_store, @@ -139,7 +157,7 @@ namespace boost { namespace program_options { else if (s == "off" || s == "no" || s == "0" || s == "false") v = any(false); else - boost::throw_exception(validation_error(validation_error::invalid_bool_value, s)); + boost::throw_exception(invalid_bool_value(s)); } // This is blatant copy-paste. However, templating this will cause a problem, @@ -161,7 +179,7 @@ namespace boost { namespace program_options { else if (s == L"off" || s == L"no" || s == L"0" || s == L"false") v = any(false); else - boost::throw_exception(validation_error(validation_error::invalid_bool_value)); + boost::throw_exception(invalid_bool_value(convert_value(s))); } #endif BOOST_PROGRAM_OPTIONS_DECL @@ -194,120 +212,212 @@ namespace boost { namespace program_options { invalid_option_value:: invalid_option_value(const std::string& bad_value) - : validation_error(validation_error::invalid_option_value, bad_value) - {} - -#ifndef BOOST_NO_STD_WSTRING - namespace + : validation_error(validation_error::invalid_option_value) { - std::string convert_value(const std::wstring& s) - { - try { - return to_local_8_bit(s); - } - catch(const std::exception&) { - return "<unrepresentable unicode string>"; - } - } + set_substitute("value", bad_value); } +#ifndef BOOST_NO_STD_WSTRING invalid_option_value:: invalid_option_value(const std::wstring& bad_value) - : validation_error(validation_error::invalid_option_value, convert_value(bad_value)) - {} -#endif - const std::string& - unknown_option::get_option_name() const throw() - { - return m_option_name; + : validation_error(validation_error::invalid_option_value) + { + set_substitute("value", convert_value(bad_value)); } +#endif - const std::string& - ambiguous_option::get_option_name() const throw() - { - return m_option_name; - } - - const std::vector<std::string>& - ambiguous_option::alternatives() const throw() + + + invalid_bool_value:: + invalid_bool_value(const std::string& bad_value) + : validation_error(validation_error::invalid_bool_value) { - return m_alternatives; + set_substitute("value", bad_value); } - void - multiple_values::set_option_name(const std::string& option_name) + + + + + + error_with_option_name::error_with_option_name( const std::string& template_, + const std::string& option_name, + const std::string& original_token, + int option_style) : + error(template_), + m_option_style(option_style), + m_error_template(template_) { - m_option_name = option_name; + // parameter | placeholder | value + // --------- | ----------- | ----- + set_substitute_default("canonical_option", "option '%canonical_option%'", "option"); + set_substitute_default("value", "argument ('%value%')", "argument"); + set_substitute_default("prefix", "%prefix%", ""); + m_substitutions["option"] = option_name; + m_substitutions["original_token"] = original_token; } - const std::string& - multiple_values::get_option_name() const throw() + + const char* error_with_option_name::what() const throw() { - return m_option_name; + // will substitute tokens each time what is run() + substitute_placeholders(m_error_template); + + return m_message.c_str(); } - - void - multiple_occurrences::set_option_name(const std::string& option_name) + + void error_with_option_name::replace_token(const string& from, const string& to) const { - m_option_name = option_name; + while (1) + { + std::size_t pos = m_message.find(from.c_str(), 0, from.length()); + // not found: all replaced + if (pos == std::string::npos) + return; + m_message.replace(pos, from.length(), to); + } } - const std::string& - multiple_occurrences::get_option_name() const throw() + string error_with_option_name::get_canonical_option_prefix() const { - return m_option_name; + switch (m_option_style) + { + case command_line_style::allow_dash_for_short: + return "-"; + case command_line_style::allow_slash_for_short: + return "/"; + case command_line_style::allow_long_disguise: + return "-"; + case command_line_style::allow_long: + return "--"; + case 0: + return ""; + } + throw std::logic_error("error_with_option_name::m_option_style can only be " + "one of [0, allow_dash_for_short, allow_slash_for_short, " + "allow_long_disguise or allow_long]"); } - - validation_error:: - validation_error(kind_t kind, - const std::string& option_value, - const std::string& option_name) - : error("") - , m_kind(kind) - , m_option_name(option_name) - , m_option_value(option_value) - , m_message(error_message(kind)) + + + string error_with_option_name::get_canonical_option_name() const { - if (!option_value.empty()) - { - m_message.append(std::string("'") + option_value + std::string("'")); - } + if (!m_substitutions.find("option")->second.length()) + return m_substitutions.find("original_token")->second; + + string original_token = strip_prefixes(m_substitutions.find("original_token")->second); + string option_name = strip_prefixes(m_substitutions.find("option")->second); + + // For long options, use option name + if (m_option_style == command_line_style::allow_long || + m_option_style == command_line_style::allow_long_disguise) + return get_canonical_option_prefix() + option_name; + + // For short options use first letter of original_token + if (m_option_style && original_token.length()) + return get_canonical_option_prefix() + original_token[0]; + + // no prefix + return option_name; } - void - validation_error::set_option_name(const std::string& option_name) + + void error_with_option_name::substitute_placeholders(const string& error_template) const { - m_option_name = option_name; + m_message = error_template; + std::map<std::string, std::string> substitutions(m_substitutions); + substitutions["canonical_option"] = get_canonical_option_name(); + substitutions["prefix"] = get_canonical_option_prefix(); + + + // + // replace placeholder with defaults if values are missing + // + for (map<string, string_pair>::const_iterator iter = m_substitution_defaults.begin(); + iter != m_substitution_defaults.end(); ++iter) + { + // missing parameter: use default + if (substitutions.count(iter->first) == 0 || + substitutions[iter->first].length() == 0) + replace_token(iter->second.first, iter->second.second); + } + + + // + // replace placeholder with values + // placeholder are denoted by surrounding '%' + // + for (map<string, string>::iterator iter = substitutions.begin(); + iter != substitutions.end(); ++iter) + replace_token('%' + iter->first + '%', iter->second); } - const std::string& - validation_error::get_option_name() const throw() + + void ambiguous_option::substitute_placeholders(const string& original_error_template) const { - return m_option_name; + // For short forms, all alternatives must be identical, by + // definition, to the specified option, so we don't need to + // display alternatives + if (m_option_style == command_line_style::allow_dash_for_short || + m_option_style == command_line_style::allow_slash_for_short) + { + error_with_option_name::substitute_placeholders(original_error_template); + return; + } + + + string error_template = original_error_template; + // remove duplicates using std::set + std::set<std::string> alternatives_set (m_alternatives.begin(), m_alternatives.end()); + std::vector<std::string> alternatives_vec (alternatives_set.begin(), alternatives_set.end()); + + error_template += " and matches "; + // Being very cautious: should be > 1 alternative! + if (alternatives_vec.size() > 1) + { + for (unsigned i = 0; i < alternatives_vec.size() - 1; ++i) + error_template += "'%prefix%" + alternatives_vec[i] + "', "; + error_template += "and "; + } + + // there is a programming error if multiple options have the same name... + if (m_alternatives.size() > 1 && alternatives_vec.size() == 1) + error_template += "different versions of "; + + error_template += "'%prefix%" + alternatives_vec.back() + "'"; + + + // use inherited logic + error_with_option_name::substitute_placeholders(error_template); } - std::string - validation_error::error_message(kind_t kind) + + + + + + string + validation_error::get_template(kind_t kind) { // Initially, store the message in 'const char*' variable, // to avoid conversion to std::string in all cases. const char* msg; switch(kind) { - case multiple_values_not_allowed: - msg = "multiple values not allowed"; - break; - case at_least_one_value_required: - msg = "at least one value required"; - break; case invalid_bool_value: - msg = "invalid bool value"; + msg = "the argument ('%value%') for option '%canonical_option%' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'"; break; case invalid_option_value: - msg = "invalid option value"; + msg = "the argument ('%value%') for option '%canonical_option%' is invalid"; + break; + case multiple_values_not_allowed: + msg = "option '%canonical_option%' only takes a single argument"; + break; + case at_least_one_value_required: + msg = "option '%canonical_option%' requires at least one argument"; break; + // currently unused case invalid_option: - msg = "invalid option"; + msg = "option '%canonical_option%' is not valid"; break; default: msg = "unknown error"; @@ -315,21 +425,4 @@ namespace boost { namespace program_options { return msg; } - const char* - validation_error::what() const throw() - { - if (!m_option_name.empty()) - { - m_message = "in option '" + m_option_name + "': " - + error_message(m_kind); - } - return m_message.c_str(); - } - - const std::string& - required_option::get_option_name() const throw() - { - return m_option_name; - } - }} |