// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CMD_LINE_PARSER_CHECk_1_
#define DLIB_CMD_LINE_PARSER_CHECk_1_
#include "cmd_line_parser_kernel_abstract.h"
#include <sstream>
#include <string>
#include "../string.h"
#include <vector>
namespace dlib
{
template <
typename clp_base
>
class cmd_line_parser_check_1 : public clp_base
{
/*!
This extension doesn't add any state.
!*/
public:
typedef typename clp_base::char_type char_type;
typedef typename clp_base::string_type string_type;
// ------------------------------------------------------------------------------------
class cmd_line_check_error : public dlib::error
{
friend class cmd_line_parser_check_1;
cmd_line_check_error(
error_type t,
const string_type& opt_,
const string_type& arg_
) :
dlib::error(t),
opt(opt_),
opt2(),
arg(arg_),
required_opts()
{ set_info_string(); }
cmd_line_check_error(
error_type t,
const string_type& opt_,
const string_type& opt2_,
int // this is just to make this constructor different from the one above
) :
dlib::error(t),
opt(opt_),
opt2(opt2_),
arg(),
required_opts()
{ set_info_string(); }
cmd_line_check_error (
error_type t,
const string_type& opt_,
const std::vector<string_type>& vect
) :
dlib::error(t),
opt(opt_),
opt2(),
arg(),
required_opts(vect)
{ set_info_string(); }
cmd_line_check_error(
error_type t,
const string_type& opt_
) :
dlib::error(t),
opt(opt_),
opt2(),
arg(),
required_opts()
{ set_info_string(); }
~cmd_line_check_error() throw() {}
void set_info_string (
)
{
std::ostringstream sout;
switch (type)
{
case EINVALID_OPTION_ARG:
sout << "Command line error: '" << narrow(arg) << "' is not a valid argument to "
<< "the '" << narrow(opt) << "' option.";
break;
case EMISSING_REQUIRED_OPTION:
if (required_opts.size() == 1)
{
sout << "Command line error: The '" << narrow(opt) << "' option requires the presence of "
<< "the '" << required_opts[0] << "' option.";
}
else
{
sout << "Command line error: The '" << narrow(opt) << "' option requires the presence of "
<< "one of the following options: ";
for (unsigned long i = 0; i < required_opts.size(); ++i)
{
if (i == required_opts.size()-2)
sout << "'" << required_opts[i] << "' or ";
else if (i == required_opts.size()-1)
sout << "'" << required_opts[i] << "'.";
else
sout << "'" << required_opts[i] << "', ";
}
}
break;
case EINCOMPATIBLE_OPTIONS:
sout << "Command line error: The '" << narrow(opt) << "' and '" << narrow(opt2)
<< "' options cannot be given together on the command line.";
break;
case EMULTIPLE_OCCURANCES:
sout << "Command line error: The '" << narrow(opt) << "' option can only "
<< "be given on the command line once.";
break;
default:
sout << "Command line error.";
break;
}
const_cast<std::string&>(info) = wrap_string(sout.str(),0,0);
}
public:
const string_type opt;
const string_type opt2;
const string_type arg;
const std::vector<string_type> required_opts;
};
// ------------------------------------------------------------------------------------
template <
typename T
>
void check_option_arg_type (
const string_type& option_name
) const;
template <
typename T
>
void check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const;
template <
typename T,
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const;
template <
size_t length
>
void check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const;
template <
size_t length
>
void check_incompatible_options (
const char_type* (&option_set)[length]
) const;
template <
size_t length
>
void check_one_time_options (
const char_type* (&option_set)[length]
) const;
void check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const;
void check_sub_option (
const string_type& parent_option,
const string_type& sub_option
) const;
template <
size_t length
>
void check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const;
template <
size_t length
>
void check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const;
template <
size_t parent_length,
size_t sub_length
>
void check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const;
};
template <
typename clp_base
>
inline void swap (
cmd_line_parser_check_1<clp_base>& a,
cmd_line_parser_check_1<clp_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template <typename T>
void cmd_line_parser_check_1<clp_base>::
check_option_arg_type (
const string_type& option_name
) const
{
try
{
const typename clp_base::option_type& opt = this->option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
string_cast<T>(opt.argument(i,j));
}
}
}
catch (string_cast_error& e)
{
throw cmd_line_check_error(EINVALID_OPTION_ARG,option_name,e.info);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template <typename T>
void cmd_line_parser_check_1<clp_base>::
check_option_arg_range (
const string_type& option_name,
const T& first,
const T& last
) const
{
try
{
const typename clp_base::option_type& opt = this->option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
T temp(string_cast<T>(opt.argument(i,j)));
if (temp < first || last < temp)
{
throw cmd_line_check_error(
EINVALID_OPTION_ARG,
option_name,
opt.argument(i,j)
);
}
}
}
}
catch (string_cast_error& e)
{
throw cmd_line_check_error(EINVALID_OPTION_ARG,option_name,e.info);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < typename T, size_t length >
void cmd_line_parser_check_1<clp_base>::
check_option_arg_range (
const string_type& option_name,
const T (&arg_set)[length]
) const
{
try
{
const typename clp_base::option_type& opt = this->option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
T temp(string_cast<T>(opt.argument(i,j)));
size_t k = 0;
for (; k < length; ++k)
{
if (arg_set[k] == temp)
break;
}
if (k == length)
{
throw cmd_line_check_error(
EINVALID_OPTION_ARG,
option_name,
opt.argument(i,j)
);
}
}
}
}
catch (string_cast_error& e)
{
throw cmd_line_check_error(EINVALID_OPTION_ARG,option_name,e.info);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_option_arg_range (
const string_type& option_name,
const char_type* (&arg_set)[length]
) const
{
const typename clp_base::option_type& opt = this->option(option_name);
const unsigned long number_of_arguments = opt.number_of_arguments();
const unsigned long count = opt.count();
for (unsigned long i = 0; i < number_of_arguments; ++i)
{
for (unsigned long j = 0; j < count; ++j)
{
size_t k = 0;
for (; k < length; ++k)
{
if (arg_set[k] == opt.argument(i,j))
break;
}
if (k == length)
{
throw cmd_line_check_error(
EINVALID_OPTION_ARG,
option_name,
opt.argument(i,j)
);
}
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_incompatible_options (
const char_type* (&option_set)[length]
) const
{
for (size_t i = 0; i < length; ++i)
{
for (size_t j = i+1; j < length; ++j)
{
if (this->option(option_set[i]).count() > 0 &&
this->option(option_set[j]).count() > 0 )
{
throw cmd_line_check_error(
EINCOMPATIBLE_OPTIONS,
option_set[i],
option_set[j],
0 // this argument has no meaning and is only here to make this
// call different from the other constructor
);
}
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
void cmd_line_parser_check_1<clp_base>::
check_incompatible_options (
const string_type& option_name1,
const string_type& option_name2
) const
{
if (this->option(option_name1).count() > 0 &&
this->option(option_name2).count() > 0 )
{
throw cmd_line_check_error(
EINCOMPATIBLE_OPTIONS,
option_name1,
option_name2,
0 // this argument has no meaning and is only here to make this
// call different from the other constructor
);
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
void cmd_line_parser_check_1<clp_base>::
check_sub_option (
const string_type& parent_option,
const string_type& sub_option
) const
{
if (this->option(parent_option).count() == 0)
{
if (this->option(sub_option).count() != 0)
{
std::vector<string_type> vect;
vect.resize(1);
vect[0] = parent_option;
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option, vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_sub_options (
const string_type& parent_option,
const char_type* (&sub_option_set)[length]
) const
{
if (this->option(parent_option).count() == 0)
{
size_t i = 0;
for (; i < length; ++i)
{
if (this->option(sub_option_set[i]).count() > 0)
break;
}
if (i != length)
{
std::vector<string_type> vect;
vect.resize(1);
vect[0] = parent_option;
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option_set[i], vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_sub_options (
const char_type* (&parent_option_set)[length],
const string_type& sub_option
) const
{
// first check if the sub_option is present
if (this->option(sub_option).count() > 0)
{
// now check if any of the parents are present
bool parents_present = false;
for (size_t i = 0; i < length; ++i)
{
if (this->option(parent_option_set[i]).count() > 0)
{
parents_present = true;
break;
}
}
if (!parents_present)
{
std::vector<string_type> vect(parent_option_set, parent_option_set+length);
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option, vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t parent_length, size_t sub_length >
void cmd_line_parser_check_1<clp_base>::
check_sub_options (
const char_type* (&parent_option_set)[parent_length],
const char_type* (&sub_option_set)[sub_length]
) const
{
// first check if any of the parent options are present
bool parents_present = false;
for (size_t i = 0; i < parent_length; ++i)
{
if (this->option(parent_option_set[i]).count() > 0)
{
parents_present = true;
break;
}
}
if (!parents_present)
{
// none of these sub options should be present
size_t i = 0;
for (; i < sub_length; ++i)
{
if (this->option(sub_option_set[i]).count() > 0)
break;
}
if (i != sub_length)
{
std::vector<string_type> vect(parent_option_set, parent_option_set+parent_length);
throw cmd_line_check_error( EMISSING_REQUIRED_OPTION, sub_option_set[i], vect);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename clp_base>
template < size_t length >
void cmd_line_parser_check_1<clp_base>::
check_one_time_options (
const char_type* (&option_set)[length]
) const
{
size_t i = 0;
for (; i < length; ++i)
{
if (this->option(option_set[i]).count() > 1)
break;
}
if (i != length)
{
throw cmd_line_check_error(
EMULTIPLE_OCCURANCES,
option_set[i]
);
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CMD_LINE_PARSER_CHECk_1_