Clean up exception classes, changes regarding to Ticket #3423

[SVN r58138]
This commit is contained in:
Sascha Ochsenknecht
2009-12-04 13:38:56 +00:00
parent 35bf26f432
commit 6e0f1db1fc
6 changed files with 186 additions and 93 deletions

View File

@@ -55,11 +55,11 @@ namespace boost { namespace program_options {
{
static std::basic_string<charT> empty;
if (v.size() > 1)
boost::throw_exception(validation_error("multiple values not allowed"));
boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed));
else if (v.size() == 1)
return v.front();
else if (!allow_empty)
boost::throw_exception(validation_error("at least one value required"));
boost::throw_exception(validation_error(validation_error::at_least_one_value_required));
return empty;
}

View File

@@ -25,17 +25,33 @@ namespace boost { namespace program_options {
class BOOST_PROGRAM_OPTIONS_DECL invalid_syntax : public error {
public:
invalid_syntax(const std::string& tokens, const std::string& msg)
: error(std::string(msg).append(" in '").append(tokens).append("'")),
tokens(tokens), msg(msg)
{}
enum kind_t {
long_not_allowed = 30,
long_adjacent_not_allowed,
short_adjacent_not_allowed,
empty_adjacent_parameter,
missing_parameter,
extra_parameter,
unrecognized_line
};
invalid_syntax(const std::string& tokens, kind_t kind);
// gcc says that throw specification on dtor is loosened
// without this line
~invalid_syntax() throw() {}
kind_t kind() const;
protected:
/** Used to convert kind_t to a related error text */
static std::string error_message(kind_t kind);
private:
// TODO: copy ctor might throw
std::string tokens, msg;
std::string m_tokens;
kind_t m_kind;
};
/** Class thrown when option name is not recognized. */
@@ -50,12 +66,10 @@ namespace boost { namespace program_options {
// without this line
~unknown_option() throw() {}
const std::string& get_option_name() const throw()
{
return m_option_name;
}
const std::string& get_option_name() const throw();
private:
std::string m_option_name;
std::string m_option_name;
};
/** Class thrown when there's ambiguity amoung several possible options. */
@@ -63,30 +77,35 @@ namespace boost { namespace program_options {
public:
ambiguous_option(const std::string& name,
const std::vector<std::string>& alternatives)
: error(std::string("ambiguous option ").append(name)),
alternatives(alternatives)
: error(std::string("ambiguous option ").append(name))
, alternatives(alternatives)
, m_option_name(name)
{}
~ambiguous_option() throw() {}
const std::string& get_option_name() const throw();
private:
// TODO: copy ctor might throw
std::vector<std::string> alternatives;
std::string m_option_name;
};
/** Class thrown when there are several option values, but
user called a method which cannot return them all. */
class BOOST_PROGRAM_OPTIONS_DECL multiple_values : public error {
public:
multiple_values(const std::string& what)
: error(what), m_option_name() {}
multiple_values()
: error("multiple values")
, m_option_name() {}
~multiple_values() throw() {}
void set_option_name(const std::string& option);
const std::string& get_option_name() const throw()
{
return m_option_name;
}
const std::string& get_option_name() const throw();
private:
std::string m_option_name; // The name of the option which
// caused the exception.
@@ -97,16 +116,15 @@ namespace boost { namespace program_options {
them all. */
class BOOST_PROGRAM_OPTIONS_DECL multiple_occurrences : public error {
public:
multiple_occurrences(const std::string& what)
: error(what), m_option_name() {}
multiple_occurrences()
: error("multiple occurrences")
, m_option_name() {}
~multiple_occurrences() throw() {}
void set_option_name(const std::string& option);
const std::string& get_option_name() const throw()
{
return m_option_name;
}
const std::string& get_option_name() const throw();
private:
std::string m_option_name; // The name of the option which
@@ -116,22 +134,40 @@ namespace boost { namespace program_options {
/** Class thrown when value of option is incorrect. */
class BOOST_PROGRAM_OPTIONS_DECL validation_error : public error {
public:
validation_error(const std::string& what) : error(what) {}
enum kind_t {
multiple_values_not_allowed = 30,
at_least_one_value_required,
invalid_bool_value,
invalid_option_value,
invalid_option
};
validation_error(kind_t kind,
const std::string& option_value = "",
const std::string& option_name = "");
~validation_error() throw() {}
void set_option_name(const std::string& option);
const std::string& get_option_name() const throw()
{
return m_option_name;
}
const std::string& get_option_name() const throw();
const char* what() const throw();
protected:
/** Used to convert kind_t to a related error text */
static std::string error_message(kind_t kind);
private:
mutable std::string m_message; // For on-demand formatting in 'what'
kind_t m_kind;
std::string m_option_name; // The name of the option which
// caused the exception.
std::string m_option_value; // Optional: value of the option m_options_name
mutable std::string m_message; // For on-demand formatting in 'what'
};
/** Class thrown if there is an invalid option value givenn */
class BOOST_PROGRAM_OPTIONS_DECL invalid_option_value
: public validation_error
{
@@ -142,39 +178,23 @@ namespace boost { namespace program_options {
#endif
};
/** Class thrown when there are too many positional options. */
/** Class thrown when there are too many positional options.
This is a programming error.
*/
class BOOST_PROGRAM_OPTIONS_DECL too_many_positional_options_error : public error {
public:
too_many_positional_options_error(const std::string& what)
: error(what) {}
};
/** Class thrown when there are too few positional options. */
class BOOST_PROGRAM_OPTIONS_DECL too_few_positional_options_error : public error {
public:
too_few_positional_options_error(const std::string& what)
: error(what) {}
too_many_positional_options_error()
: error("too many positional options")
{}
};
/** Class thrown when there are syntax errors in given command line */
class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_syntax : public invalid_syntax {
public:
enum kind_t {
long_not_allowed = 30,
long_adjacent_not_allowed,
short_adjacent_not_allowed,
empty_adjacent_parameter,
missing_parameter,
extra_parameter
};
invalid_command_line_syntax(const std::string& tokens, kind_t kind);
kind_t kind() const;
protected:
static std::string error_message(kind_t kind);
private:
kind_t m_kind;
};
/** Class thrown when there are programming error related to style */
class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_style : public error {
public:
invalid_command_line_style(const std::string& msg)

View File

@@ -34,13 +34,15 @@ namespace boost { namespace program_options {
using namespace std;
using namespace boost::program_options::command_line_style;
invalid_command_line_syntax::
invalid_command_line_syntax(const std::string& tokens, kind_t kind)
: invalid_syntax(tokens, error_message(kind)), m_kind(kind)
invalid_syntax::
invalid_syntax(const std::string& tokens, kind_t kind)
: error(error_message(kind).append(" in '").append(tokens).append("'"))
, m_tokens(tokens)
, m_kind(kind)
{}
std::string
invalid_command_line_syntax::error_message(kind_t kind)
invalid_syntax::error_message(kind_t kind)
{
// Initially, store the message in 'const char*' variable,
// to avoid conversion to std::string in all cases.
@@ -65,18 +67,25 @@ namespace boost { namespace program_options {
case extra_parameter:
msg = "extra parameter";
break;
case unrecognized_line:
msg = "unrecognized line";
break;
default:
msg = "unknown error";
}
return msg;
}
invalid_command_line_syntax::kind_t
invalid_command_line_syntax::kind() const
invalid_syntax::kind_t
invalid_syntax::kind() const
{
return m_kind;
}
invalid_command_line_syntax::
invalid_command_line_syntax(const std::string& tokens, kind_t kind)
: invalid_syntax(tokens, kind)
{}
}}
@@ -326,8 +335,7 @@ namespace boost { namespace program_options { namespace detail {
if (opt.position_key != -1) {
if (position >= m_positional->max_total_count())
{
boost::throw_exception(too_many_positional_options_error(
"too many positional options"));
boost::throw_exception(too_many_positional_options_error());
}
opt.string_key = m_positional->name_for_position(position);
++position;

View File

@@ -114,7 +114,7 @@ namespace boost { namespace program_options { namespace detail {
break;
} else {
boost::throw_exception(invalid_syntax(s, "unrecognized line"));
boost::throw_exception(invalid_syntax(s, invalid_syntax::unrecognized_line));
}
}
}

View File

@@ -97,9 +97,9 @@ namespace boost { namespace program_options {
{
if (!value_store.empty())
boost::throw_exception(
multiple_occurrences("multiple_occurrences"));
multiple_occurrences());
if (new_tokens.size() > 1)
boost::throw_exception(multiple_values("multiple_values"));
boost::throw_exception(multiple_values());
value_store = new_tokens.empty() ? std::string("") : new_tokens.front();
}
@@ -139,8 +139,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(
"'" + s + "' doesn't look like a bool value."));
boost::throw_exception(validation_error(validation_error::invalid_bool_value, s));
}
// This is blatant copy-paste. However, templating this will cause a problem,
@@ -162,7 +161,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("invalid bool value"));
boost::throw_exception(validation_error(validation_error::invalid_bool_value));
}
#endif
BOOST_PROGRAM_OPTIONS_DECL
@@ -188,19 +187,17 @@ namespace boost { namespace program_options {
{
if (!value.empty())
boost::throw_exception(
multiple_occurrences("multiple_occurrences"));
multiple_occurrences());
}
}
invalid_option_value::
invalid_option_value(const std::string& bad_value)
: validation_error(string("invalid option value '")
.append(bad_value).append("'"))
: validation_error(validation_error::invalid_option_value, bad_value)
{}
#ifndef BOOST_NO_STD_WSTRING
namespace
{
std::string convert_value(const std::wstring& s)
@@ -216,43 +213,111 @@ namespace boost { namespace program_options {
invalid_option_value::
invalid_option_value(const std::wstring& bad_value)
: validation_error(string("invalid option value '")
.append(convert_value(bad_value))
.append("'"))
: 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;
}
void multiple_values::set_option_name(const std::string& option_name)
const std::string&
ambiguous_option::get_option_name() const throw()
{
return m_option_name;
}
void
multiple_values::set_option_name(const std::string& option_name)
{
m_option_name = option_name;
}
void multiple_occurrences::set_option_name(const std::string& option_name)
const std::string&
multiple_values::get_option_name() const throw()
{
return m_option_name;
}
void
multiple_occurrences::set_option_name(const std::string& option_name)
{
m_option_name = option_name;
}
void validation_error::set_option_name(const std::string& option_name)
const std::string&
multiple_occurrences::get_option_name() const throw()
{
return m_option_name;
}
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))
{
if (!option_value.empty())
{
m_message.append(std::string("'") + option_value + std::string("'"));
}
}
void
validation_error::set_option_name(const std::string& option_name)
{
m_option_name = option_name;
}
const char* validation_error::what() const throw()
const std::string&
validation_error::get_option_name() const throw()
{
return m_option_name;
}
std::string
validation_error::error_message(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";
break;
case invalid_option_value:
msg = "invalid option value";
break;
case invalid_option:
msg = "invalid option";
break;
default:
msg = "unknown error";
}
return msg;
}
const char*
validation_error::what() const throw()
{
if (!m_option_name.empty())
{
m_message = "in option '" + m_option_name + "': "
+ logic_error::what();
return m_message.c_str();
}
else
{
return logic_error::what();
+ error_message(m_kind);
}
return m_message.c_str();
}
}}

View File

@@ -92,7 +92,7 @@ void test_multiple_occurrences()
catch (multiple_occurrences& e)
{
BOOST_CHECK_EQUAL(e.get_option_name(), "cfgfile");
BOOST_CHECK_EQUAL(string(e.what()), "multiple_occurrences");
BOOST_CHECK_EQUAL(string(e.what()), "multiple occurrences");
}
}