diff options
Diffstat (limited to 'ml/dlib/dlib/cmd_line_parser')
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_1.h | 580 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_c.h | 453 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h | 799 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h | 673 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_c.h | 203 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/cmd_line_parser_print_1.h | 205 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/get_option.h | 181 | ||||
-rw-r--r-- | ml/dlib/dlib/cmd_line_parser/get_option_abstract.h | 146 |
8 files changed, 3240 insertions, 0 deletions
diff --git a/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_1.h b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_1.h new file mode 100644 index 000000000..1736b4b56 --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_1.h @@ -0,0 +1,580 @@ +// 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_ + + diff --git a/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_c.h b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_c.h new file mode 100644 index 000000000..7ff858e89 --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_check_c.h @@ -0,0 +1,453 @@ +// 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_C_ +#define DLIB_CMD_LINE_PARSER_CHECk_C_ + +#include "cmd_line_parser_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" +#include <string> +#include "../interfaces/cmd_line_parser_option.h" +#include "../string.h" + +namespace dlib +{ + + template < + typename clp_check + > + class cmd_line_parser_check_c : public clp_check + { + public: + + typedef typename clp_check::char_type char_type; + typedef typename clp_check::string_type string_type; + + 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_check + > + inline void swap ( + cmd_line_parser_check_c<clp_check>& a, + cmd_line_parser_check_c<clp_check>& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template <typename T> + void cmd_line_parser_check_c<clp_check>:: + check_option_arg_type ( + const string_type& option_name + ) const + { + COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false); + + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name), + "\tvoid cmd_line_parser_check::check_option_arg_type()" + << "\n\tYou must have already parsed the command line and option_name must be valid." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_name: " << option_name + ); + + clp_check::template check_option_arg_type<T>(option_name); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template <typename T> + void cmd_line_parser_check_c<clp_check>:: + check_option_arg_range ( + const string_type& option_name, + const T& first, + const T& last + ) const + { + COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false); + + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name) && + first <= last, + "\tvoid cmd_line_parser_check::check_option_arg_range()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_name: " << option_name + << "\n\tfirst: " << first + << "\n\tlast: " << last + ); + + clp_check::check_option_arg_range(option_name,first,last); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < typename T, size_t length > + void cmd_line_parser_check_c<clp_check>:: + check_option_arg_range ( + const string_type& option_name, + const T (&arg_set)[length] + ) const + { + COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false); + + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name), + "\tvoid cmd_line_parser_check::check_option_arg_range()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_name: " << option_name + ); + + clp_check::check_option_arg_range(option_name,arg_set); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < size_t length > + void cmd_line_parser_check_c<clp_check>:: + check_option_arg_range ( + const string_type& option_name, + const char_type* (&arg_set)[length] + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name), + "\tvoid cmd_line_parser_check::check_option_arg_range()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_name): " << ((this->option_is_defined(option_name))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_name: " << option_name + ); + + clp_check::check_option_arg_range(option_name,arg_set); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < size_t length > + void cmd_line_parser_check_c<clp_check>:: + check_incompatible_options ( + const char_type* (&option_set)[length] + ) const + { + // make sure requires clause is not broken + for (size_t i = 0; i < length; ++i) + { + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_set[i]), + "\tvoid cmd_line_parser_check::check_incompatible_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_set[i]): " << ((this->option_is_defined(option_set[i]))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_set[i]: " << option_set[i] + << "\n\ti: " << static_cast<unsigned long>(i) + ); + + } + clp_check::check_incompatible_options(option_set); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + void cmd_line_parser_check_c<clp_check>:: + check_incompatible_options ( + const string_type& option_name1, + const string_type& option_name2 + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_name1) && + this->option_is_defined(option_name2), + "\tvoid cmd_line_parser_check::check_incompatible_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_name1): " << ((this->option_is_defined(option_name1))?"true":"false") + << "\n\toption_is_defined(option_name2): " << ((this->option_is_defined(option_name2))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_name1: " << option_name1 + << "\n\toption_name2: " << option_name2 + ); + + clp_check::check_incompatible_options(option_name1,option_name2); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + void cmd_line_parser_check_c<clp_check>:: + check_sub_option ( + const string_type& parent_option, + const string_type& sub_option + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(parent_option) && + this->option_is_defined(sub_option), + "\tvoid cmd_line_parser_check::check_sub_option()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\tparsed_line(): " << this->parsed_line() + << "\n\toption_is_defined(parent_option): " << this->option_is_defined(parent_option) + << "\n\toption_is_defined(sub_option): " << this->option_is_defined(sub_option) + << "\n\tparent_option: " << parent_option + << "\n\tsub_option: " << sub_option + ); + clp_check::check_sub_option(parent_option,sub_option); + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < size_t length > + void cmd_line_parser_check_c<clp_check>:: + check_sub_options ( + const string_type& parent_option, + const char_type* (&sub_option_set)[length] + ) const + { + // make sure requires clause is not broken + for (size_t i = 0; i < length; ++i) + { + DLIB_CASSERT( this->option_is_defined(sub_option_set[i]), + "\tvoid cmd_line_parser_check::check_sub_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(sub_option_set[i]): " + << ((this->option_is_defined(sub_option_set[i]))?"true":"false") + << "\n\tsub_option_set[i]: " << sub_option_set[i] + << "\n\ti: " << static_cast<unsigned long>(i) + ); + + } + + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(parent_option), + "\tvoid cmd_line_parser_check::check_sub_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(parent_option): " << ((this->option_is_defined(parent_option))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\tparent_option: " << parent_option + ); + clp_check::check_sub_options(parent_option,sub_option_set); + + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < size_t length > + void cmd_line_parser_check_c<clp_check>:: + check_sub_options ( + const char_type* (&parent_option_set)[length], + const string_type& sub_option + ) const + { + // make sure requires clause is not broken + for (size_t i = 0; i < length; ++i) + { + DLIB_CASSERT( this->option_is_defined(parent_option_set[i]), + "\tvoid cmd_line_parser_check::check_sub_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(parent_option_set[i]): " + << ((this->option_is_defined(parent_option_set[i]))?"true":"false") + << "\n\tparent_option_set[i]: " << parent_option_set[i] + << "\n\ti: " << static_cast<unsigned long>(i) + ); + + } + + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(sub_option), + "\tvoid cmd_line_parser_check::check_sub_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(sub_option): " << ((this->option_is_defined(sub_option))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\tsub_option: " << sub_option + ); + clp_check::check_sub_options(parent_option_set,sub_option); + + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < size_t parent_length, size_t sub_length > + void cmd_line_parser_check_c<clp_check>:: + check_sub_options ( + const char_type* (&parent_option_set)[parent_length], + const char_type* (&sub_option_set)[sub_length] + ) const + { + // make sure requires clause is not broken + for (size_t i = 0; i < sub_length; ++i) + { + DLIB_CASSERT( this->option_is_defined(sub_option_set[i]), + "\tvoid cmd_line_parser_check::check_sub_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(sub_option_set[i]): " + << ((this->option_is_defined(sub_option_set[i]))?"true":"false") + << "\n\tsub_option_set[i]: " << sub_option_set[i] + << "\n\ti: " << static_cast<unsigned long>(i) + ); + } + + for (size_t i = 0; i < parent_length; ++i) + { + DLIB_CASSERT( this->option_is_defined(parent_option_set[i]), + "\tvoid cmd_line_parser_check::check_parent_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(parent_option_set[i]): " + << ((this->option_is_defined(parent_option_set[i]))?"true":"false") + << "\n\tparent_option_set[i]: " << parent_option_set[i] + << "\n\ti: " << static_cast<unsigned long>(i) + ); + } + + + + DLIB_CASSERT( this->parsed_line() == true , + "\tvoid cmd_line_parser_check::check_sub_options()" + << "\n\tYou must have parsed the command line before you call this function." + << "\n\tthis: " << this + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + ); + + clp_check::check_sub_options(parent_option_set,sub_option_set); + + } + +// ---------------------------------------------------------------------------------------- + + template <typename clp_check> + template < size_t length > + void cmd_line_parser_check_c<clp_check>:: + check_one_time_options ( + const char_type* (&option_set)[length] + ) const + { + // make sure requires clause is not broken + for (size_t i = 0; i < length; ++i) + { + DLIB_CASSERT( this->parsed_line() == true && this->option_is_defined(option_set[i]), + "\tvoid cmd_line_parser_check::check_one_time_options()" + << "\n\tSee the requires clause for this function." + << "\n\tthis: " << this + << "\n\toption_is_defined(option_set[i]): " << ((this->option_is_defined(option_set[i]))?"true":"false") + << "\n\tparsed_line(): " << ((this->parsed_line())?"true":"false") + << "\n\toption_set[i]: " << option_set[i] + << "\n\ti: " << static_cast<unsigned long>(i) + ); + + } + clp_check::check_one_time_options(option_set); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_CHECk_C_ + diff --git a/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h new file mode 100644 index 000000000..68ea5a135 --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h @@ -0,0 +1,799 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CMD_LINE_PARSER_KERNEl_1_ +#define DLIB_CMD_LINE_PARSER_KERNEl_1_ + +#include "cmd_line_parser_kernel_abstract.h" +#include "../algs.h" +#include <string> +#include <sstream> +#include "../interfaces/enumerable.h" +#include "../interfaces/cmd_line_parser_option.h" +#include "../assert.h" +#include "../string.h" + +namespace dlib +{ + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + class cmd_line_parser_kernel_1 : public enumerable<cmd_line_parser_option<charT> > + { + /*! + REQUIREMENTS ON map + is an implementation of map/map_kernel_abstract.h + is instantiated to map items of type std::basic_string<charT> to void* + + REQUIREMENTS ON sequence + is an implementation of sequence/sequence_kernel_abstract.h and + is instantiated with std::basic_string<charT> + + REQUIREMENTS ON sequence2 + is an implementation of sequence/sequence_kernel_abstract.h and + is instantiated with std::basic_string<charT>* + + INITIAL VALUE + options.size() == 0 + argv.size() == 0 + have_parsed_line == false + + CONVENTION + have_parsed_line == parsed_line() + argv[index] == operator[](index) + argv.size() == number_of_arguments() + *((option_t*)options[name]) == option(name) + options.is_in_domain(name) == option_is_defined(name) + !*/ + + + + + public: + + typedef charT char_type; + typedef std::basic_string<charT> string_type; + typedef cmd_line_parser_option<charT> option_type; + + // exception class + class cmd_line_parse_error : public dlib::error + { + void set_info_string ( + ) + { + std::ostringstream sout; + switch (type) + { + case EINVALID_OPTION: + sout << "Command line error: '" << narrow(item) << "' is not a valid option."; + break; + case ETOO_FEW_ARGS: + if (num > 1) + { + sout << "Command line error: The '" << narrow(item) << "' option requires " << num + << " arguments."; + } + else + { + sout << "Command line error: The '" << narrow(item) << "' option requires " << num + << " argument."; + } + break; + case ETOO_MANY_ARGS: + sout << "Command line error: The '" << narrow(item) << "' option does not take any arguments.\n"; + break; + default: + sout << "Command line error."; + break; + } + const_cast<std::string&>(info) = wrap_string(sout.str(),0,0); + } + + public: + cmd_line_parse_error( + error_type t, + const std::basic_string<charT>& _item + ) : + dlib::error(t), + item(_item), + num(0) + { set_info_string();} + + cmd_line_parse_error( + error_type t, + const std::basic_string<charT>& _item, + unsigned long _num + ) : + dlib::error(t), + item(_item), + num(_num) + { set_info_string();} + + cmd_line_parse_error( + ) : + dlib::error(), + item(), + num(0) + { set_info_string();} + + ~cmd_line_parse_error() throw() {} + + const std::basic_string<charT> item; + const unsigned long num; + }; + + + private: + + class option_t : public cmd_line_parser_option<charT> + { + /*! + INITIAL VALUE + options.size() == 0 + + CONVENTION + name_ == name() + description_ == description() + number_of_arguments_ == number_of_arguments() + options[N][arg] == argument(arg,N) + num_present == count() + !*/ + + friend class cmd_line_parser_kernel_1<charT,map,sequence,sequence2>; + + public: + + const std::basic_string<charT>& name ( + ) const { return name_; } + + const std::basic_string<charT>& group_name ( + ) const { return group_name_; } + + const std::basic_string<charT>& description ( + ) const { return description_; } + + unsigned long number_of_arguments( + ) const { return number_of_arguments_; } + + unsigned long count ( + ) const { return num_present; } + + const std::basic_string<charT>& argument ( + unsigned long arg, + unsigned long N + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( N < count() && arg < number_of_arguments(), + "\tconst string_type& cmd_line_parser_option::argument(unsigned long,unsigned long)" + << "\n\tInvalid arguments were given to this function." + << "\n\tthis: " << this + << "\n\tN: " << N + << "\n\targ: " << arg + << "\n\tname(): " << narrow(name()) + << "\n\tcount(): " << count() + << "\n\tnumber_of_arguments(): " << number_of_arguments() + ); + + return options[N][arg]; + } + + protected: + + option_t ( + ) : + num_present(0) + {} + + ~option_t() + { + clear(); + } + + private: + + void clear() + /*! + ensures + - #count() == 0 + - clears everything out of options and frees memory + !*/ + { + for (unsigned long i = 0; i < options.size(); ++i) + { + delete [] options[i]; + } + options.clear(); + num_present = 0; + } + + // data members + std::basic_string<charT> name_; + std::basic_string<charT> group_name_; + std::basic_string<charT> description_; + sequence2 options; + unsigned long number_of_arguments_; + unsigned long num_present; + + + + // restricted functions + option_t(option_t&); // copy constructor + option_t& operator=(option_t&); // assignment operator + }; + + // -------------------------- + + public: + + cmd_line_parser_kernel_1 ( + ); + + virtual ~cmd_line_parser_kernel_1 ( + ); + + void clear( + ); + + void parse ( + int argc, + const charT** argv + ); + + void parse ( + int argc, + charT** argv + ) + { + parse(argc, const_cast<const charT**>(argv)); + } + + bool parsed_line( + ) const; + + bool option_is_defined ( + const string_type& name + ) const; + + void add_option ( + const string_type& name, + const string_type& description, + unsigned long number_of_arguments = 0 + ); + + void set_group_name ( + const string_type& group_name + ); + + string_type get_group_name ( + ) const { return group_name; } + + const cmd_line_parser_option<charT>& option ( + const string_type& name + ) const; + + unsigned long number_of_arguments( + ) const; + + const string_type& operator[] ( + unsigned long index + ) const; + + void swap ( + cmd_line_parser_kernel_1& item + ); + + // functions from the enumerable interface + bool at_start ( + ) const { return options.at_start(); } + + void reset ( + ) const { options.reset(); } + + bool current_element_valid ( + ) const { return options.current_element_valid(); } + + const cmd_line_parser_option<charT>& element ( + ) const { return *static_cast<cmd_line_parser_option<charT>*>(options.element().value()); } + + cmd_line_parser_option<charT>& element ( + ) { return *static_cast<cmd_line_parser_option<charT>*>(options.element().value()); } + + bool move_next ( + ) const { return options.move_next(); } + + size_t size ( + ) const { return options.size(); } + + private: + + // data members + map options; + sequence argv; + bool have_parsed_line; + string_type group_name; + + // restricted functions + cmd_line_parser_kernel_1(cmd_line_parser_kernel_1&); // copy constructor + cmd_line_parser_kernel_1& operator=(cmd_line_parser_kernel_1&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + inline void swap ( + cmd_line_parser_kernel_1<charT,map,sequence,sequence2>& a, + cmd_line_parser_kernel_1<charT,map,sequence,sequence2>& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + cmd_line_parser_kernel_1 ( + ) : + have_parsed_line(false) + { + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + ~cmd_line_parser_kernel_1 ( + ) + { + // delete all option_t objects in options + options.reset(); + while (options.move_next()) + { + delete static_cast<option_t*>(options.element().value()); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + clear( + ) + { + have_parsed_line = false; + argv.clear(); + + + // delete all option_t objects in options + options.reset(); + while (options.move_next()) + { + delete static_cast<option_t*>(options.element().value()); + } + options.clear(); + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + parse ( + int argc_, + const charT** argv + ) + { + using namespace std; + + // make sure there aren't any arguments hanging around from the last time + // parse was called + this->argv.clear(); + + // make sure that the options have been cleared of any arguments since + // the last time parse() was called + if (have_parsed_line) + { + options.reset(); + while (options.move_next()) + { + static_cast<option_t*>(options.element().value())->clear(); + } + options.reset(); + } + + // this tells us if we have seen -- on the command line all by itself + // or not. + bool escape = false; + + const unsigned long argc = static_cast<unsigned long>(argc_); + try + { + + for (unsigned long i = 1; i < argc; ++i) + { + if (argv[i][0] == _dT(charT,'-') && !escape) + { + // we are looking at the start of an option + + // -------------------------------------------------------------------- + if (argv[i][1] == _dT(charT,'-')) + { + // we are looking at the start of a "long named" option + string_type temp = &argv[i][2]; + string_type first_argument; + typename string_type::size_type pos = temp.find_first_of(_dT(charT,'=')); + // This variable will be 1 if there is an argument supplied via the = sign + // and 0 otherwise. + unsigned long extra_argument = 0; + if (pos != string_type::npos) + { + // there should be an extra argument + extra_argument = 1; + first_argument = temp.substr(pos+1); + temp = temp.substr(0,pos); + } + + // make sure this name is defined + if (!options.is_in_domain(temp)) + { + // the long name is not a valid option + if (argv[i][2] == _dT(charT,'\0')) + { + // there was nothing after the -- on the command line + escape = true; + continue; + } + else + { + // there was something after the command line but it + // wasn't a valid option + throw cmd_line_parse_error(EINVALID_OPTION,temp); + } + } + + + option_t* o = static_cast<option_t*>(options[temp]); + + // check the number of arguments after this option and make sure + // it is correct + if (argc + extra_argument <= o->number_of_arguments() + i) + { + // there are too few arguments + throw cmd_line_parse_error(ETOO_FEW_ARGS,temp,o->number_of_arguments()); + } + if (extra_argument && first_argument.size() == 0 ) + { + // if there would be exactly the right number of arguments if + // the first_argument wasn't empty + if (argc == o->number_of_arguments() + i) + throw cmd_line_parse_error(ETOO_FEW_ARGS,temp,o->number_of_arguments()); + else + { + // in this case we just ignore the trailing = and parse everything + // the same. + extra_argument = 0; + } + } + // you can't force an option that doesn't have any arguments to take + // one by using the --option=arg syntax + if (extra_argument == 1 && o->number_of_arguments() == 0) + { + throw cmd_line_parse_error(ETOO_MANY_ARGS,temp); + } + + + + + + + // at this point we know that the option is ok and we should + // populate its options object + if (o->number_of_arguments() > 0) + { + + string_type* stemp = new string_type[o->number_of_arguments()]; + unsigned long j = 0; + + // add the argument after the = sign if one is present + if (extra_argument) + { + stemp[0] = first_argument; + ++j; + } + + for (; j < o->number_of_arguments(); ++j) + { + stemp[j] = argv[i+j+1-extra_argument]; + } + o->options.add(o->options.size(),stemp); + } + o->num_present += 1; + + + // adjust the value of i to account for the arguments to + // this option + i += o->number_of_arguments() - extra_argument; + } + // -------------------------------------------------------------------- + else + { + // we are looking at the start of a list of a single char options + + // make sure there is something in this string other than - + if (argv[i][1] == _dT(charT,'\0')) + { + throw cmd_line_parse_error(); + } + + string_type temp = &argv[i][1]; + const typename string_type::size_type num = temp.size(); + for (unsigned long k = 0; k < num; ++k) + { + string_type name; + // Doing this instead of name = temp[k] seems to avoid a bug in g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 + // which results in name[0] having the wrong value. + name.resize(1); + name[0] = temp[k]; + + + // make sure this name is defined + if (!options.is_in_domain(name)) + { + // the name is not a valid option + throw cmd_line_parse_error(EINVALID_OPTION,name); + } + + option_t* o = static_cast<option_t*>(options[name]); + + // if there are chars immediately following this option + int delta = 0; + if (num != k+1) + { + delta = 1; + } + + // check the number of arguments after this option and make sure + // it is correct + if (argc + delta <= o->number_of_arguments() + i) + { + // there are too few arguments + std::ostringstream sout; + throw cmd_line_parse_error(ETOO_FEW_ARGS,name,o->number_of_arguments()); + } + + + o->num_present += 1; + + // at this point we know that the option is ok and we should + // populate its options object + if (o->number_of_arguments() > 0) + { + string_type* stemp = new string_type[o->number_of_arguments()]; + if (delta == 1) + { + temp = &argv[i][2+k]; + k = (unsigned long)num; // this ensures that the argument to this + // option isn't going to be treated as a + // list of options + + stemp[0] = temp; + } + for (unsigned long j = 0; j < o->number_of_arguments()-delta; ++j) + { + stemp[j+delta] = argv[i+j+1]; + } + o->options.add(o->options.size(),stemp); + + // adjust the value of i to account for the arguments to + // this option + i += o->number_of_arguments()-delta; + } + } // for (unsigned long k = 0; k < num; ++k) + } + // -------------------------------------------------------------------- + + } + else + { + // this is just a normal argument + string_type temp = argv[i]; + this->argv.add(this->argv.size(),temp); + } + + } + have_parsed_line = true; + + } + catch (...) + { + have_parsed_line = false; + + // clear all the option objects + options.reset(); + while (options.move_next()) + { + static_cast<option_t*>(options.element().value())->clear(); + } + options.reset(); + + throw; + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + bool cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + parsed_line( + ) const + { + return have_parsed_line; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + bool cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + option_is_defined ( + const string_type& name + ) const + { + return options.is_in_domain(name); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + set_group_name ( + const string_type& group_name_ + ) + { + group_name = group_name_; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + add_option ( + const string_type& name, + const string_type& description, + unsigned long number_of_arguments + ) + { + option_t* temp = new option_t; + try + { + temp->name_ = name; + temp->group_name_ = group_name; + temp->description_ = description; + temp->number_of_arguments_ = number_of_arguments; + void* t = temp; + string_type n(name); + options.add(n,t); + }catch (...) { delete temp; throw;} + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + const cmd_line_parser_option<charT>& cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + option ( + const string_type& name + ) const + { + return *static_cast<cmd_line_parser_option<charT>*>(options[name]); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + unsigned long cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + number_of_arguments( + ) const + { + return argv.size(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + const std::basic_string<charT>& cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + operator[] ( + unsigned long index + ) const + { + return argv[index]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>:: + swap ( + cmd_line_parser_kernel_1<charT,map,sequence,sequence2>& item + ) + { + options.swap(item.options); + argv.swap(item.argv); + exchange(have_parsed_line,item.have_parsed_line); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_KERNEl_1_ + diff --git a/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h new file mode 100644 index 000000000..8461ffb26 --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h @@ -0,0 +1,673 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_CMD_LINE_PARSER_KERNEl_ABSTRACT_ +#ifdef DLIB_CMD_LINE_PARSER_KERNEl_ABSTRACT_ + +#include "../algs.h" +#include <string> +#include "../interfaces/enumerable.h" +#include "../interfaces/cmd_line_parser_option.h" +#include <vector> +#include <iostream> + +namespace dlib +{ + + template < + typename charT + > + class cmd_line_parser : public enumerable<cmd_line_parser_option<charT> > + { + /*! + REQUIREMENTS ON charT + Must be an integral type suitable for storing characters. (e.g. char + or wchar_t) + + INITIAL VALUE + - parsed_line() == false + - option_is_defined(x) == false, for all values of x + - get_group_name() == "" + + ENUMERATION ORDER + The enumerator will enumerate over all the options defined in *this + in alphebetical order according to the name of the option. + + POINTERS AND REFERENCES TO INTERNAL DATA + parsed_line(), option_is_defined(), option(), number_of_arguments(), + operator[](), and swap() functions do not invalidate pointers or + references to internal data. All other functions have no such guarantee. + + + WHAT THIS OBJECT REPRESENTS + This object represents a command line parser. + The command lines must match the following BNF. + + command_line ::= <program_name> { <options> | <arg> } [ -- {<word>} ] + program_name ::= <word> + arg ::= any <word> that does not start with - + option_arg ::= <sword> + option_name ::= <char> + long_option_name ::= <char> {<char> | - } + options ::= <bword> - <option_name> {<option_name>} {<option_arg>} | + <bword> -- <long_option_name> [=<option_arg>] {<bword> <option_arg>} + char ::= any character other than - or = + word ::= any string from argv where argv is the second + parameter to main() + sword ::= any suffix of a string from argv where argv is the + second parameter to main() + bword ::= This is an empty string which denotes the begining of a + <word>. + + + Options with arguments: + An option with N arguments will consider the next N swords to be + its arguments. + + so for example, if we have an option o that expects 2 arguments + then the following are a few legal examples: + + program -o arg1 arg2 general_argument + program -oarg1 arg2 general_argument + + arg1 and arg2 are associated with the option o and general_argument + is not. + + Arguments not associated with an option: + An argument that is not associated with an option is considered a + general command line argument and is indexed by operator[] defined + by the cmd_line_parser object. Additionally, if the string + "--" appears in the command line all by itself then all words + following it are considered to be general command line arguments. + + + Consider the following two examples involving a command line and + a cmd_line_parser object called parser. + + Example 1: + command line: program general_arg1 -o arg1 arg2 general_arg2 + Then the following is true (assuming the o option is defined + and takes 2 arguments). + + parser[0] == "general_arg1" + parser[1] == "general_arg2" + parser.number_of_arguments() == 2 + parser.option("o").argument(0) == "arg1" + parser.option("o").argument(1) == "arg2" + parser.option("o").count() == 1 + + Example 2: + command line: program general_arg1 -- -o arg1 arg2 general_arg2 + Then the following is true (the -- causes everything following + it to be treated as a general argument). + + parser[0] == "general_arg1" + parser[1] == "-o" + parser[2] == "arg1" + parser[3] == "arg2" + parser[4] == "general_arg2" + parser.number_of_arguments() == 5 + parser.option("o").count() == 0 + !*/ + + public: + + typedef charT char_type; + typedef std::basic_string<charT> string_type; + typedef cmd_line_parser_option<charT> option_type; + + // exception class + class cmd_line_parse_error : public dlib::error + { + /*! + GENERAL + This exception is thrown if there is an error detected in a + command line while it is being parsed. You can consult this + object's type and item members to determine the nature of the + error. (note that the type member is inherited from dlib::error). + + INTERPRETING THIS EXCEPTION + - if (type == EINVALID_OPTION) then + - There was an undefined option on the command line + - item == The invalid option that was on the command line + - if (type == ETOO_FEW_ARGS) then + - An option was given on the command line but it was not + supplied with the required number of arguments. + - item == The name of this option. + - num == The number of arguments expected by this option. + - if (type == ETOO_MANY_ARGS) then + - An option was given on the command line such as --option=arg + but this option doesn't take any arguments. + - item == The name of this option. + !*/ + public: + const std::basic_string<charT> item; + const unsigned long num; + }; + + // -------------------------- + + cmd_line_parser ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + !*/ + + virtual ~cmd_line_parser ( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc + if this exception is thrown then #*this is unusable + until clear() is called and succeeds + !*/ + + void parse ( + int argc, + const charT** argv + ); + /*! + requires + - argv == an array of strings that was obtained from the second argument + of the function main(). + (i.e. argv[0] should be the <program> token, argv[1] should be + an <options> or <arg> token, etc.) + - argc == the number of strings in argv + ensures + - parses the command line given by argc and argv + - #parsed_line() == true + - #at_start() == true + throws + - std::bad_alloc + if this exception is thrown then #*this is unusable until clear() + is called successfully + - cmd_line_parse_error + This exception is thrown if there is an error parsing the command line. + If this exception is thrown then #parsed_line() == false and all + options will have their count() set to 0 but otherwise there will + be no effect (i.e. all registered options will remain registered). + !*/ + + void parse ( + int argc, + charT** argv + ); + /*! + This just calls this->parse(argc,argv) and performs the necessary const_cast + on argv. + !*/ + + bool parsed_line( + ) const; + /*! + ensures + - returns true if parse() has been called successfully + - returns false otherwise + !*/ + + bool option_is_defined ( + const string_type& name + ) const; + /*! + ensures + - returns true if the option has been added to the parser object + by calling add_option(name). + - returns false otherwise + !*/ + + void add_option ( + const string_type& name, + const string_type& description, + unsigned long number_of_arguments = 0 + ); + /*! + requires + - parsed_line() == false + - option_is_defined(name) == false + - name does not contain any ' ', '\t', '\n', or '=' characters + - name[0] != '-' + - name.size() > 0 + ensures + - #option_is_defined(name) == true + - #at_start() == true + - #option(name).count() == 0 + - #option(name).description() == description + - #option(name).number_of_arguments() == number_of_arguments + - #option(name).group_name() == get_group_name() + throws + - std::bad_alloc + if this exception is thrown then the add_option() function has no + effect + !*/ + + const option_type& option ( + const string_type& name + ) const; + /*! + requires + - option_is_defined(name) == true + ensures + - returns the option specified by name + !*/ + + unsigned long number_of_arguments( + ) const; + /*! + requires + - parsed_line() == true + ensures + - returns the number of arguments present in the command line. + This count does not include options or their arguments. Only + arguments unrelated to any option are counted. + !*/ + + const string_type& operator[] ( + unsigned long N + ) const; + /*! + requires + - parsed_line() == true + - N < number_of_arguments() + ensures + - returns the Nth command line argument + !*/ + + void swap ( + cmd_line_parser& item + ); + /*! + ensures + - swaps *this and item + !*/ + + void print_options ( + std::basic_ostream<char_type>& out + ) const; + /*! + ensures + - prints all the command line options to out. + - #at_start() == true + throws + - any exception. + if an exception is thrown then #at_start() == true but otherwise + it will have no effect on the state of #*this. + !*/ + + void print_options ( + ) const; + /*! + ensures + - prints all the command line options to cout. + - #at_start() == true + throws + - any exception. + if an exception is thrown then #at_start() == true but otherwise + it will have no effect on the state of #*this. + !*/ + + string_type get_group_name ( + ) const; + /*! + ensures + - returns the current group name. This is the group new options will be + added into when added via add_option(). + - The group name of an option is used by print_options(). In particular, + it groups all options with the same group name together and displays them + under a title containing the text of the group name. This allows you to + group similar options together in the output of print_options(). + - A group name of "" (i.e. the empty string) means that no group name is + set. + !*/ + + void set_group_name ( + const string_type& group_name + ); + /*! + ensures + - #get_group_name() == group_name + !*/ + + // ------------------------------------------------------------- + // Input Validation Tools + // ------------------------------------------------------------- + + class cmd_line_check_error : public dlib::error + { + /*! + This is the exception thrown by the check_*() routines if they find a + command line error. The interpretation of the member variables is defined + below in each check_*() routine. + !*/ + + 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; + /*! + requires + - parsed_line() == true + - option_is_defined(option_name) == true + - T is not a pointer type + ensures + - all the arguments for the given option are convertible + by string_cast<T>() to an object of type T. + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EINVALID_OPTION_ARG + - opt == option_name + - arg == the text of the offending argument + !*/ + + template < + typename T + > + void check_option_arg_range ( + const string_type& option_name, + const T& first, + const T& last + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(option_name) == true + - first <= last + - T is not a pointer type + ensures + - all the arguments for the given option are convertible + by string_cast<T>() to an object of type T and the resulting value is + in the range first to last inclusive. + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EINVALID_OPTION_ARG + - opt == option_name + - arg == the text of the offending argument + !*/ + + template < + typename T, + size_t length + > + void check_option_arg_range ( + const string_type& option_name, + const T (&arg_set)[length] + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(option_name) == true + - T is not a pointer type + ensures + - for each argument to the given option: + - this argument is convertible by string_cast<T>() to an object of + type T and the resulting value is equal to some element in the + arg_set array. + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EINVALID_OPTION_ARG + - opt == option_name + - arg == the text of the offending argument + !*/ + + template < + size_t length + > + void check_option_arg_range ( + const string_type& option_name, + const char_type* (&arg_set)[length] + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(option_name) == true + ensures + - for each argument to the given option: + - there is a string in the arg_set array that is equal to this argument. + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EINVALID_OPTION_ARG + - opt == option_name + - arg == the text of the offending argument + !*/ + + template < + size_t length + > + void check_one_time_options ( + const char_type* (&option_set)[length] + ) const; + /*! + requires + - parsed_line() == true + - for all valid i: + - option_is_defined(option_set[i]) == true + ensures + - all the options in the option_set array occur at most once on the + command line. + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EMULTIPLE_OCCURANCES + - opt == the option that occurred more than once on the command line. + !*/ + + void check_incompatible_options ( + const string_type& option_name1, + const string_type& option_name2 + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(option_name1) == true + - option_is_defined(option_name2) == true + ensures + - option(option_name1).count() == 0 || option(option_name2).count() == 0 + (i.e. at most, only one of the options is currently present) + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EINCOMPATIBLE_OPTIONS + - opt == option_name1 + - opt2 == option_name2 + !*/ + + template < + size_t length + > + void check_incompatible_options ( + const char_type* (&option_set)[length] + ) const; + /*! + requires + - parsed_line() == true + - for all valid i: + - option_is_defined(option_set[i]) == true + ensures + - At most only one of the options in the array option_set has a count() + greater than 0. (i.e. at most, only one of the options is currently present) + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EINCOMPATIBLE_OPTIONS + - opt == One of the incompatible options found. + - opt2 == The next incompatible option found. + !*/ + + void check_sub_option ( + const string_type& parent_option, + const string_type& sub_option + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(parent_option) == true + - option_is_defined(sub_option) == true + ensures + - if (option(parent_option).count() == 0) then + - option(sub_option).count() == 0 + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EMISSING_REQUIRED_OPTION + - opt == sub_option. + - required_opts == a vector that contains only parent_option. + !*/ + + template < + size_t length + > + void check_sub_options ( + const char_type* (&parent_option_set)[length], + const string_type& sub_option + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(sub_option) == true + - for all valid i: + - option_is_defined(parent_option_set[i] == true + ensures + - if (option(sub_option).count() > 0) then + - At least one of the options in the array parent_option_set has a count() + greater than 0. (i.e. at least one of the options in parent_option_set + is currently present) + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EMISSING_REQUIRED_OPTION + - opt == the first option from the sub_option that is present. + - required_opts == a vector containing everything from parent_option_set. + !*/ + + template < + size_t length + > + void check_sub_options ( + const string_type& parent_option, + const char_type* (&sub_option_set)[length] + ) const; + /*! + requires + - parsed_line() == true + - option_is_defined(parent_option) == true + - for all valid i: + - option_is_defined(sub_option_set[i]) == true + ensures + - if (option(parent_option).count() == 0) then + - for all valid i: + - option(sub_option_set[i]).count() == 0 + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EMISSING_REQUIRED_OPTION + - opt == the first option from the sub_option_set that is present. + - required_opts == a vector that contains only parent_option. + !*/ + + 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; + /*! + requires + - parsed_line() == true + - for all valid i: + - option_is_defined(parent_option_set[i] == true + - for all valid j: + - option_is_defined(sub_option_set[j]) == true + ensures + - for all valid j: + - if (option(sub_option_set[j]).count() > 0) then + - At least one of the options in the array parent_option_set has a count() + greater than 0. (i.e. at least one of the options in parent_option_set + is currently present) + throws + - std::bad_alloc + - cmd_line_check_error + This exception is thrown if the ensures clause could not be satisfied. + The exception's members will be set as follows: + - type == EMISSING_REQUIRED_OPTION + - opt == the first option from the sub_option_set that is present. + - required_opts == a vector containing everything from parent_option_set. + !*/ + + + private: + + // restricted functions + cmd_line_parser(cmd_line_parser&); // copy constructor + cmd_line_parser& operator=(cmd_line_parser&); // assignment operator + + }; + +// ----------------------------------------------------------------------------------------- + + typedef cmd_line_parser<char> command_line_parser; + typedef cmd_line_parser<wchar_t> wcommand_line_parser; + +// ----------------------------------------------------------------------------------------- + + template < + typename charT + > + inline void swap ( + cmd_line_parser<charT>& a, + cmd_line_parser<charT>& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +// ----------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_KERNEl_ABSTRACT_ + diff --git a/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_c.h b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_c.h new file mode 100644 index 000000000..e80543018 --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_c.h @@ -0,0 +1,203 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CMD_LINE_PARSER_KERNEl_C_ +#define DLIB_CMD_LINE_PARSER_KERNEl_C_ + +#include "cmd_line_parser_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" +#include <string> +#include "../interfaces/cmd_line_parser_option.h" +#include "../string.h" + +namespace dlib +{ + + template < + typename clp_base + > + class cmd_line_parser_kernel_c : public clp_base + { + public: + + typedef typename clp_base::char_type char_type; + typedef typename clp_base::string_type string_type; + typedef typename clp_base::option_type option_type; + + void add_option ( + const string_type& name, + const string_type& description, + unsigned long number_of_arguments = 0 + ); + + const option_type& option ( + const string_type& name + ) const; + + unsigned long number_of_arguments( + ) const; + + const option_type& element ( + ) const; + + option_type& element ( + ); + + const string_type& operator[] ( + unsigned long N + ) const; + + }; + + + template < + typename clp_base + > + inline void swap ( + cmd_line_parser_kernel_c<clp_base>& a, + cmd_line_parser_kernel_c<clp_base>& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + const typename clp_base::string_type& cmd_line_parser_kernel_c<clp_base>:: + operator[] ( + unsigned long N + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true && N < number_of_arguments(), + "\tvoid cmd_line_parser::operator[](unsigned long N)" + << "\n\tYou must specify a valid index N and the parser must have run already." + << "\n\tthis: " << this + << "\n\tN: " << N + << "\n\tparsed_line(): " << this->parsed_line() + << "\n\tnumber_of_arguments(): " << number_of_arguments() + ); + + return clp_base::operator[](N); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + void cmd_line_parser_kernel_c<clp_base>:: + add_option ( + const string_type& name, + const string_type& description, + unsigned long number_of_arguments + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == false && + name.size() > 0 && + this->option_is_defined(name) == false && + name.find_first_of(_dT(char_type," \t\n=")) == string_type::npos && + name[0] != '-', + "\tvoid cmd_line_parser::add_option(const string_type&,const string_type&,unsigned long)" + << "\n\tsee the requires clause of add_option()" + << "\n\tthis: " << this + << "\n\tname.size(): " << static_cast<unsigned long>(name.size()) + << "\n\tname: \"" << narrow(name) << "\"" + << "\n\tparsed_line(): " << (this->parsed_line()? "true" : "false") + << "\n\tis_option_defined(\"" << narrow(name) << "\"): " << (this->option_is_defined(name)? "true" : "false") + ); + + clp_base::add_option(name,description,number_of_arguments); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + const typename clp_base::option_type& cmd_line_parser_kernel_c<clp_base>:: + option ( + const string_type& name + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->option_is_defined(name) == true, + "\toption cmd_line_parser::option(const string_type&)" + << "\n\tto get an option it must be defined by a call to add_option()" + << "\n\tthis: " << this + << "\n\tname: \"" << narrow(name) << "\"" + ); + + return clp_base::option(name); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + unsigned long cmd_line_parser_kernel_c<clp_base>:: + number_of_arguments( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->parsed_line() == true , + "\tunsigned long cmd_line_parser::number_of_arguments()" + << "\n\tyou must parse the command line before you can find out how many arguments it has" + << "\n\tthis: " << this + ); + + return clp_base::number_of_arguments(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + const typename clp_base::option_type& cmd_line_parser_kernel_c<clp_base>:: + element ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst cmd_line_parser_option& cmd_line_parser::element()" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return clp_base::element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + typename clp_base::option_type& cmd_line_parser_kernel_c<clp_base>:: + element ( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tcmd_line_parser_option& cmd_line_parser::element()" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return clp_base::element(); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_KERNEl_C_ + diff --git a/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_print_1.h b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_print_1.h new file mode 100644 index 000000000..3f52c842f --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_print_1.h @@ -0,0 +1,205 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CMD_LINE_PARSER_PRINt_1_ +#define DLIB_CMD_LINE_PARSER_PRINt_1_ + +#include "cmd_line_parser_kernel_abstract.h" +#include "../algs.h" +#include "../string.h" +#include <iostream> +#include <string> +#include <sstream> +#include <map> +#include <memory> + +namespace dlib +{ + + template < + typename clp_base + > + class cmd_line_parser_print_1 : public clp_base + { + + public: + + void print_options ( + std::basic_ostream<typename clp_base::char_type>& out + ) const; + + void print_options ( + ) const + { + print_options(std::cout); + } + + }; + + template < + typename clp_base + > + inline void swap ( + cmd_line_parser_print_1<clp_base>& a, + cmd_line_parser_print_1<clp_base>& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename clp_base + > + void cmd_line_parser_print_1<clp_base>:: + print_options ( + std::basic_ostream<typename clp_base::char_type>& out + ) const + { + typedef typename clp_base::char_type ct; + typedef std::basic_string<ct> string; + typedef typename string::size_type size_type; + + typedef std::basic_ostringstream<ct> ostringstream; + + try + { + + + size_type max_len = 0; + this->reset(); + + // this loop here is just the bottom loop but without the print statements. + // I'm doing this to figure out what len should be. + while (this->move_next()) + { + size_type len = 0; + len += 3; + if (this->element().name().size() > 1) + { + ++len; + } + len += this->element().name().size(); + + if (this->element().number_of_arguments() == 1) + { + len += 6; + } + else + { + for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i) + { + len += 7; + if (i+1 > 9) + ++len; + } + } + + len += 3; + if (len < 33) + max_len = std::max(max_len,len); + } + + + // Make a separate ostringstream for each option group. We are going to write + // the output for each group to a separate ostringstream so that we can keep + // them grouped together in the final output. + std::map<string,std::shared_ptr<ostringstream> > groups; + this->reset(); + while(this->move_next()) + { + if (!groups[this->element().group_name()]) + groups[this->element().group_name()].reset(new ostringstream); + } + + + + + this->reset(); + + while (this->move_next()) + { + ostringstream& sout = *groups[this->element().group_name()]; + + size_type len = 0; + sout << _dT(ct,"\n -"); + len += 3; + if (this->element().name().size() > 1) + { + sout << _dT(ct,"-"); + ++len; + } + sout << this->element().name(); + len += this->element().name().size(); + + if (this->element().number_of_arguments() == 1) + { + sout << _dT(ct," <arg>"); + len += 6; + } + else + { + for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i) + { + sout << _dT(ct," <arg") << i+1 << _dT(ct,">"); + len += 7; + if (i+1 > 9) + ++len; + } + } + + sout << _dT(ct," "); + len += 3; + + while (len < max_len) + { + ++len; + sout << _dT(ct," "); + } + + const unsigned long ml = static_cast<unsigned long>(max_len); + // now print the description but make it wrap around nicely if it + // is to long to fit on one line. + if (len <= max_len) + sout << wrap_string(this->element().description(),0,ml); + else + sout << _dT(ct,"\n") << wrap_string(this->element().description(),ml,ml); + } + + // Only print out a generic Options: group name if there is an unnamed option + // present. + if (groups.count(string()) == 1) + out << _dT(ct,"Options:"); + + // Now print everything out + typename std::map<string,std::shared_ptr<ostringstream> >::iterator i; + for (i = groups.begin(); i != groups.end(); ++i) + { + // print the group name if we have one + if (i->first.size() != 0) + { + if (i != groups.begin()) + out << _dT(ct,"\n\n"); + out << i->first << _dT(ct,":"); + } + + // print the options in the group + out << i->second->str(); + } + out << _dT(ct,"\n\n"); + this->reset(); + } + catch (...) + { + this->reset(); + throw; + } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_PRINt_1_ + diff --git a/ml/dlib/dlib/cmd_line_parser/get_option.h b/ml/dlib/dlib/cmd_line_parser/get_option.h new file mode 100644 index 000000000..2c8d1644f --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/get_option.h @@ -0,0 +1,181 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_GET_OPTiON_Hh_ +#define DLIB_GET_OPTiON_Hh_ + +#include "get_option_abstract.h" +#include "../string.h" +#include "../is_kind.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class option_parse_error : public error + { + public: + option_parse_error(const std::string& option_string, const std::string& str): + error(EOPTION_PARSE,"Error parsing argument for option '" + option_string + "', offending string is '" + str + "'.") {} + }; + +// ---------------------------------------------------------------------------------------- + + template <typename config_reader_type, typename T> + T impl_config_reader_get_option ( + const config_reader_type& cr, + const std::string& option_name, + const std::string& full_option_name, + T default_value + ) + { + std::string::size_type pos = option_name.find_first_of("."); + if (pos == std::string::npos) + { + if (cr.is_key_defined(option_name)) + { + try{ return string_cast<T>(cr[option_name]); } + catch (string_cast_error&) { throw option_parse_error(full_option_name, cr[option_name]); } + } + } + else + { + std::string block_name = option_name.substr(0,pos); + if (cr.is_block_defined(block_name)) + { + return impl_config_reader_get_option(cr.block(block_name), + option_name.substr(pos+1), + full_option_name, + default_value); + } + } + + return default_value; + } + +// ---------------------------------------------------------------------------------------- + + template <typename cr_type, typename T> + typename enable_if<is_config_reader<cr_type>,T>::type get_option ( + const cr_type& cr, + const std::string& option_name, + T default_value + ) + { + return impl_config_reader_get_option(cr, option_name, option_name, default_value); + } + +// ---------------------------------------------------------------------------------------- + + template <typename parser_type, typename T> + typename disable_if<is_config_reader<parser_type>,T>::type get_option ( + const parser_type& parser, + const std::string& option_name, + T default_value + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( parser.option_is_defined(option_name) == true && + parser.option(option_name).number_of_arguments() == 1, + "\t T get_option()" + << "\n\t option_name: " << option_name + << "\n\t parser.option_is_defined(option_name): " << parser.option_is_defined(option_name) + << "\n\t parser.option(option_name).number_of_arguments(): " << parser.option(option_name).number_of_arguments() + ); + + if (parser.option(option_name)) + { + try + { + default_value = string_cast<T>(parser.option(option_name).argument()); + } + catch (string_cast_error&) + { + throw option_parse_error(option_name, parser.option(option_name).argument()); + } + } + return default_value; + } + +// ---------------------------------------------------------------------------------------- + + template <typename parser_type, typename cr_type, typename T> + typename disable_if<is_config_reader<parser_type>,T>::type get_option ( + const parser_type& parser, + const cr_type& cr, + const std::string& option_name, + T default_value + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( parser.option_is_defined(option_name) == true && + parser.option(option_name).number_of_arguments() == 1, + "\t T get_option()" + << "\n\t option_name: " << option_name + << "\n\t parser.option_is_defined(option_name): " << parser.option_is_defined(option_name) + << "\n\t parser.option(option_name).number_of_arguments(): " << parser.option(option_name).number_of_arguments() + ); + + if (parser.option(option_name)) + return get_option(parser, option_name, default_value); + else + return get_option(cr, option_name, default_value); + } + +// ---------------------------------------------------------------------------------------- + + template <typename parser_type, typename cr_type, typename T> + typename disable_if<is_config_reader<parser_type>,T>::type get_option ( + const cr_type& cr, + const parser_type& parser, + const std::string& option_name, + T default_value + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( parser.option_is_defined(option_name) == true && + parser.option(option_name).number_of_arguments() == 1, + "\t T get_option()" + << "\n\t option_name: " << option_name + << "\n\t parser.option_is_defined(option_name): " << parser.option_is_defined(option_name) + << "\n\t parser.option(option_name).number_of_arguments(): " << parser.option(option_name).number_of_arguments() + ); + + if (parser.option(option_name)) + return get_option(parser, option_name, default_value); + else + return get_option(cr, option_name, default_value); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template <typename T> + inline std::string get_option ( + const T& cr, + const std::string& option_name, + const char* default_value + ) + { + return get_option(cr, option_name, std::string(default_value)); + } + +// ---------------------------------------------------------------------------------------- + + template <typename T, typename U> + inline std::string get_option ( + const T& parser, + const U& cr, + const std::string& option_name, + const char* default_value + ) + { + return get_option(parser, cr, option_name, std::string(default_value)); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_GET_OPTiON_Hh_ + diff --git a/ml/dlib/dlib/cmd_line_parser/get_option_abstract.h b/ml/dlib/dlib/cmd_line_parser/get_option_abstract.h new file mode 100644 index 000000000..90dc16721 --- /dev/null +++ b/ml/dlib/dlib/cmd_line_parser/get_option_abstract.h @@ -0,0 +1,146 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_GET_OPTiON_ABSTRACT_Hh_ +#ifdef DLIB_GET_OPTiON_ABSTRACT_Hh_ + +#inclue <string> + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class option_parse_error : public error + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the exception thrown by the get_option() functions. It is + thrown when the option string given by a command line parser or + config reader can't be converted into the type T. + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename config_reader_type, + typename T + > + T get_option ( + const config_reader_type& cr, + const std::string& option_name, + T default_value + ); + /*! + requires + - T is a type which can be read from an input stream + - config_reader_type == an implementation of config_reader/config_reader_kernel_abstract.h + ensures + - option_name is used to index into the given config_reader. + - if (cr contains an entry corresponding to option_name) then + - converts the string value in cr corresponding to option_name into + an object of type T and returns it. + - else + - returns default_value + - The scheme for indexing into cr based on option_name is best + understood by looking at a few examples: + - an option name of "name" corresponds to cr["name"] + - an option name of "block1.name" corresponds to cr.block("block1")["name"] + - an option name of "block1.block2.name" corresponds to cr.block("block1").block("block2")["name"] + throws + - option_parse_error + This exception is thrown if we attempt but fail to convert the string value + in cr into an object of type T. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename command_line_parser_type, + typename T + > + T get_option ( + const command_line_parser_type& parser, + const std::string& option_name, + T default_value + ); + /*! + requires + - parser.option_is_defined(option_name) == true + - parser.option(option_name).number_of_arguments() == 1 + - T is a type which can be read from an input stream + - command_line_parser_type == an implementation of cmd_line_parser/cmd_line_parser_kernel_abstract.h + ensures + - if (parser.option(option_name)) then + - converts parser.option(option_name).argument() into an object + of type T and returns it. That is, the string argument to this + command line option is converted into a T and returned. + - else + - returns default_value + throws + - option_parse_error + This exception is thrown if we attempt but fail to convert the string + argument into an object of type T. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename command_line_parser_type, + typename config_reader_type, + typename T + > + T get_option ( + const command_line_parser_type& parser, + const config_reader_type& cr, + const std::string& option_name, + T default_value + ); + /*! + requires + - parser.option_is_defined(option_name) == true + - parser.option(option_name).number_of_arguments() == 1 + - T is a type which can be read from an input stream + - command_line_parser_type == an implementation of cmd_line_parser/cmd_line_parser_kernel_abstract.h + - config_reader_type == an implementation of config_reader/config_reader_kernel_abstract.h + ensures + - if (parser.option(option_name)) then + - returns get_option(parser, option_name, default_value) + - else + - returns get_option(cr, option_name, default_value) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename command_line_parser_type, + typename config_reader_type, + typename T + > + T get_option ( + const config_reader_type& cr, + const command_line_parser_type& parser, + const std::string& option_name, + T default_value + ); + /*! + requires + - parser.option_is_defined(option_name) == true + - parser.option(option_name).number_of_arguments() == 1 + - T is a type which can be read from an input stream + - command_line_parser_type == an implementation of cmd_line_parser/cmd_line_parser_kernel_abstract.h + - config_reader_type == an implementation of config_reader/config_reader_kernel_abstract.h + ensures + - if (parser.option(option_name)) then + - returns get_option(parser, option_name, default_value) + - else + - returns get_option(cr, option_name, default_value) + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_GET_OPTiON_ABSTRACT_Hh_ + + |