summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h')
-rw-r--r--ml/dlib/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h799
1 files changed, 799 insertions, 0 deletions
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_
+