1.1 --- a/.hgignore Sun Mar 16 07:32:43 2008 +0000
1.2 +++ b/.hgignore Mon Mar 17 11:03:35 2008 +0000
1.3 @@ -31,4 +31,5 @@
1.4 ^autom4te.cache/.*
1.5 ^build-aux/.*
1.6 ^objs.*/.*
1.7 -^test/[a-z_]*$
1.8 \ No newline at end of file
1.9 +^test/[a-z_]*$
1.10 +^demo/.*_demo$
2.1 --- a/demo/Makefile.am Sun Mar 16 07:32:43 2008 +0000
2.2 +++ b/demo/Makefile.am Mon Mar 17 11:03:35 2008 +0000
2.3 @@ -3,6 +3,10 @@
2.4
2.5 if WANT_DEMO
2.6
2.7 -noinst_PROGRAMS +=
2.8 +noinst_PROGRAMS += \
2.9 + demo/arg_parser_demo
2.10
2.11 endif WANT_DEMO
2.12 +
2.13 +demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc
2.14 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/demo/arg_parser_demo.cc Mon Mar 17 11:03:35 2008 +0000
3.3 @@ -0,0 +1,82 @@
3.4 +/* -*- C++ -*-
3.5 + *
3.6 + * This file is a part of LEMON, a generic C++ optimization library
3.7 + *
3.8 + * Copyright (C) 2003-2008
3.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
3.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
3.11 + *
3.12 + * Permission to use, modify and distribute this software is granted
3.13 + * provided that this copyright notice appears in all copies. For
3.14 + * precise terms see the accompanying LICENSE file.
3.15 + *
3.16 + * This software is provided "AS IS" with no warranty of any kind,
3.17 + * express or implied, and with no claim as to its suitability for any
3.18 + * purpose.
3.19 + *
3.20 + */
3.21 +
3.22 +///\ingroup demos
3.23 +///\file
3.24 +///\brief Argument parser demo
3.25 +///
3.26 +/// This example shows how the argument parser can be used.
3.27 +///
3.28 +/// \include arg_parser_demo.cc
3.29 +
3.30 +#include <lemon/arg_parser.h>
3.31 +
3.32 +using namespace lemon;
3.33 +int main(int argc, const char **argv)
3.34 +{
3.35 + ArgParser ap(argc,argv);
3.36 + int i;
3.37 + std::string s;
3.38 + double d;
3.39 + bool b,sil;
3.40 + bool g1,g2,g3;
3.41 + ap.refOption("n", "An integer input.", i, true)
3.42 + .refOption("val", "A double input.", d)
3.43 + .synonym("vals","val")
3.44 + .refOption("name", "A string input.", s)
3.45 + .refOption("f", "A switch.", b)
3.46 + .refOption("nohelp", "", sil)
3.47 + .refOption("gra","Choice A",g1)
3.48 + .refOption("grb","Choice B",g2)
3.49 + .refOption("grc","Choice C",g3)
3.50 + .optionGroup("gr","gra")
3.51 + .optionGroup("gr","grb")
3.52 + .optionGroup("gr","grc")
3.53 + .mandatoryGroup("gr")
3.54 + .onlyOneGroup("gr")
3.55 + .other("infile","The input file.")
3.56 + .other("...");
3.57 +
3.58 + ap.parse();
3.59 +
3.60 + std::cout << "Parameters of '" << ap.commandName() << "':\n";
3.61 +
3.62 + if(ap.given("n")) std::cout << " Value of -n: " << i << std::endl;
3.63 + if(ap.given("val")) std::cout << " Value of -val: " << d << std::endl;
3.64 + if(ap.given("name")) std::cout << " Value of -name: " << s << std::endl;
3.65 + if(ap.given("f")) std::cout << " -f is given\n";
3.66 + if(ap.given("nohelp")) std::cout << " Value of -nohelp: " << sil << std::endl;
3.67 + if(ap.given("gra")) std::cout << " -gra is given\n";
3.68 + if(ap.given("grb")) std::cout << " -grb is given\n";
3.69 + if(ap.given("grc")) std::cout << " -grc is given\n";
3.70 +
3.71 + switch(ap.files().size()) {
3.72 + case 0:
3.73 + std::cout << " No file argument was given.\n";
3.74 + break;
3.75 + case 1:
3.76 + std::cout << " 1 file argument was given. It is:\n";
3.77 + break;
3.78 + default:
3.79 + std::cout << " "
3.80 + << ap.files().size() << " file arguments were given. They are:\n";
3.81 + }
3.82 + for(unsigned int i=0;i<ap.files().size();++i)
3.83 + std::cout << " '" << ap.files()[i] << "'\n";
3.84 +
3.85 +}
4.1 --- a/lemon/Makefile.am Sun Mar 16 07:32:43 2008 +0000
4.2 +++ b/lemon/Makefile.am Mon Mar 17 11:03:35 2008 +0000
4.3 @@ -7,6 +7,7 @@
4.4 lib_LTLIBRARIES += lemon/libemon.la
4.5
4.6 lemon_libemon_la_SOURCES = \
4.7 + lemon/arg_parser.cc \
4.8 lemon/base.cc \
4.9 lemon/random.cc
4.10
4.11 @@ -15,6 +16,7 @@
4.12 lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS)
4.13
4.14 lemon_HEADERS += \
4.15 + lemon/arg_parser.h \
4.16 lemon/concept_check.h \
4.17 lemon/dim2.h \
4.18 lemon/error.h \
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/lemon/arg_parser.cc Mon Mar 17 11:03:35 2008 +0000
5.3 @@ -0,0 +1,465 @@
5.4 +/* -*- C++ -*-
5.5 + *
5.6 + * This file is a part of LEMON, a generic C++ optimization library
5.7 + *
5.8 + * Copyright (C) 2003-2008
5.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
5.11 + *
5.12 + * Permission to use, modify and distribute this software is granted
5.13 + * provided that this copyright notice appears in all copies. For
5.14 + * precise terms see the accompanying LICENSE file.
5.15 + *
5.16 + * This software is provided "AS IS" with no warranty of any kind,
5.17 + * express or implied, and with no claim as to its suitability for any
5.18 + * purpose.
5.19 + *
5.20 + */
5.21 +
5.22 +#include <lemon/arg_parser.h>
5.23 +
5.24 +namespace lemon {
5.25 +
5.26 + void ArgParser::_showHelp(void *p)
5.27 + {
5.28 + (static_cast<ArgParser*>(p))->showHelp();
5.29 + exit(1);
5.30 + }
5.31 +
5.32 + ArgParser::ArgParser(int argc, const char **argv) :_argc(argc), _argv(argv),
5.33 + _command_name(argv[0]) {
5.34 + funcOption("-help","Print a short help message",_showHelp,this);
5.35 + synonym("help","-help");
5.36 + synonym("h","-help");
5.37 +
5.38 + }
5.39 +
5.40 + ArgParser::~ArgParser()
5.41 + {
5.42 + for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
5.43 + if(i->second.self_delete)
5.44 + switch(i->second.type) {
5.45 + case BOOL:
5.46 + delete i->second.bool_p;
5.47 + break;
5.48 + case STRING:
5.49 + delete i->second.string_p;
5.50 + break;
5.51 + case DOUBLE:
5.52 + delete i->second.double_p;
5.53 + break;
5.54 + case INTEGER:
5.55 + delete i->second.int_p;
5.56 + break;
5.57 + case UNKNOWN:
5.58 + break;
5.59 + case FUNC:
5.60 + break;
5.61 + }
5.62 + }
5.63 +
5.64 +
5.65 + ArgParser &ArgParser::intOption(const std::string &name,
5.66 + const std::string &help,
5.67 + int value, bool obl)
5.68 + {
5.69 + ParData p;
5.70 + p.int_p=new int(value);
5.71 + p.self_delete=true;
5.72 + p.help=help;
5.73 + p.type=INTEGER;
5.74 + p.mandatory=obl;
5.75 + _opts[name]=p;
5.76 + return *this;
5.77 + }
5.78 +
5.79 + ArgParser &ArgParser::doubleOption(const std::string &name,
5.80 + const std::string &help,
5.81 + double value, bool obl)
5.82 + {
5.83 + ParData p;
5.84 + p.double_p=new double(value);
5.85 + p.self_delete=true;
5.86 + p.help=help;
5.87 + p.type=DOUBLE;
5.88 + p.mandatory=obl;
5.89 + _opts[name]=p;
5.90 + return *this;
5.91 + }
5.92 +
5.93 + ArgParser &ArgParser::boolOption(const std::string &name,
5.94 + const std::string &help,
5.95 + bool value, bool obl)
5.96 + {
5.97 + ParData p;
5.98 + p.bool_p=new bool(value);
5.99 + p.self_delete=true;
5.100 + p.help=help;
5.101 + p.type=BOOL;
5.102 + p.mandatory=obl;
5.103 + _opts[name]=p;
5.104 + return *this;
5.105 + }
5.106 +
5.107 + ArgParser &ArgParser::stringOption(const std::string &name,
5.108 + const std::string &help,
5.109 + std::string value, bool obl)
5.110 + {
5.111 + ParData p;
5.112 + p.string_p=new std::string(value);
5.113 + p.self_delete=true;
5.114 + p.help=help;
5.115 + p.type=STRING;
5.116 + p.mandatory=obl;
5.117 + _opts[name]=p;
5.118 + return *this;
5.119 + }
5.120 +
5.121 + ArgParser &ArgParser::refOption(const std::string &name,
5.122 + const std::string &help,
5.123 + int &ref, bool obl)
5.124 + {
5.125 + ParData p;
5.126 + p.int_p=&ref;
5.127 + p.self_delete=false;
5.128 + p.help=help;
5.129 + p.type=INTEGER;
5.130 + p.mandatory=obl;
5.131 + _opts[name]=p;
5.132 + return *this;
5.133 + }
5.134 +
5.135 + ArgParser &ArgParser::refOption(const std::string &name,
5.136 + const std::string &help,
5.137 + double &ref, bool obl)
5.138 + {
5.139 + ParData p;
5.140 + p.double_p=&ref;
5.141 + p.self_delete=false;
5.142 + p.help=help;
5.143 + p.type=DOUBLE;
5.144 + p.mandatory=obl;
5.145 + _opts[name]=p;
5.146 + return *this;
5.147 + }
5.148 +
5.149 + ArgParser &ArgParser::refOption(const std::string &name,
5.150 + const std::string &help,
5.151 + bool &ref, bool obl)
5.152 + {
5.153 + ParData p;
5.154 + p.bool_p=&ref;
5.155 + p.self_delete=false;
5.156 + p.help=help;
5.157 + p.type=BOOL;
5.158 + p.mandatory=obl;
5.159 + _opts[name]=p;
5.160 +
5.161 + ref = false;
5.162 +
5.163 + return *this;
5.164 + }
5.165 +
5.166 + ArgParser &ArgParser::refOption(const std::string &name,
5.167 + const std::string &help,
5.168 + std::string &ref, bool obl)
5.169 + {
5.170 + ParData p;
5.171 + p.string_p=&ref;
5.172 + p.self_delete=false;
5.173 + p.help=help;
5.174 + p.type=STRING;
5.175 + p.mandatory=obl;
5.176 + _opts[name]=p;
5.177 + return *this;
5.178 + }
5.179 +
5.180 + ArgParser &ArgParser::funcOption(const std::string &name,
5.181 + const std::string &help,
5.182 + void (*func)(void *),void *data)
5.183 + {
5.184 + ParData p;
5.185 + p.func_p.p=func;
5.186 + p.func_p.data=data;
5.187 + p.self_delete=false;
5.188 + p.help=help;
5.189 + p.type=FUNC;
5.190 + p.mandatory=false;
5.191 + _opts[name]=p;
5.192 + return *this;
5.193 + }
5.194 +
5.195 + ArgParser &ArgParser::optionGroup(const std::string &group,
5.196 + const std::string &opt)
5.197 + {
5.198 + Opts::iterator i = _opts.find(opt);
5.199 + LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
5.200 + LEMON_ASSERT(!(i->second.ingroup),
5.201 + "Option already in option group: '"+opt+"'");
5.202 + GroupData &g=_groups[group];
5.203 + g.opts.push_back(opt);
5.204 + i->second.ingroup=true;
5.205 + return *this;
5.206 + }
5.207 +
5.208 + ArgParser &ArgParser::onlyOneGroup(const std::string &group)
5.209 + {
5.210 + GroupData &g=_groups[group];
5.211 + g.only_one=true;
5.212 + return *this;
5.213 + }
5.214 +
5.215 + ArgParser &ArgParser::synonym(const std::string &syn,
5.216 + const std::string &opt)
5.217 + {
5.218 + Opts::iterator o = _opts.find(opt);
5.219 + Opts::iterator s = _opts.find(syn);
5.220 + LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'");
5.221 + LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
5.222 + ParData p;
5.223 + p.help=opt;
5.224 + p.mandatory=false;
5.225 + p.syn=true;
5.226 + _opts[syn]=p;
5.227 + o->second.has_syn=true;
5.228 + return *this;
5.229 + }
5.230 +
5.231 + ArgParser &ArgParser::mandatoryGroup(const std::string &group)
5.232 + {
5.233 + GroupData &g=_groups[group];
5.234 + g.mandatory=true;
5.235 + return *this;
5.236 + }
5.237 +
5.238 + ArgParser &ArgParser::other(const std::string &name,
5.239 + const std::string &help)
5.240 + {
5.241 + _others_help.push_back(OtherArg(name,help));
5.242 + return *this;
5.243 + }
5.244 +
5.245 + void ArgParser::show(std::ostream &os,Opts::iterator i)
5.246 + {
5.247 + os << "-" << i->first;
5.248 + if(i->second.has_syn)
5.249 + for(Opts::iterator j=_opts.begin();j!=_opts.end();++j)
5.250 + if(j->second.syn&&j->second.help==i->first)
5.251 + os << "|-" << j->first;
5.252 + switch(i->second.type) {
5.253 + case STRING:
5.254 + os << " str";
5.255 + break;
5.256 + case INTEGER:
5.257 + os << " int";
5.258 + break;
5.259 + case DOUBLE:
5.260 + os << " num";
5.261 + break;
5.262 + default:
5.263 + break;
5.264 + }
5.265 + }
5.266 +
5.267 + void ArgParser::show(std::ostream &os,Groups::iterator i)
5.268 + {
5.269 + GroupData::Opts::iterator o=i->second.opts.begin();
5.270 + while(o!=i->second.opts.end()) {
5.271 + show(os,_opts.find(*o));
5.272 + ++o;
5.273 + if(o!=i->second.opts.end()) os<<'|';
5.274 + }
5.275 + }
5.276 +
5.277 + void ArgParser::showHelp(Opts::iterator i)
5.278 + {
5.279 + if(i->second.help.size()==0||i->second.syn) return;
5.280 + std::cerr << " ";
5.281 + show(std::cerr,i);
5.282 + std::cerr << std::endl;
5.283 + std::cerr << " " << i->second.help << std::endl;
5.284 + }
5.285 + void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::iterator i)
5.286 + {
5.287 + if(i->help.size()==0) return;
5.288 + std::cerr << " " << i->name << std::endl
5.289 + << " " << i->help << std::endl;
5.290 + }
5.291 +
5.292 + void ArgParser::shortHelp()
5.293 + {
5.294 + const unsigned int LINE_LEN=77;
5.295 + const std::string indent(" ");
5.296 + std::cerr << "Usage:\n " << _command_name;
5.297 + int pos=_command_name.size()+2;
5.298 + for(Groups::iterator g=_groups.begin();g!=_groups.end();++g) {
5.299 + std::ostringstream cstr;
5.300 + cstr << ' ';
5.301 + if(!g->second.mandatory) cstr << '[';
5.302 + show(cstr,g);
5.303 + if(!g->second.mandatory) cstr << ']';
5.304 + if(pos+cstr.str().size()>LINE_LEN) {
5.305 + std::cerr << std::endl << indent;
5.306 + pos=indent.size();
5.307 + }
5.308 + std::cerr << cstr.str();
5.309 + pos+=cstr.str().size();
5.310 + }
5.311 + for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
5.312 + if(!i->second.ingroup&&!i->second.syn) {
5.313 + std::ostringstream cstr;
5.314 + cstr << ' ';
5.315 + if(!i->second.mandatory) cstr << '[';
5.316 + show(cstr,i);
5.317 + if(!i->second.mandatory) cstr << ']';
5.318 + if(pos+cstr.str().size()>LINE_LEN) {
5.319 + std::cerr << std::endl << indent;
5.320 + pos=indent.size();
5.321 + }
5.322 + std::cerr << cstr.str();
5.323 + pos+=cstr.str().size();
5.324 + }
5.325 + for(std::vector<OtherArg>::iterator i=_others_help.begin();
5.326 + i!=_others_help.end();++i)
5.327 + {
5.328 + std::ostringstream cstr;
5.329 + cstr << ' ' << i->name;
5.330 +
5.331 + if(pos+cstr.str().size()>LINE_LEN) {
5.332 + std::cerr << std::endl << indent;
5.333 + pos=indent.size();
5.334 + }
5.335 + std::cerr << cstr.str();
5.336 + pos+=cstr.str().size();
5.337 + }
5.338 + std::cerr << std::endl;
5.339 + }
5.340 +
5.341 + void ArgParser::showHelp()
5.342 + {
5.343 + shortHelp();
5.344 + std::cerr << "Where:\n";
5.345 + for(std::vector<OtherArg>::iterator i=_others_help.begin();
5.346 + i!=_others_help.end();++i) showHelp(i);
5.347 + for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
5.348 + exit(1);
5.349 + }
5.350 +
5.351 +
5.352 + void ArgParser::unknownOpt(std::string arg)
5.353 + {
5.354 + std::cerr << "\nUnknown option: " << arg << "\n";
5.355 + std::cerr << "\nType '" << _command_name <<
5.356 + " --help' to obtain a short summary on the usage.\n\n";
5.357 + exit(1);
5.358 + }
5.359 +
5.360 + void ArgParser::requiresValue(std::string arg, OptType t)
5.361 + {
5.362 + std::cerr << "Argument '" << arg << "' requires a";
5.363 + switch(t) {
5.364 + case STRING:
5.365 + std::cerr << " string";
5.366 + break;
5.367 + case INTEGER:
5.368 + std::cerr << "n integer";
5.369 + break;
5.370 + case DOUBLE:
5.371 + std::cerr << " floating point";
5.372 + break;
5.373 + default:
5.374 + break;
5.375 + }
5.376 + std::cerr << " value\n\n";
5.377 + showHelp();
5.378 + }
5.379 +
5.380 +
5.381 + void ArgParser::checkMandatories()
5.382 + {
5.383 + bool ok=true;
5.384 + for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
5.385 + if(i->second.mandatory&&!i->second.set)
5.386 + {
5.387 + if(ok)
5.388 + std::cerr << _command_name
5.389 + << ": The following mandatory arguments are missing.\n";
5.390 + ok=false;
5.391 + showHelp(i);
5.392 + }
5.393 + for(Groups::iterator i=_groups.begin();i!=_groups.end();++i)
5.394 + if(i->second.mandatory||i->second.only_one)
5.395 + {
5.396 + int set=0;
5.397 + for(GroupData::Opts::iterator o=i->second.opts.begin();
5.398 + o!=i->second.opts.end();++o)
5.399 + if(_opts.find(*o)->second.set) ++set;
5.400 + if(i->second.mandatory&&!set) {
5.401 + std::cerr << _command_name
5.402 + << ": At least one of the following arguments is mandatory.\n";
5.403 + ok=false;
5.404 + for(GroupData::Opts::iterator o=i->second.opts.begin();
5.405 + o!=i->second.opts.end();++o)
5.406 + showHelp(_opts.find(*o));
5.407 + }
5.408 + if(i->second.only_one&&set>1) {
5.409 + std::cerr << _command_name
5.410 + << ": At most one of the following arguments can be given.\n";
5.411 + ok=false;
5.412 + for(GroupData::Opts::iterator o=i->second.opts.begin();
5.413 + o!=i->second.opts.end();++o)
5.414 + showHelp(_opts.find(*o));
5.415 + }
5.416 + }
5.417 + if(!ok) {
5.418 + std::cerr << "\nType '" << _command_name <<
5.419 + " --help' to obtain a short summary on the usage.\n\n";
5.420 + exit(1);
5.421 + }
5.422 + }
5.423 +
5.424 + ArgParser &ArgParser::parse()
5.425 + {
5.426 + for(int ar=1; ar<_argc; ++ar) {
5.427 + std::string arg(_argv[ar]);
5.428 + if (arg[0] != '-' || arg.size() == 1) {
5.429 + _file_args.push_back(arg);
5.430 + }
5.431 + else {
5.432 + Opts::iterator i = _opts.find(arg.substr(1));
5.433 + if(i==_opts.end()) unknownOpt(arg);
5.434 + else {
5.435 + if(i->second.syn) i=_opts.find(i->second.help);
5.436 + ParData &p(i->second);
5.437 + if (p.type==BOOL) *p.bool_p=true;
5.438 + else if (p.type==FUNC) p.func_p.p(p.func_p.data);
5.439 + else if(++ar==_argc) requiresValue(arg, p.type);
5.440 + else {
5.441 + std::string val(_argv[ar]);
5.442 + std::istringstream vals(val);
5.443 + switch(p.type) {
5.444 + case STRING:
5.445 + *p.string_p=val;
5.446 + break;
5.447 + case INTEGER:
5.448 + vals >> *p.int_p;
5.449 + break;
5.450 + case DOUBLE:
5.451 + vals >> *p.double_p;
5.452 + break;
5.453 + default:
5.454 + break;
5.455 + }
5.456 + if(p.type!=STRING&&(!vals||!vals.eof()))
5.457 + requiresValue(arg, p.type);
5.458 + }
5.459 + p.set = true;
5.460 + }
5.461 + }
5.462 + }
5.463 + checkMandatories();
5.464 +
5.465 + return *this;
5.466 + }
5.467 +
5.468 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/lemon/arg_parser.h Mon Mar 17 11:03:35 2008 +0000
6.3 @@ -0,0 +1,369 @@
6.4 +/* -*- C++ -*-
6.5 + *
6.6 + * This file is a part of LEMON, a generic C++ optimization library
6.7 + *
6.8 + * Copyright (C) 2003-2008
6.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
6.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
6.11 + *
6.12 + * Permission to use, modify and distribute this software is granted
6.13 + * provided that this copyright notice appears in all copies. For
6.14 + * precise terms see the accompanying LICENSE file.
6.15 + *
6.16 + * This software is provided "AS IS" with no warranty of any kind,
6.17 + * express or implied, and with no claim as to its suitability for any
6.18 + * purpose.
6.19 + *
6.20 + */
6.21 +
6.22 +#ifndef LEMON_ARG_PARSER
6.23 +#define LEMON_ARG_PARSER
6.24 +
6.25 +#include <vector>
6.26 +#include <map>
6.27 +#include <list>
6.28 +#include <string>
6.29 +#include <iostream>
6.30 +#include <sstream>
6.31 +#include <algorithm>
6.32 +#include <lemon/error.h>
6.33 +
6.34 +///\ingroup misc
6.35 +///\file
6.36 +///\brief A tool to parse command line arguments.
6.37 +
6.38 +namespace lemon {
6.39 +
6.40 + ///Command line arguments parser
6.41 +
6.42 + ///\ingroup misc
6.43 + ///Command line arguments parser.
6.44 + ///
6.45 + ///For a complete example see the \ref arg_parser_demo.cc demo file.
6.46 + class ArgParser {
6.47 +
6.48 + static void _showHelp(void *p);
6.49 + protected:
6.50 +
6.51 + int _argc;
6.52 + const char **_argv;
6.53 +
6.54 + enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
6.55 +
6.56 + class ParData {
6.57 + public:
6.58 + union {
6.59 + bool *bool_p;
6.60 + int *int_p;
6.61 + double *double_p;
6.62 + std::string *string_p;
6.63 + struct {
6.64 + void (*p)(void *);
6.65 + void *data;
6.66 + } func_p;
6.67 +
6.68 + };
6.69 + std::string help;
6.70 + bool mandatory;
6.71 + OptType type;
6.72 + bool set;
6.73 + bool ingroup;
6.74 + bool has_syn;
6.75 + bool syn;
6.76 + bool self_delete;
6.77 + ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
6.78 + has_syn(false), syn(false), self_delete(false) {}
6.79 + };
6.80 +
6.81 + typedef std::map<std::string,ParData> Opts;
6.82 + Opts _opts;
6.83 +
6.84 + class GroupData
6.85 + {
6.86 + public:
6.87 + typedef std::list<std::string> Opts;
6.88 + Opts opts;
6.89 + bool only_one;
6.90 + bool mandatory;
6.91 + GroupData() :only_one(false), mandatory(false) {}
6.92 + };
6.93 +
6.94 + typedef std::map<std::string,GroupData> Groups;
6.95 + Groups _groups;
6.96 +
6.97 + struct OtherArg
6.98 + {
6.99 + std::string name;
6.100 + std::string help;
6.101 + OtherArg(std::string n, std::string h) :name(n), help(h) {}
6.102 +
6.103 + };
6.104 +
6.105 + std::vector<OtherArg> _others_help;
6.106 + std::vector<std::string> _file_args;
6.107 + std::string _command_name;
6.108 +
6.109 +
6.110 + private:
6.111 + //Bind a function to an option.
6.112 +
6.113 + //\param name The name of the option. The leading '-' must be omitted.
6.114 + //\param help A help string.
6.115 + //\retval func The function to be called when the option is given. It
6.116 + // must be of type "void f(void *)"
6.117 + //\param data Data to be passed to \c func
6.118 + ArgParser &funcOption(const std::string &name,
6.119 + const std::string &help,
6.120 + void (*func)(void *),void *data);
6.121 +
6.122 + public:
6.123 +
6.124 + ///\e
6.125 + ArgParser(int argc, const char **argv);
6.126 +
6.127 + ~ArgParser();
6.128 +
6.129 + ///Add a new integer type option
6.130 +
6.131 + ///\param name The name of the option. The leading '-' must be omitted.
6.132 + ///\param help A help string.
6.133 + ///\retval value The value of the argument will be written to this variable.
6.134 + ///\param obl Indicate if the option is mandatory.
6.135 + ArgParser &intOption(const std::string &name,
6.136 + const std::string &help,
6.137 + int value=0, bool obl=false);
6.138 +
6.139 + ///Add a new floating point type option
6.140 +
6.141 + ///\param name The name of the option. The leading '-' must be omitted.
6.142 + ///\param help A help string.
6.143 + ///\retval value The value of the argument will be written to this variable.
6.144 + ///\param obl Indicate if the option is mandatory.
6.145 + ArgParser &doubleOption(const std::string &name,
6.146 + const std::string &help,
6.147 + double value=0, bool obl=false);
6.148 +
6.149 + ///Add a new bool type option
6.150 +
6.151 + ///\param name The name of the option. The leading '-' must be omitted.
6.152 + ///\param help A help string.
6.153 + ///\retval value The value of the argument will be written to this variable.
6.154 + ///\param obl Indicate if the option is mandatory.
6.155 + ////\note A mandatory bool obtion is of very little use.)
6.156 + ArgParser &boolOption(const std::string &name,
6.157 + const std::string &help,
6.158 + bool value=false, bool obl=false);
6.159 +
6.160 + ///Add a new string type option
6.161 +
6.162 + ///\param name The name of the option. The leading '-' must be omitted.
6.163 + ///\param help A help string.
6.164 + ///\retval value The value of the argument will be written to this variable.
6.165 + ///\param obl Indicate if the option is mandatory.
6.166 + ArgParser &stringOption(const std::string &name,
6.167 + const std::string &help,
6.168 + std::string value="", bool obl=false);
6.169 +
6.170 + ///\name Options with external storage
6.171 + ///Using this functions, the value of the option will be directly written
6.172 + ///into a variable once the option appears in the command line.
6.173 +
6.174 + ///@{
6.175 +
6.176 + ///Add a new integer type option with a storage reference
6.177 +
6.178 + ///\param name The name of the option. The leading '-' must be omitted.
6.179 + ///\param help A help string.
6.180 + ///\retval ref The value of the argument will be written to this variable.
6.181 + ///\param obl Indicate if the option is mandatory.
6.182 + ArgParser &refOption(const std::string &name,
6.183 + const std::string &help,
6.184 + int &ref, bool obl=false);
6.185 +
6.186 + ///Add a new floating type option with a storage reference
6.187 +
6.188 + ///\param name The name of the option. The leading '-' must be omitted.
6.189 + ///\param help A help string.
6.190 + ///\retval ref The value of the argument will be written to this variable.
6.191 + ///\param obl Indicate if the option is mandatory.
6.192 + ArgParser &refOption(const std::string &name,
6.193 + const std::string &help,
6.194 + double &ref, bool obl=false);
6.195 +
6.196 + ///Add a new bool type option with a storage reference
6.197 +
6.198 + ///\param name The name of the option. The leading '-' must be omitted.
6.199 + ///\param help A help string.
6.200 + ///\retval ref The value of the argument will be written to this variable.
6.201 + ///\param obl Indicate if the option is mandatory.
6.202 + ////\note A mandatory bool obtion is of very little use.)
6.203 + ArgParser &refOption(const std::string &name,
6.204 + const std::string &help,
6.205 + bool &ref, bool obl=false);
6.206 +
6.207 + ///Add a new string type option with a storage reference
6.208 +
6.209 + ///\param name The name of the option. The leading '-' must be omitted.
6.210 + ///\param help A help string.
6.211 + ///\retval ref The value of the argument will be written to this variable.
6.212 + ///\param obl Indicate if the option is mandatory.
6.213 + ArgParser &refOption(const std::string &name,
6.214 + const std::string &help,
6.215 + std::string &ref, bool obl=false);
6.216 +
6.217 + ///@}
6.218 +
6.219 + ///\name Option Groups and Synonyms
6.220 + ///
6.221 +
6.222 + ///@{
6.223 +
6.224 + ///Boundle some options into a group
6.225 +
6.226 + /// You can group some option by calling this function repeatedly for each
6.227 + /// option to be grouped with the same groupname.
6.228 + ///\param group The group name.
6.229 + ///\param opt The option name.
6.230 + ArgParser &optionGroup(const std::string &group,
6.231 + const std::string &opt);
6.232 +
6.233 + ///Make the members of a group exclusive
6.234 +
6.235 + ///If you call this function for a group, than at most one of them can be
6.236 + ///given at the same time
6.237 + ArgParser &onlyOneGroup(const std::string &group);
6.238 +
6.239 + ///Make a group mandatory
6.240 +
6.241 + ///Using this function, at least one of the members of \c group
6.242 + ///must be given.
6.243 + ArgParser &mandatoryGroup(const std::string &group);
6.244 +
6.245 + ///Create synonym to an option
6.246 +
6.247 + ///With this function you can create a synonym \c syn of the
6.248 + ///option \c opt.
6.249 + ArgParser &synonym(const std::string &syn,
6.250 + const std::string &opt);
6.251 +
6.252 + ///@}
6.253 +
6.254 + ///Give help string for non-parsed arguments.
6.255 +
6.256 + ///With this function you can give help string for non-parsed arguments.
6.257 + ///The parameter \c name will be printed in the short usage line, while
6.258 + ///\c help gives a more detailed description.
6.259 + ArgParser &other(const std::string &name,
6.260 + const std::string &help="");
6.261 +
6.262 + ///Give back the non-option type arguments.
6.263 +
6.264 + ///Give back a reference to a vector consisting of the program arguments
6.265 + ///not starting with a '-' character.
6.266 + std::vector<std::string> &files() { return _file_args; }
6.267 +
6.268 + ///Give back the command name (the 0th argument)
6.269 + const std::string &commandName() { return _command_name; }
6.270 +
6.271 + void show(std::ostream &os,Opts::iterator i);
6.272 + void show(std::ostream &os,Groups::iterator i);
6.273 + void showHelp(Opts::iterator i);
6.274 + void showHelp(std::vector<OtherArg>::iterator i);
6.275 + void shortHelp();
6.276 + void showHelp();
6.277 +
6.278 + void unknownOpt(std::string arg);
6.279 +
6.280 + void requiresValue(std::string arg, OptType t);
6.281 + void checkMandatories();
6.282 +
6.283 + ///Start the parsing process
6.284 + ArgParser &parse();
6.285 +
6.286 + /// Synonym for parse()
6.287 + ArgParser &run()
6.288 + {
6.289 + return parse();
6.290 + }
6.291 +
6.292 + ///Check if an opion has been given to the command.
6.293 + bool given(std::string op)
6.294 + {
6.295 + Opts::iterator i = _opts.find(op);
6.296 + return i!=_opts.end()?i->second.set:false;
6.297 + }
6.298 +
6.299 +
6.300 + ///Magic type for operator[]
6.301 +
6.302 + ///This is the type of the return value of ArgParser::operator[]().
6.303 + ///It automatically converts to \c int, \c double, \c bool or
6.304 + ///\c std::string if the type of the option matches, otherwise it
6.305 + ///throws an exception (i.e. it performs runtime type checking).
6.306 + class RefType
6.307 + {
6.308 + ArgParser &_parser;
6.309 + std::string _name;
6.310 + public:
6.311 + ///\e
6.312 + RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
6.313 + ///\e
6.314 + operator bool()
6.315 + {
6.316 + Opts::iterator i = _parser._opts.find(_name);
6.317 + LEMON_ASSERT(i==_parser._opts.end(),
6.318 + std::string()+"Unkown option: '"+_name+"'");
6.319 + LEMON_ASSERT(i->second.type!=ArgParser::BOOL,
6.320 + std::string()+"'"+_name+"' is a bool option");
6.321 + return *(i->second.bool_p);
6.322 + }
6.323 + ///\e
6.324 + operator std::string()
6.325 + {
6.326 + Opts::iterator i = _parser._opts.find(_name);
6.327 + LEMON_ASSERT(i==_parser._opts.end(),
6.328 + std::string()+"Unkown option: '"+_name+"'");
6.329 + LEMON_ASSERT(i->second.type!=ArgParser::STRING,
6.330 + std::string()+"'"+_name+"' is a string option");
6.331 + return *(i->second.string_p);
6.332 + }
6.333 + ///\e
6.334 + operator double()
6.335 + {
6.336 + Opts::iterator i = _parser._opts.find(_name);
6.337 + LEMON_ASSERT(i==_parser._opts.end(),
6.338 + std::string()+"Unkown option: '"+_name+"'");
6.339 + LEMON_ASSERT(i->second.type!=ArgParser::DOUBLE &&
6.340 + i->second.type!=ArgParser::INTEGER,
6.341 + std::string()+"'"+_name+"' is a floating point option");
6.342 + return i->second.type==ArgParser::DOUBLE ?
6.343 + *(i->second.double_p) : *(i->second.int_p);
6.344 + }
6.345 + ///\e
6.346 + operator int()
6.347 + {
6.348 + Opts::iterator i = _parser._opts.find(_name);
6.349 + LEMON_ASSERT(i==_parser._opts.end(),
6.350 + std::string()+"Unkown option: '"+_name+"'");
6.351 + LEMON_ASSERT(i->second.type!=ArgParser::INTEGER,
6.352 + std::string()+"'"+_name+"' is an integer option");
6.353 + return *(i->second.int_p);
6.354 + }
6.355 +
6.356 + };
6.357 +
6.358 + ///Give back the value of an option
6.359 +
6.360 + ///Give back the value of an option.
6.361 + ///\sa RefType
6.362 + RefType operator[](const std::string &n)
6.363 + {
6.364 + return RefType(*this, n);
6.365 + }
6.366 +
6.367 + };
6.368 +}
6.369 +
6.370 +
6.371 +
6.372 +#endif // LEMON_MAIN_PARAMS