summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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.cpp279
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;
- }
-
}}